文字起こしと発声時刻で動画に文字を表示してみた

WSL の debian で作業した。 apt install ffmpegFFmpegをインストールした。

音声ファイルを静止画の動画にする

ffmpeg
  -loop 1
  -r 30
  -i image.png
  -i audio.mp3
  -pix_fmg yuv420p
  movie.mp4

文字起こしと文節ごとの発声時刻データを作る

とりあえず、Google の Cloud Speech-to-Text を使った。他の音声認識サービスでも同じようなものだろう。Cloud Speech-to-Text では単語ごとの発声時刻も取得できる。文字を表示させるのは単語単位よりも文節単位のほうがよさそうに思った。文字起こしした文章を GiNZA を使って文節に分けた。

文字起こしと単語とごの発声時刻

gcloud beta ml speech recognize
  audio.mp3
  --language-code="ja-JP"
  --encoding="mp3"
  --sample-rate=44100
  --include-word-time-offsets

サンプルレートが分からないときはffmpeg -i audio.mp3で確認できる。

文節に分ける

GiNZA のインストールを手元でやると時間がかかるから、Google Colaboratory を使った。

pip install "https://github.com/megagonlabs/ginza/releases/download/latest/ginza-latest.tar.gz"
import spacy
nlp = spacy.load('ja_ginza')
doc = nlp('まずは心を鎮めます。目を閉じて。全身の力をすーっと抜いていきます')
for sent in doc.sents:
    for token in sent:
        print(token.i, token._.bunsetu_index, token.orth_)
    print('EOS')

token._.bunsetu_indexで文節のインデックスが取得できる。

動画に文字を書き込む

今回は手っ取り早く FFMpeg の drawtext を使った。

日本語フォントをインストールする

IPA フォントにした。

sudo apt install fonts-ipafont

フォントのパスの確認方法

fc-list

文字を書き込む位置と場所とタイミングを決める

今回は適当に手で書いた。表示するフレームは発声時刻のデータを使う。

drawtext
    =text='まずは'
    :fontfile='/usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf'
    :fontsize=60
    :fontcolor='#FFF100'
    :enable='between(n, trunc(0 * 30), trunc((43/10) * 30))'
    :y=(th * 1)
,drawtext
    =text='心を'
    :fontfile='/usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf'
    :fontsize=60
    :fontcolor='#FFF100'
    :enable='between(n, trunc((7/10) * 30), trunc((43/10) * 30))'
    :y=(th * 2) + 10
,drawtext
    =text='静めます'
    :fontfile='/usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf'
    :fontsize=60
    :fontcolor='#FFF100'
    :enable='between(n, trunc((22/10) * 30), trunc((43/10) * 30))'
    :y=(th * 3) + 10


,drawtext
    =text='目を'
    :fontfile='/usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf'
    :fontsize=60
    :fontcolor='#FFF100'
    :enable='between(n, trunc((43/10) * 30), trunc((83/10) * 30))'
    :y=(th * 1)
,drawtext
    =text='閉じて'
    :fontfile='/usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf'
    :fontsize=60
    :fontcolor='#FFF100'
    :enable='between(n, trunc((49/10) * 30), trunc((83/10) * 30))'
    :y=(th * 2) + 10

......

書き込む

ffmpeg -i movie.mp4 -vf "`cat draw.txt`" result.mp4

その他

字幕を SVG アニメーションで作ったら Web の編集ツールとか工夫できそうで面白そう。

音の波形で文字の装飾とかできそう。

音声を字幕動画にするのに、たぶん一番面倒そうな発声タイミングと文字表示の同期が簡単にできることがわかった。