LESSON 30分

ストーリー

田中VPoE
音声認識(STT)の次は、音声合成(TTS: Text-to-Speech)だ。テキストから自然な音声を生成する技術を学ぼう
あなた
最近のTTSはかなり自然になりましたよね。社内通知の自動音声化やeラーニングのナレーション生成に使えそうです
田中VPoE
その通り。OpenAIのTTSやElevenLabsなど、APIベースで高品質な音声が生成できるようになった。感情表現や多言語対応まで進んでいる
あなた
声のクローニングもできると聞きました。倫理面も含めて学びたいです

音声合成(TTS)の概要

主要なTTSサービス

サービス提供元特徴コスト目安
OpenAI TTSOpenAI6種類の声、自然な抑揚$15/100万文字
ElevenLabsElevenLabs声のクローニング、感情制御$5/月〜
Google Cloud TTSGoogleWaveNet、多言語、SSML対応$4/100万文字
Amazon PollyAWSNTTS(ニューラル)、AWS統合$4/100万文字
Azure SpeechMicrosoftカスタムニューラル音声$15/100万文字
VOICEVOXOSS日本語特化、無料、商用利用可無料

TTS技術の進化

第1世代: 規則合成         → 機械的で不自然
第2世代: 統計的パラメトリック → やや自然だが平坦
第3世代: ニューラルTTS      → 人間に近い自然さ
第4世代: ゼロショットTTS    → 数秒のサンプルで声を再現

OpenAI TTSの実装

基本的な音声生成

from openai import OpenAI
from pathlib import Path

client = OpenAI()

def text_to_speech(
    text: str,
    voice: str = "alloy",
    model: str = "tts-1-hd",
    output_path: str = "output.mp3"
) -> str:
    """テキストから音声を生成"""
    # 利用可能な声: alloy, echo, fable, onyx, nova, shimmer
    response = client.audio.speech.create(
        model=model,       # tts-1(高速)or tts-1-hd(高品質)
        voice=voice,
        input=text,
        speed=1.0          # 0.25〜4.0
    )

    response.stream_to_file(output_path)
    return output_path


# 使用例: 通知メッセージの音声化
text_to_speech(
    text="本日の売上レポートです。売上合計は1億2千万円で、前日比105%でした。",
    voice="nova",
    output_path="daily_report.mp3"
)

長文テキストのバッチ処理

def batch_tts(
    texts: list[str],
    voice: str = "alloy",
    output_dir: str = "audio_output"
) -> list[str]:
    """複数テキストの一括音声生成"""
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    output_files = []

    for i, text in enumerate(texts):
        # OpenAI TTSの入力上限は4096文字
        if len(text) > 4096:
            chunks = split_text_for_tts(text, max_chars=4000)
            chunk_files = []
            for j, chunk in enumerate(chunks):
                path = f"{output_dir}/part_{i}_{j}.mp3"
                text_to_speech(chunk, voice=voice, output_path=path)
                chunk_files.append(path)
            # チャンクを結合
            merged_path = f"{output_dir}/merged_{i}.mp3"
            merge_audio_files(chunk_files, merged_path)
            output_files.append(merged_path)
        else:
            path = f"{output_dir}/audio_{i}.mp3"
            text_to_speech(text, voice=voice, output_path=path)
            output_files.append(path)

    return output_files


def split_text_for_tts(text: str, max_chars: int = 4000) -> list[str]:
    """テキストを文単位で分割"""
    sentences = text.replace("。", "。\n").split("\n")
    chunks = []
    current_chunk = ""

    for sentence in sentences:
        if len(current_chunk) + len(sentence) > max_chars:
            if current_chunk:
                chunks.append(current_chunk.strip())
            current_chunk = sentence
        else:
            current_chunk += sentence

    if current_chunk.strip():
        chunks.append(current_chunk.strip())

    return chunks

Google Cloud TTSの実装

SSMLを使った高度な音声制御

from google.cloud import texttospeech

def synthesize_with_ssml(
    ssml_text: str,
    output_path: str = "output.wav",
    language_code: str = "ja-JP",
    voice_name: str = "ja-JP-Neural2-B"
) -> str:
    """SSMLで音声を生成(ポーズ、強調、速度制御)"""
    client = texttospeech.TextToSpeechClient()

    input_text = texttospeech.SynthesisInput(ssml=ssml_text)

    voice = texttospeech.VoiceSelectionParams(
        language_code=language_code,
        name=voice_name
    )

    audio_config = texttospeech.AudioConfig(
        audio_encoding=texttospeech.AudioEncoding.LINEAR16,
        speaking_rate=1.0,
        pitch=0.0
    )

    response = client.synthesize_speech(
        input=input_text,
        voice=voice,
        audio_config=audio_config
    )

    with open(output_path, "wb") as out:
        out.write(response.audio_content)
    return output_path


# SSML例: 自然なナレーション
ssml = """
<speak>
    <p>
        <s>本日の会議のアジェンダをお伝えします。</s>
        <break time="500ms"/>
        <s>第一に、<emphasis level="strong">売上報告</emphasis>です。</s>
        <s>第二に、新商品の企画について議論します。</s>
        <break time="300ms"/>
        <s>それでは始めましょう。</s>
    </p>
</speak>
"""
synthesize_with_ssml(ssml)

業務活用パターン

パターン1: eラーニングナレーション自動生成

def generate_elearning_audio(
    script: list[dict],
    voice: str = "nova"
) -> list[str]:
    """eラーニング用のナレーション音声を自動生成

    script例:
    [
        {"slide": 1, "text": "本講座では..."},
        {"slide": 2, "text": "最初に..."},
    ]
    """
    audio_files = []
    for item in script:
        path = f"slide_{item['slide']}.mp3"
        text_to_speech(
            text=item["text"],
            voice=voice,
            output_path=path
        )
        audio_files.append({
            "slide": item["slide"],
            "audio": path,
            "text": item["text"]
        })
    return audio_files

パターン2: 多言語カスタマーサポート

def generate_multilingual_announcement(
    message_ja: str,
    target_languages: list[str] = ["en", "zh", "ko"]
) -> dict[str, str]:
    """日本語メッセージを多言語音声に変換"""
    results = {"ja": None}

    # 日本語音声生成
    results["ja"] = text_to_speech(message_ja, voice="nova", output_path="msg_ja.mp3")

    # 翻訳 + 音声生成
    for lang in target_languages:
        translated = translate_text(message_ja, target_lang=lang)
        voice = select_voice_for_language(lang)
        path = f"msg_{lang}.mp3"
        results[lang] = text_to_speech(translated, voice=voice, output_path=path)

    return results

パターン3: レポートの音声化

日次レポート(テキスト)


[要約生成] → LLMで3分以内に収まる要約を生成


[TTS] → 自然な音声に変換


[配信] → 社内ポッドキャストとして配信

倫理とガイドライン

音声AI利用時の注意点

リスク説明対策
ディープフェイク本人の声を無断で複製本人の同意を必須にする
なりすまし詐欺経営者の声を模倣した詐欺音声認証の多要素化
著作権侵害声優・ナレーターの権利侵害ライセンス確認
偽情報拡散AIナレーションによる偽ニュースAI生成の明示

社内ガイドライン(推奨)

1. AI生成音声であることを明示する
2. 個人の声のクローニングには書面での同意を取得する
3. 外部公開する音声には「AI Generated」の注記を含める
4. 声優・ナレーターの権利を尊重する
5. 定期的にガイドラインを見直す

まとめ

技術概要推奨ツール
基本TTSテキストから音声生成OpenAI TTS, Google Cloud TTS
SSMLポーズ・強調・速度の制御Google Cloud TTS, Azure Speech
声のクローニングサンプルから声を再現ElevenLabs
日本語特化高品質日本語TTSVOICEVOX, Google Cloud TTS

チェックリスト

  • 主要なTTSサービスの特徴とコストを比較できる
  • OpenAI TTSを使った音声生成を実装できる
  • SSMLによる高度な音声制御を理解した
  • 業務活用パターン(eラーニング、多言語対応、レポート音声化)を把握した
  • 音声AI利用時の倫理的配慮を説明できる

次のステップへ

次は動画分析の技術を学び、映像データからの情報抽出方法を習得します。


推定読了時間: 30分