ナレーション
npm run tts は src/timeline.ts の各行を public/audio/<lang>/<key>.wav に音声化し、
Cartesiaの単語タイムスタンプを <key>.words.json に保存し、src/audio.generated.ts を実際の
行長で書き換えます。行はエンジン、音声、モデル、速度、テキストごとにキャッシュされます。新規または編集された行のみが再音声化されます。
npm run tts -- en または -- es で1つの言語に限定できます。
Cartesiaの設定
- 設定は
video.config.mjs(tts)にあります:モデルsonic-3.6-2026-08-27、速度1。 - 英語音声:
5568a7df-e5ab-4442-9fae-2e9ba1b15ad8(en-GB)。 CARTESIA_API_KEYは次の順序で検索されます:- 環境変数;
- 動画フォルダ内の
.env(gitignore対象;.env.exampleをコピー); ~/Documents/repos/.env。
- キーを印刷したり、エコーしたり、コミットしたりしないでください。キーが存在するかどうかを表示せずに確認します。例:
test -n "$CARTESIA_API_KEY" && echo set。
エンジンとKokoroフォールバック
video.config.mjs 内の tts.engine:
auto(デフォルト):キーが見つかりサービスが応答する場合はCartesiaを使用。そうでない場合、言語全体がKokoro(ローカル、無料)で音声化され、警告が表示されます。1つの言語が2つの音声で混在することはありません。Cartesiaが途中で応答しなくなった場合、その言語全体がKokoroで再作成され、次回Cartesiaが復帰したときに再度再作成されます。cartesia:フォールバックせずに失敗します。kokoro:オフラインのまま。音声:af_bella(EN)、ef_dora(ES)。Kokoroは単語タイムスタンプを提供しないため、キャプションは比例配分でタイミング調整されます。
出力にKokoroに関する警告がある場合、動画にCartesia音声が使用されていないことを意味します。動画を引き渡す際にその旨を伝えてください。
スペイン語音声
voices.es は、スペイン語バージョンが作成されるまで null です。Cartesia音声ライブラリからスペイン語音声を選択し、スクリプトのサンプル行を聞いて、そのIDを video.config.mjs に記録します(es: { id: '<voice-id>', language: 'es' })。そして、'es' を SETTINGS.voices に追加し(スペイン語キャプションが必要な場合は SETTINGS.subtitles にも追加します)。
発音
TTSはナレーションテキストを読み上げます。キャプションには書き言葉のテキストが表示されます。TTSが数字や記号を誤って読む場合は、say の第4引数としてその行に話し言葉を与え、記事の書き言葉形式はキャプションとして保持します。
say(0.3, 'It solved 14/20 tasks.', 'Resolvió 14/20 tareas.', {
en: 'It solved fourteen out of twenty tasks.',
es: 'Resolvió catorce de veinte tareas.',
})
- TTSは話し言葉を読み上げます(キャッシュは話し言葉が変更されたときに行を再音声化します)。行の長さは話し言葉から取得されます。
- キャプションには書き言葉のテキストが表示され、行全体に比例配分でタイミング調整されます(単語タイムスタンプは話し言葉に属するため、その行では使用されません)。
- 行は平易に記述し(「14/20」、「83 %」、「p = 0.0018」)、試聴してTTSが誤っている場合にのみ話し言葉を追加してください。
- スラッシュ、バージョン文字列(「gpt-5.6」)、ファイル名、頭字語がよく問題になります。これらを含む各行を試聴してください。
音声QA
npm run audio-qa(out/audio-qa.md を書き込みます):
- 各行を同じラウドネスにノーマライズします(ファイルバージョンごとに1回)。
- ソースのピークが -0.1 dBFS に達した行をクリッピングとしてフラグ付けします。
- テキスト長からの推定の1.6倍以上続く行を長すぎるとしてフラグ付けします:これは音切れや繰り返しの兆候です。フラグ付けされた各行を試聴し、問題がある場合は再音声化してください(テキストを少し編集するか、そのwavを削除します)。
npm run renderの後、out/内の各ミックスを -16 LUFS integrated、±1 LU(トゥルーピーク -1.5 dBTP)に対して測定し、ターゲットから外れている場合は終了コード1で終了します。
ナレーション後、npm run lint を再度実行してください。実際の長さが推定値に置き換わり、動画がターゲット長からずれたり、キャプションが17文字/秒を超えたりする可能性があります。
音楽背景
ソフトな背景音楽はローカルで生成されます(npm run music、npm run render で不足時に自動生成されます。python3とnumpy、または uv が必要です)。行が再生されている間、音楽の音量は30%にダッキングされます。音楽を無効にするには、SETTINGS.music を null に設定します。