活用シーンとソリューション

ショート動画の AI ナレーションを自社サーバーで作成:Kokoro 音声合成(日本語・中国語・英語ほか)

6 ステップ 13 分で読めます 64 回閲覧 0
目次

TikTok、Reels、YouTube ショートや EC モールの商品ページに載せるショート動画にはナレーションが欠かせませんが、台本を毎回自分で録音するのは手間がかかります。オンラインの音声合成サービスは文字数に応じて課金されるうえ、台本をアップロードする必要があります。Kokoro はオープンウェイトの音声合成モデルで、自然な声で読み上げられ、一般的な CPU サーバーでも動作するほど軽量です。この記事では、Kokoro のインストール、ボイスの選び方、台本ファイルから WAV のナレーション音声とタイミングの合った SRT 字幕を作成する方法、中国語ナレーションに含まれる英単語の扱い、アップロード用の音声の仕上げ方を解説します。

TikTok や YouTube をはじめ多くのプラットフォームでは、リアルな AI 生成コンテンツや合成コンテンツにラベルを付けることがクリエイターに求められています。各プラットフォームの最新のルールに従ってください。この記事では Kokoro の内蔵ボイスを使用します。本人の同意なく実在の人物の声を模倣しないでください。

ステップ1:Kokoro をインストール

# Debian 12 / Ubuntu 22.04 or 24.04 (Kokoro needs Python 3.10 to 3.12)
apt install -y python3-venv espeak-ng ffmpeg
python3 -m venv /opt/tts
/opt/tts/bin/pip install --upgrade pip
/opt/tts/bin/pip install torch --index-url https://download.pytorch.org/whl/cpu   # CPU-only build, much smaller
/opt/tts/bin/pip install kokoro soundfile "misaki[zh]"

# Japanese voices additionally need:
/opt/tts/bin/pip install "misaki[ja]"
/opt/tts/bin/python -m unidic download          # Japanese dictionary, about 500 MB

システムの Python が 3.13 以降の場合(Debian 13 など)は、代わりに uv で Python 3.12 の環境を作成します。--seed を付けると pip も入るため、以降のコマンドはそのまま使えます。

curl -LsSf https://astral.sh/uv/install.sh | sh
~/.local/bin/uv venv --seed -p 3.12 /opt/tts
/opt/tts/bin/pip install torch --index-url https://download.pytorch.org/whl/cpu
/opt/tts/bin/pip install kokoro soundfile "misaki[zh]"

モデル(約 330 MB)と各ボイスは、初回使用時に Hugging Face からダウンロードされます。

ステップ2:言語とボイスを選ぶ

コード言語ボイスの例
aアメリカ英語af_heart, af_bella, am_michael, am_adam
bイギリス英語bf_emma, bf_isabella, bm_george, bm_daniel
z標準中国語zf_xiaobei, zf_xiaoni, zm_yunxi, zm_yunjian
j日本語jf_alpha, jf_nezumi, jm_kumo
eスペイン語ef_dora, em_alex
fフランス語ff_siwis
iイタリア語if_sara, im_nicola
pブラジルポルトガル語pf_dora, pm_alex
hヒンディー語hf_alpha, hm_omega

ボイス名の 1 文字目は言語を、2 文字目は女性(f)か男性(m)かを表します。Kokoro は韓国語、ロシア語、タイ語、ベトナム語、マレー語には対応していません。これらの市場向けには字幕を使うか、別の音声合成エンジンを利用してください。

ステップ3:ナレーション作成スクリプトを用意

cat > /opt/tts/tts.py <<'EOF2'
import os, sys
import numpy as np
import soundfile as sf
from kokoro import KPipeline

LANG = os.environ.get("TTS_LANG", "a")            # a = US English, z = Mandarin Chinese, j = Japanese ...
VOICE = os.environ.get("TTS_VOICE", "af_heart")
SPEED = float(os.environ.get("TTS_SPEED", "1.0"))
PAUSE = float(os.environ.get("TTS_PAUSE", "0.3"))  # seconds of silence after each line
RATE = 24000

def ts(t):
    ms = int(round(t * 1000))
    h, ms = divmod(ms, 3600000)
    m, ms = divmod(ms, 60000)
    s, ms = divmod(ms, 1000)
    return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"

pipeline = KPipeline(lang_code=LANG, repo_id="hexgrad/Kokoro-82M")
for path in sys.argv[1:]:
    lines = [l.strip() for l in open(path, encoding="utf-8") if l.strip()]
    parts, srt, pos = [], [], 0
    for i, line in enumerate(lines, 1):
        show, _, say = line.partition("|")            # "subtitle text|text to speak" (optional)
        chunks = [np.asarray(a, dtype=np.float32) for _, _, a in pipeline(say or show, voice=VOICE, speed=SPEED)]
        audio = np.concatenate(chunks) if chunks else np.zeros(RATE // 2, dtype=np.float32)
        srt.append(f"{i}\n{ts(pos / RATE)} --> {ts((pos + len(audio)) / RATE)}\n{show.strip()}\n")
        silence = np.zeros(int(PAUSE * RATE), dtype=np.float32)
        parts += [audio, silence]
        pos += len(audio) + len(silence)
    base = os.path.splitext(path)[0]
    sf.write(base + ".wav", np.concatenate(parts), RATE)
    with open(base + ".srt", "w", encoding="utf-8") as f:
        f.write("\n".join(srt))
    print(f"{path}: {len(lines)} lines, {pos / RATE:.1f}s -> {base}.wav, {base}.srt", flush=True)
EOF2

テキストファイルの 1 行が、ナレーションの 1 文と字幕 1 つになります。スクリプトはテキストファイルと同じ場所に、WAV ファイルと、タイミングが完全に一致する SRT ファイルを書き出します。言語、ボイス、話速、行間のポーズは環境変数で指定します。

ステップ4:最初のナレーションを生成

mkdir -p /data/voice && cd /data/voice
cat > demo.txt <<'EOF2'
这款竹制笔记本支架有六档高度可调。
支持 USB-C 接口和 iPhone。|支持 优艾斯比西 接口和爱疯。
折叠后可以放进背包,重量只有一点一公斤。
EOF2
TTS_LANG=z TTS_VOICE=zf_xiaobei /opt/tts/bin/python /opt/tts/tts.py demo.txt

# English:  TTS_LANG=a TTS_VOICE=af_heart     Japanese:  TTS_LANG=j TTS_VOICE=jf_alpha

当社のテストでは、中国語ボイスは 39.9 や 2026 などの数字を正しく読み上げましたが、USB-C や iPhone のようなラテン文字の単語は読み飛ばしたり、不明瞭に発音したりしました。こうした行では、上の 2 行目のように、まず字幕用のテキストを書き、続けて | と読み上げ用のテキストを書きます。字幕には正しい製品名が表示され、音声は発音どおりに書いた表記を読み上げます。日本語でもブランド名に同じ方法が使えます(| の後にカタカナで書きます)。

ステップ5:最適なボイスと話速を見つける

# Render the same text with several voices to compare them
for v in zf_xiaobei zf_xiaoni zm_yunxi zm_yunjian; do
  cp demo.txt "try-$v.txt"
  TTS_LANG=z TTS_VOICE=$v /opt/tts/bin/python /opt/tts/tts.py "try-$v.txt"
done

# Slightly faster speech and shorter pauses, typical for short videos
TTS_LANG=z TTS_VOICE=zm_yunxi TTS_SPEED=1.1 TTS_PAUSE=0.2 /opt/tts/bin/python /opt/tts/tts.py demo.txt

WAV ファイルをダウンロードし、多くの視聴者と同じようにスマートフォンで聴いてみてください。長く複雑な文よりも、自然な位置に読点を入れた短い文のほうがずっと聞きやすくなります。

ステップ6:アップロード用に音声を仕上げる

# Normalise loudness to about -14 LUFS (common for short-video platforms) and make an MP3
ffmpeg -i demo.wav -af loudnorm=I=-14:TP=-1.5 -ar 48000 -ac 2 demo-final.wav
ffmpeg -i demo-final.wav -c:a libmp3lame -q:a 2 demo.mp3

音声と demo.srt を動画編集ソフトに読み込みます。商品紹介ショート動画の自動作成で紹介しているように、写真・音声・字幕から動画全体をスクリプトで作成することもできます。既存の動画を別の言語にする場合は、AI による動画の多言語吹き替えを参照してください。

よくある質問

CPU サーバーでの処理速度は?

Kokoro は小さなモデルです。最近のマルチコアサーバーであれば、通常は実時間より速く音声を生成できるため、モデルの読み込み後は 1 分のナレーションが 1 分よりかなり短い時間で完成します。速度は CPU とテキストの長さによって変わります。

自分の声をクローンできますか?

Kokoro で使えるのは内蔵ボイスのみです。ボイスクローンには別のモデルが必要で、通常は GPU も必要になります。声のクローンは必ず話者本人の明確な同意を得たうえで行い、合成コンテンツに関する各プラットフォームのルールに従ってください。

ボイスは商用利用できますか?

執筆時点では、Kokoro のコードとモデルは商用利用が認められている Apache 2.0 ライセンスで公開されています。利用する前にプロジェクトページで最新のライセンスを確認し、AI 生成コンテンツに関する各プラットフォームのルールに従ってください。

英語のテキストで espeak-ng のエラーが出る

英語をはじめいくつかの言語では、辞書にない単語の読みに espeak-ng を使います。ステップ1の espeak-ng パッケージがインストールされていることを確認してから、スクリプトを再実行してください。

上記の手順で解決しない場合は、サポートチケットを送信して IMIDC の 24 時間 365 日対応テクニカルサポートへご連絡ください。サーバー IP、OS と Python のバージョン、実行したコマンド、エラー全文を添えていただくと、より迅速に調査できます。

この回答はお役に立ちましたか?

関連チュートリアル