見出し画像

whisper.cpp(Core ML版)、Remotion、機械音声でゆっくり動画風のものをを作りたい

ほぼ上記の記事で事足りるのですが、いくつか補足します。

Core MLモデルの生成
models フォルダ配下に generate-coreml-model.sh にCore MLモデル生成スクリプトが用意されているので、以下のように実行する:

https://zenn.dev/shu223/articles/whisper-coreml

とありますが、うまく行きませんでした。ANECompilerServiceがしばらく動作していて、あまりに長いので得て起きたら終わっていました。largeモデルで12時間くらいかかったようです。

モデルは

からダウンロードできます。ダウンロードしたモデルを指定して

./main -m models/ggml-base.bin -l ja -f ファイル名
whisper_init_from_file_no_state: loading model from 'models/ggml-base.bin'
whisper_model_load: loading model
whisper_model_load: n_vocab       = 51865
whisper_model_load: n_audio_ctx   = 1500
whisper_model_load: n_audio_state = 512
whisper_model_load: n_audio_head  = 8
whisper_model_load: n_audio_layer = 6
whisper_model_load: n_text_ctx    = 448
whisper_model_load: n_text_state  = 512
whisper_model_load: n_text_head   = 8
whisper_model_load: n_text_layer  = 6
whisper_model_load: n_mels        = 80
whisper_model_load: ftype         = 1
whisper_model_load: type          = 2
whisper_model_load: mem required  =  310.00 MB (+    6.00 MB per decoder)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: model ctx     =  140.60 MB
whisper_model_load: model size    =  140.54 MB
whisper_init_state: kv self size  =    5.25 MB
whisper_init_state: kv cross size =   17.58 MB
whisper_init_state: loading Core ML model from 'models/ggml-base-encoder.mlmodelc'
whisper_init_state: first run on a device may take a while ...
whisper_init_state: Core ML model loaded

system_info: n_threads = 4 / 8 | AVX = 0 | AVX2 = 0 | AVX512 = 0 | FMA = 0 | NEON = 1 | ARM_FMA = 1 | F16C = 0 | FP16_VA = 1 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 0 | VSX = 0 | COREML = 1 |

main: processing 'ファイル名' (176222891 samples, 11013.9 sec), 4 threads, 1 processors, lang = ja, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:02.000]  ねー
[00:00:02.000 --> 00:00:17.880]  今日のご飯はカレーだったよ
[00:00:17.880 --> 00:00:23.200]  やっぱりカレーだ

実行したらうまく動いたようです。ただ初回実行時にANECompilerServiceが動作し、スクリプトと同じことをするようで、

whisper_init_state: loading Core ML model from 'models/ggml-base-encoder.mlmodelc'

と出ていることから結局変換はされているようです。largeモデルはまた12時間かかるのかも知れません。

あとはChatGPTに

以下のような動作をするシェルスクリプトを書いて下さい。概要、ffmpegで入力したファイルを16KHzの無圧縮wavに変換する。wavの名前はテンポラリで他と重複しそうにない名前を指定する。./mainを実行する。必要なオプションはbaseかlargeかモデルを選べること、言語(ja, enなど)を選べること。最後にテンポラリのwavを削除すること。 ffmpeg -i <input file> -ar 16000 -ac 1 -c:a pcm_s16le <random_name>.wav ./main -m models/ggml-[base|large].bin -l <language> -f <random_name>.wav rm <random_name>.wav

自作プロンプト

と指示したらオプション処理やエラー処理、usageの表示まできちんと書いてくれました。

以下のシェルスクリプトは、入力ファイルを16KHzの無圧縮wavに変換し、./mainを実行した後、一時ファイルを削除します。モデル(baseまたはlarge)と言語(ja、enなど)を選択できます。

ChatGPT
#!/bin/bash

if [ $# -lt 3 ]; then
  echo "Usage: $0 <input file> <model: base|large> <language: ja|en|...>"
  exit 1
fi

input_file="$1"
model="$2"
language="$3"

if [ "$model" != "base" ] && [ "$model" != "large" ]; then
  echo "Invalid model. Choose 'base' or 'large'."
  exit 1
fi

random_name=$(mktemp -u tmp_audio_XXXXX).wav

ffmpeg -i "$input_file" -ar 16000 -ac 1 -c:a pcm_s16le "$random_name"
./main -m "models/ggml-$model.bin" -l "$language" -f "$random_name"
rm "$random_name"

このスクリプトを、例えばconvert_and_run.shという名前で保存し、実行権限を与えて実行できます。

chmod +x convert_and_run.sh
./convert_and_run.sh <input file> <model: base|large> <language: ja|en|...>

個人的なプランとして、英語のゆっくり動画みたいなものを作ってみようかと思っています。

日本語と英語では、文化の違いや好みを除けばおそらく英語のほうが20倍くらいは視聴されます。ゆっくり動画方式ならば別に英語の発音が汚くても問題ありません。ただしテーマは普通の英語話者でも作れるものを作っても仕方ないので、日本人ならではの何かを英語で発信することが重要かと考えています。

概要

  1. 原稿を日本語で書く

  2. ChatGPTに適切なプロンプトを入れて英語の台本にする

  3. Text-to-speechで流暢な英語の音声にする

  4. Whisperでsrt形式に変換する

  5. Remotionで字幕と音声を合成する

  6. 必要な素材を配置する

Remotionで字幕を表示する

RemotionはReactのフレームワークでコーディングで動画を作れます。全自動で動画を作るよりも字幕だけSRTから自動で生成して、残りは動画編集ソフトで素材を配置するのがちょうどよいバランスだと思います。

機械音声はやや不自然かも知れませんが、滑舌はいいので、特にアナウンサーでも声優でもない人間が喋るよりはきれいにテキストに戻すことができます。テキストの原稿を一度音声にしてまたテキストに戻すのは無駄のようですが、字幕にする場合は音声に同期して表示することが重要ですから意味のあるステップだと思います。ただし機械音声が字幕ファイルを生成してくれるならこのステップは不要です。

Whisperの出力はタイムコードが付加されているので、音声と字幕のタイミングを合わせることができます。Remotionはコードで制御するのでSRTのような構造化された入力を一発で字幕に変換するのは得意です。Whiperは適切な長さで切ってくれる傾向にあるので、字幕としてちょうどいい長さの文章をタイムコード付きで得ることができます。


この記事が気に入ったらサポートをしてみませんか?