diff --git a/voicevox-remotion-template/scripts/generate-lipsync.js b/voicevox-remotion-template/scripts/generate-lipsync.js index 4ef5748..109e6a9 100644 --- a/voicevox-remotion-template/scripts/generate-lipsync.js +++ b/voicevox-remotion-template/scripts/generate-lipsync.js @@ -17,12 +17,21 @@ "src/data/pizza-oven-project-01/voicevox-manifest.json", ]; +// 用途: プロジェクト基準の相対パスを、ファイル操作で使う絶対パスへ変換する。 +// 使用方法: CLI引数や環境変数から受け取ったパスを、読み書き前にこの関数へ渡す。 +// オプションや引数詳細: value は絶対パスならそのまま、相対パスなら projectRoot から解決する。 const resolveProjectPath = (value) => path.isAbsolute(value) ? value : path.resolve(projectRoot, value); +// 用途: ログやエラーメッセージに表示しやすいプロジェクト相対パスへ変換する。 +// 使用方法: 内部処理で使う絶対パスを、利用者向けに表示したい場面で呼び出す。 +// オプションや引数詳細: targetPath は projectRoot からの相対表記にし、区切り文字はスラッシュへ統一する。 const toProjectRelative = (targetPath) => path.relative(projectRoot, targetPath).split(path.sep).join("/"); +// 用途: public 配下の音声ファイルを、Remotion から参照できる public 相対パスへ変換する。 +// 使用方法: lipsync manifest に sourceAudio を記録するときに呼び出す。 +// オプションや引数詳細: targetPath が public 配下なら public 相対、外側ならプロジェクト相対の表示用パスを返す。 const toPublicRelative = (targetPath) => { const relativePath = path.relative(publicDir, targetPath); if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) { @@ -32,6 +41,9 @@ return relativePath.split(path.sep).join("/"); }; +// 用途: 指定されたファイルまたはディレクトリが存在するかを確認する。 +// 使用方法: 入力音声、manifest、Rhubarb 実行ファイルの存在チェックで await して呼び出す。 +// オプションや引数詳細: targetPath は確認対象の絶対または相対パスで、アクセスできれば true、できなければ false を返す。 const pathExists = async (targetPath) => { try { await fs.access(targetPath); @@ -41,6 +53,9 @@ } }; +// 用途: npm run lip:generate に渡された CLI オプションを読み取り、生成対象と出力先を決める。 +// 使用方法: 起動直後に呼び出し、audioPath・outPath・rawOutPath・manifestPath・sourceManifestPaths を取得する。 +// オプションや引数詳細: 音声パスを1つ指定でき、--out、--raw-out、--manifest、複数の --source-manifest に対応する。 const parseArgs = () => { const values = { out: undefined, @@ -97,11 +112,17 @@ }; }; +// 用途: 実行環境に応じた Rhubarb CLI の実行ファイル名候補を返す。 +// 使用方法: findRhubarbBin の候補パス作成時に呼び出す。 +// オプションや引数詳細: Windows では rhubarb.exe・rhubarb.cmd・rhubarb、それ以外では rhubarb を候補にする。 const executableNames = () => process.platform === "win32" ? ["rhubarb.exe", "rhubarb.cmd", "rhubarb"] : ["rhubarb"]; +// 用途: 環境変数、ローカル配置、PATH から利用可能な Rhubarb CLI を探す。 +// 使用方法: lipsync 生成処理の前に await して呼び出し、runRhubarb に渡す実行ファイルパスを取得する。 +// オプションや引数詳細: RHUBARB_BIN が指定されていれば優先し、見つからない場合は node_modules/.bin、tools、vendor、PATH を順に探す。 const findRhubarbBin = async () => { if (process.env.RHUBARB_BIN) { const envPath = resolveProjectPath(process.env.RHUBARB_BIN); @@ -143,6 +164,9 @@ ); }; +// 用途: Rhubarb CLI を実行し、音声ファイルから口パク用の生 JSON を生成する。 +// 使用方法: generateTask 内で await し、task.inputPath から task.rawOutputPath へ Rhubarb 出力を書き出す。 +// オプションや引数詳細: rhubarbBin は実行ファイルパス、inputPath は音声ファイル、rawOutputPath は Rhubarb JSON の出力先を指定する。 const runRhubarb = (rhubarbBin, inputPath, rawOutputPath) => new Promise((resolve, reject) => { const args = [ @@ -181,9 +205,15 @@ }); }); +// 用途: JSON ファイルを読み込み、JavaScript の値として返す。 +// 使用方法: manifest、Rhubarb 生 JSON、既存 lipsync manifest の読み込みで await して呼び出す。 +// オプションや引数詳細: targetPath は UTF-8 の JSON ファイルパスを指定し、内容は JSON.parse で解釈する。 const loadJson = async (targetPath) => JSON.parse(await fs.readFile(targetPath, "utf8")); +// 用途: 既存の lipsync manifest を読み込み、追記可能な manifest 形式に整える。 +// 使用方法: 単一音声や source manifest 指定時に、既存 timelines を維持するため await して呼び出す。 +// オプションや引数詳細: manifestPath が存在しない、または version 1 の timelines 形式でない場合は空の manifest を返す。 const loadExistingGeneratedManifest = async (manifestPath) => { if (!(await pathExists(manifestPath))) { return {version: 1, timelines: {}}; @@ -197,6 +227,9 @@ return manifest; }; +// 用途: CLI で直接指定された単一音声ファイルから、口パク生成タスクを作る。 +// 使用方法: audioPath が指定されたときに await し、generateTask へ渡す task オブジェクトを得る。 +// オプションや引数詳細: audioPath は入力音声、outPath は正規化後 JSON、rawOutPath は Rhubarb 生 JSON の任意出力先を指定する。 const taskForAudioPath = async ({audioPath, outPath, rawOutPath}) => { const inputPath = resolveProjectPath(audioPath); if (!(await pathExists(inputPath))) { @@ -214,6 +247,9 @@ }; }; +// 用途: VOICEVOX manifest の各音声エントリから、口パク生成タスク群を作る。 +// 使用方法: defaultTasks または --source-manifest 指定時の処理で await して呼び出す。 +// オプションや引数詳細: manifestPath は id と file を含む JSON 配列を想定し、file は public 配下から解決する。 const tasksForVoicevoxManifest = async (manifestPath) => { if (!(await pathExists(manifestPath))) { return []; @@ -248,6 +284,9 @@ ); }; +// 用途: 既定または指定された VOICEVOX manifest から、まとめて生成する口パクタスクを集める。 +// 使用方法: 単一音声パスが指定されていない場合に await して呼び出す。 +// オプションや引数詳細: sourceManifestPaths が空なら DEFAULT_SOURCE_MANIFESTS を使い、1件も見つからなければエラーにする。 const defaultTasks = async (sourceManifestPaths) => { const manifests = sourceManifestPaths.length > 0 @@ -264,11 +303,17 @@ return tasks; }; +// 用途: JSON を整形してファイルへ書き出す。 +// 使用方法: 正規化済み口パク JSON や lipsync manifest を保存するときに await して呼び出す。 +// オプションや引数詳細: targetPath は出力先、value は JSON.stringify(value, null, 2) で書き出す値を指定する。 const writeJson = async (targetPath, value) => { await fs.mkdir(path.dirname(targetPath), {recursive: true}); await fs.writeFile(targetPath, `${JSON.stringify(value, null, 2)}\n`); }; +// 用途: 1件の音声タスクについて Rhubarb 実行、正規化、JSON 保存までを行う。 +// 使用方法: tasks の各要素に対して await し、manifest に格納する timeline を受け取る。 +// オプションや引数詳細: rhubarbBin は Rhubarb CLI、task は id・inputPath・sourceAudio・rawOutputPath・outputPath を含む。 const generateTask = async (rhubarbBin, task) => { await fs.mkdir(path.dirname(task.rawOutputPath), {recursive: true}); await runRhubarb(rhubarbBin, task.inputPath, task.rawOutputPath); diff --git a/voicevox-remotion-template/scripts/voicevox-generate.js b/voicevox-remotion-template/scripts/voicevox-generate.js index 19eec45..24e5644 100644 --- a/voicevox-remotion-template/scripts/voicevox-generate.js +++ b/voicevox-remotion-template/scripts/voicevox-generate.js @@ -13,9 +13,15 @@ ); const publicDir = path.join(projectRoot, "public"); +// 用途: プロジェクト基準の相対パスを、ファイル操作で使う絶対パスへ変換する。 +// 使用方法: CLI引数や既定値のパス文字列を渡し、以降の処理では戻り値を使う。 +// オプションや引数詳細: value は絶対パスならそのまま、相対パスなら projectRoot から解決する。 const resolveProjectPath = (value) => path.isAbsolute(value) ? value : path.resolve(projectRoot, value); +// 用途: npm run voice:generate に渡された CLI オプションを読み取り、生成対象のパスを決める。 +// 使用方法: 起動直後に呼び出し、scriptPath・outputDir・manifestPath を取得する。 +// オプションや引数詳細: --script、--output、--manifest を指定でき、省略時は yukkuri-composition 用の既定値を使う。 const parseArgs = () => { const values = { script: "src/data/yukkuri-composition/script.ts", @@ -53,9 +59,15 @@ const {scriptPath, outputDir, manifestPath} = parseArgs(); +// 用途: ログやエラーメッセージに表示しやすいプロジェクト相対パスへ変換する。 +// 使用方法: 絶対パスを利用者向けに表示したい場面で呼び出す。 +// オプションや引数詳細: targetPath は projectRoot からの相対表記にし、区切り文字はスラッシュへ統一する。 const toProjectRelative = (targetPath) => path.relative(projectRoot, targetPath).split(path.sep).join("/"); +// 用途: public 配下の出力先を、Remotion から参照できる public 相対パスへ変換する。 +// 使用方法: manifest に書き込む音声ファイルのパスを作る前に呼び出す。 +// オプションや引数詳細: targetPath は public 配下にある必要があり、外側を指す場合はエラーにする。 const toPublicRelative = (targetPath) => { const relativePath = path.relative(publicDir, targetPath); if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) { @@ -69,6 +81,9 @@ const publicRelativeOutputDir = toPublicRelative(outputDir); +// 用途: 生成された WAV バッファから再生時間を秒単位で読み取る。 +// 使用方法: synthesis のレスポンスを Buffer 化した後、manifest の durationSeconds 用に呼び出す。 +// オプションや引数詳細: buffer は RIFF/WAVE 形式の WAV データを想定し、fmt と data チャンクから長さを計算する。 const getWavDurationSeconds = (buffer) => { if (buffer.toString("ascii", 0, 4) !== "RIFF") { throw new Error("Invalid WAV header: RIFF not found."); @@ -101,6 +116,9 @@ return dataSize / byteRate; }; +// 用途: TypeScript の時系列脚本を一時ディレクトリへコンパイルし、Node.js から読み込む。 +// 使用方法: script.ts の characters と timeline を取得するために await して呼び出す。 +// オプションや引数詳細: scriptPath の内容を CommonJS として emit し、処理後は一時出力を削除する。 const loadScriptModule = async () => { const outDir = await fs.mkdtemp(path.join(os.tmpdir(), "voicevox-script-")); const compilerOptions = { @@ -145,6 +163,9 @@ } }; +// 用途: 起動中の VOICEVOX エンジンから利用可能な話者一覧を取得する。 +// 使用方法: 音声生成前に await して呼び出し、speakerName と styleName の解決に使う。 +// オプションや引数詳細: VOICEVOX_URL の /speakers を参照し、HTTP エラー時は例外を投げる。 const fetchSpeakers = async () => { const response = await fetch(`${VOICEVOX_URL}/speakers`); if (!response.ok) { @@ -154,6 +175,9 @@ return response.json(); }; +// 用途: say(...) の個別指定とキャラクター既定値から、VOICEVOX の話者名とスタイル名を決める。 +// 使用方法: 各 speech イベントの処理時に呼び出し、resolveSpeakerId へ渡す voice 情報を得る。 +// オプションや引数詳細: characters は脚本のキャラクター定義、speech は id・character・voicevox を含む say イベントを想定する。 const resolveVoice = (characters, speech) => { const character = characters[speech.character]; if (!character) { @@ -167,6 +191,9 @@ }; }; +// 用途: VOICEVOX の話者一覧から、指定された話者名とスタイル名に対応する speaker id を探す。 +// 使用方法: audio_query と synthesis の speaker パラメータを作る直前に呼び出す。 +// オプションや引数詳細: speakers は /speakers の戻り値、voice は speakerName・styleName、speechId はエラー表示用の発話IDを渡す。 const resolveSpeakerId = (speakers, voice, speechId) => { const speaker = speakers.find(({name}) => name === voice.speakerName); if (!speaker) {