LoginSignup
1
0

More than 1 year has passed since last update.

SubRip(.srt)ファイル形式の時間文字列をPythonのtimedeltaから生成する

Posted at

Pythonを使ってSubRipファイルを作成する際につまづいた箇所があったので記事にします。

SubRipファイル(拡張子.srt)は動画の字幕に使われるファイルです。
Youtubeの字幕でも使われています。1

SubRipファイルは以下のような形式で記述する必要があります。2

1
00:02:16,612 --> 00:02:19,376
Senator, we're making
our final approach into Coruscant.

2
00:02:19,482 --> 00:02:21,609
Very good, Lieutenant.

手元に各音源の再生時間と字幕のテキストがあれば機械的に生成できそうです。3

しかしこの00:02:16,612(時間:分:秒,ミリ秒)という形式の時間文字列をPythonでどう作るかでつまづきました。

Pythonで時間の計算といえばdatetime.timedeltaだろうと思ったのですが、
単純なstr(timedleta)ではミリ秒以下の表記ができません。

また、timedelta.microsecondsだと値が整数のため桁の扱いが厄介でした。
整数を上から3桁目で丸めて4桁目以下を除外するということ…? 桁数が変動する場合は…?

というわけでミリ秒以下も考慮して必要な時間の文字列をつくる関数を作りました。

from datetime import timedelta

def format_srttime(timedelta: timedelta) -> str:
    """timedeltaをSRT形式の時間表示にフォーマットする"""
    ss, mi = divmod(timedelta.total_seconds(), 1)
    mi = int(round(mi, 3) * 1000)
    mm, ss = divmod(ss, 60)
    hh, mm = divmod(mm, 60)
    srttime = f'{int(hh):02}:{int(mm):02}:{int(ss):02},{mi:03}'
    return srttime

timdedelta.total_secondes()を使って小数点以下を含んだ秒数を取得しています。

divmodは割り算の商と余りを計算してくれます。
取得した秒数を1で割ることで、整数部分(秒)ssと小数部分(マイクロ秒)miに分離しています。
同じような計算で秒ssを60で割って分mm、分を60で割って時間hhを計算しています。4

マイクロ秒は小数なのでround()で丸めてから1000倍して無理やり整数にしています。
こうすることで整数値に対する桁数処理の問題を回避しています。

あとはその結果をf文字列に入れて桁数が揃うように:02などで0埋めの指定をします。
あわせて、f文字列内でfloatになっている変数をintに揃えています。

そんな感じで00:02:16,612のような形式で時間の文字列を生成できるようになりました。
これで字幕作成が捗ります。

実際、筆者はVOICEPEAK5から音声ファイルと台詞のテキストファイルを出力して、
(再生時間の計算などしつつ)自動でSubRipファイルを作成できるようになりました。

VOICEPEAK(音声化) → Python(字幕作成) → Premiere Pro(動画作成) → Youtube(動画公開)

という流れで動画をつくれるようになったので、その話も機運が高まったらまた書きます。

  1. Youtubeヘルプ サポートされる字幕ファイル

  2. 引用元: SubRip - Wikipedia

  3. 各音源と字幕が一対一対応すれば、ですが。筆者はVOICEPEAKを使っていたのでこのニーズが発生しました。

  4. 公式の計算を倣いました。 参考: cpython/Lib/datetime.py

  5. VOICEPEAK 公式

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0