ショートのテロップ、作ってみたら面倒すぎた — 文字起こしを少しでも楽に
ショート動画のテロップ(字幕)は、見る分には当たり前。でも自分で作ると、どこで何を喋っているかを見て聞いて起こす、ものすごく面倒な作業でした。その面倒をどう減らすか考えて、音声認識で文字起こしとタイムスタンプを自動化し、DogaRunを作るまでの話です。
自分でショート動画を作るようになって、テロップ(字幕)付けが想像以上にしんどい作業だと知りました。とくにきついのが文字起こしです。1分ぶんの喋りを起こすだけで、十分以上かかることもあります。一度では聞き取れないので、再生しては数秒戻し、また聞き直す——この往復を延々と繰り返すからです。
テロップはどのショートにも当たり前に入っているので、外から見ると簡単そうに見えます。でも実際に入れる側に回ると、「見て・聞いて・起こして・合わせる」の連続で、地味に一番時間を溶かす工程でした。
見るのは一瞬、作るのはしんどい
面倒は、文字起こしだけで終わりません。起こした文字を、映像の「どのタイミングで出すか」に合わせる作業がまた重い。前に書いた記事(iMovieでテロップが思い通りに置けないときの解決法)のように、iMovieだと自由な位置に置くために、テロップごとグリーンバックの画像を作る羽目になったりもします。字幕の数だけ、この「合わせる・置く」の地味な作業が積み上がっていきます。
どうにかならないか、と考えた
さすがに毎回これは続けられない。どうにかならないか、と考えました。
順番に手をつけるなら、最初に引っかかるのは「聞いて手で打つ」ところです。ここは音声認識(自動文字起こし)に任せてしまえばいい。実際、手作業だと1分ぶんに十分以上かかっていたのが、自動にすると起こす時間そのものがなくなり、残るのは誤変換や区切りを直す数分だけになります。
さらに欲を言えば、文字と一緒に「それをいつ喋ったか」のタイムスタンプまで出したい。言葉に時刻がくっついていれば、さっきの「合わせる」作業の土台が、最初から手に入ることになります。
原理はシンプル。でも「使える道具」にするのは別だった
調べてみると、文字起こしとタイムスタンプを取得する仕組み自体は、Google Cloudの Speech-to-Text などのAPIを使って実現できます。ポイントは、単語ごとの「開始・終了時刻」を返してもらうこと。Speech-to-Text(v2)なら、chirp_2 というモデルに音声を渡し、enable_word_time_offsets を有効にするだけです。ざっくり、こんな感じになります。
from google.cloud.speech_v2 import SpeechClient
from google.cloud.speech_v2.types import cloud_speech
from google.api_core.client_options import ClientOptions
REGION = "us-central1"
# chirp_2 はリージョナルのエンドポイントを使う
client = SpeechClient(client_options=ClientOptions(
api_endpoint=f"{REGION}-speech.googleapis.com"))
config = cloud_speech.RecognitionConfig(
explicit_decoding_config=cloud_speech.ExplicitDecodingConfig(
encoding=cloud_speech.ExplicitDecodingConfig.AudioEncoding.LINEAR16,
sample_rate_hertz=16000,
audio_channel_count=1,
),
language_codes=["ja-JP"],
model="chirp_2",
features=cloud_speech.RecognitionFeatures(
enable_word_time_offsets=True, # ← 単語ごとの開始・終了時刻を返す
),
)
req = cloud_speech.RecognizeRequest(
recognizer=f"projects/{PROJECT}/locations/{REGION}/recognizers/_",
config=config,
content=audio_bytes, # 16kHz・モノラル・LINEAR16 の WAV
)
res = client.recognize(request=req)
for result in res.results:
for w in result.alternatives[0].words:
# start_offset / end_offset が、音から実測した時刻
print(w.word, w.start_offset.total_seconds(), w.end_offset.total_seconds())
キモは enable_word_time_offsets=True の一行と、返ってくる start_offset / end_offset です。これは音声そのものから測った時刻なので、字幕の表示タイミングの土台に、そのまま使えます。
ただ、自分だけが使えるプログラムを作ることと、毎日の動画制作で使える道具にすることは別でした。動画をアップロードしたら、時刻付きで文字起こしされ、読みやすい単位に区切られ、直して、mp4やSRTとして書き出すまでが1つの画面で完結する。そこまでつながって、やっと毎日使えるものになりました。
DogaRun では、実際にこの仕組みを使っている
DogaRunは、その「文字起こしと時刻付けという、一番時間のかかる初期工程を自動化して、あとは出てきた下地を直すだけにしたい」という気持ちからスタートして、誰でもブラウザから使える形にしたものです。
中身は、まさにさっきの仕組みそのものです。アップロードされた動画や音声を、まず ffmpeg で 16kHz・モノラルの音声に変換し、それを Speech-to-Text の chirp_2 に渡して、単語ごとの実測時刻つきで文字起こしします。長い音声は内部で分割して処理し、時刻は動画の実尺でクリップします。その結果が、編集画面にそのまま並びます。
DogaRunで文字起こしした結果(実際の画面)。文・単語に、音声から実測した秒数がついています。この時刻をそのまま字幕のタイミングに使うので、「合わせ直す」作業が要りません(画面は筆者の実際のショート動画のものです)。
あとは、この下地を直すだけです。時刻つきの字幕として区切られて出てくるので、誤変換を直しても表示タイミングは崩れません。1枚に詰まりすぎた字幕は、意味の切れ目で区切り直すだけ。ゼロから文字を打って、秒数を合わせて……という往復が、「出てきたものを直す」に変わります。
料金と、無料でできること
料金まわりも隠さず書いておきます。
- 音声認識による自動文字起こしは、無料のFreeプランでも毎月一定量まで試せます(月20クレジット=文字起こし約10分ぶんに相当)。それ以上や本格的な運用は有料プランです。音声認識にはAPI利用料などのコストがかかるため無制限ではありませんが、まずは無料で試せる、というのは伝えておきます。
- 自動文字起こしを使わなくても、字幕の編集そのものは無料で試せます。時刻付きで区切られた字幕をブラウザ上で直していく、という基本の操作から触ってもらえます。
- そして自動文字起こしは万能ではありません。固有名詞や数字は誤変換しますし、早口やBGMの被りでも精度は落ちます。出てくるのはあくまで「下書き」で、最後は人の目で直す前提だと思ってください。
まとめ
字幕づくりで一番重いのは、聞いて・手で起こして・時刻を合わせる、の繰り返しです。ここを音声認識の文字起こしと時刻付きデータ化に任せて、人は「出てきた下地を直す」だけにする——DogaRunは、そこを自動化したくて作ったツールです。同じところで消耗している人は、Freeプランから触ってみてください。