こんにちは、Tech Samuraiです!
GoProで撮影した動画を記録用やドライブレコーダーとして見返した時、「画面の中に撮影日時が表示されていない」ことに不便を感じたことはありませんか?
GoPro Labs(公式の裏技ファームウェア)を使えば撮影時に焼き込むことも可能ですが、すでに撮影済みの大量の動画ファイルには適用できません。
そこで今回は、「撮影済みの大量の動画ファイル」に対して、後からPCで自動的に日時を焼き込むPythonスクリプトを作成しました。Ubuntu 環境で作りましたが、Windowsでも動作します。
FFmpeg特有の「エスケープ地獄」や「タイムゾーンのズレ」との戦いの記録と、完成したコードを共有します。
開発環境
- PC: Ubuntu ※Windowsでも動作可能
- 言語: Python 3.x
- ツール: FFmpeg, ffprobe
- 素材: GoPro HEROシリーズで撮影した .MP4 ファイル
Step 1:動画から「撮影開始日時」を取得する
まずは、動画ファイル自体が持っているメタデータから、正確な撮影日時が取得できるかを確認します。これには ffprobe を使用します。
GoProの動画は通常、作成日時が UTC(協定世界時) で記録されています。日本時間(JST)として扱うには、取得した時間に+9時間する必要があります。
検証用コード
まずはデータが取れるか確認するための小さなスクリプトでテストしました。
import subprocess
import json
import datetime
import sys
def check_metadata(video_path):
# ffprobeでjson形式のメタデータを取得
cmd = [
'ffprobe', '-v', 'quiet', '-print_format', 'json',
'-show_entries', 'format_tags=creation_time', video_path
]
try:
output = subprocess.check_output(cmd)
data = json.loads(output)
tags = data.get('format', {}).get('tags', {})
creation_time = tags.get('creation_time')
if creation_time:
print(f"メタデータ(UTC): {creation_time}")
# 文字列を日付オブジェクトに変換
dt_utc = datetime.datetime.fromisoformat(creation_time.replace('Z', '+00:00'))
# JSTに変換
dt_jst = dt_utc.astimezone(datetime.timezone(datetime.timedelta(hours=9)))
print(f"日本時間(JST): {dt_jst}")
return True
else:
print("creation_time が見つかりませんでした。")
return False
except Exception as e:
print(f"エラー: {e}")
if __name__ == "__main__":
check_metadata("sample_video.MP4")
Step 2:FFmpegの「エスケープ地獄」との戦い
日時が取得できたので、次は ffmpeg の drawtext フィルタを使って画面に焼き付けます。
ここで今回一番ハマったのが、「コロン(:)の扱い」です。
最初は 2025-12-10 12:30:45 のように表示しようとしましたが、FFmpegのコマンドライン引数において : は特殊文字(区切り文字)として扱われます。
Pythonの subprocess 経由で渡す際、エスケープ処理(\)が複雑になり、何度やってもエラーが出たり、文字が表示されなかったりしました。
解決策:区切り文字を変える
無理にコロンを表示させてコードを複雑にするよりも、視認性を保ったまま安全な文字を使う方針に切り替えました。
- ×
12:30:45(エスケープ処理が大変) - △
12-30-45(ハイフン:安全だが時刻としては少し見にくい) - ◎
12.30.45(ドット:見やすく、エラーにならない)
最終的に、デジタル時計風の ドット区切り を採用しました。
Step 3:UTCとJSTのズレ問題
FFmpegには pts:gmtime という「動画の進行に合わせて時計のカウントを進める機能」があります。しかし、これは名前の通り gmtime(グリニッジ標準時)で表示されてしまいます。
Python側でJSTに変換した時間を渡しても、FFmpeg側でまたUTCとして解釈され、表示される時刻が9時間ズレてしまう現象が発生しました。
解決策
FFmpegに渡す開始時間(タイムスタンプ)にあらかじめ 「9時間分の秒数(32400秒)」を足して渡す ことで、無理やりJSTとして表示させるロジックを組み込みました。
【完成形】一括処理スクリプト
これまでの試行錯誤を統合し、以下の機能を実装した完成コードです。
- フォルダ一括処理:
original_videosフォルダ内の動画を全部処理 - 自動フォルダ作成:
processed_videosに変換後ファイルを保存 - ファイル名リネーム:
2025-12-10_13.00.00.mp4のように撮影日時にリネーム - テストモード搭載: 各動画の最初の5秒だけ処理して動作確認が可能
ディレクトリ構成
project_root/
├── batch_add_timer.py (このスクリプト)
├── original_videos/ (ここにGoPro動画を入れる)
└── processed_videos/ (ここに出力される)
ソースコード
Gitリポジトリ
※環境に合わせて FONT_PATH (フォントファイルの場所)を書き換えて使用してください。
まとめ
DaVinci Resolveなどの動画編集ソフトを使えば手動でタイトルを入れることは可能ですが、何十本ものファイルを寝ている間に全自動で処理したい場合は、やはり Python + FFmpeg の組み合わせが強力です。
最初はエラーに悩まされましたが、「コマンドラインツール特有の制約(コロンのエスケープなど)」を回避する工夫をすることで、安定して動作するスクリプトになりました。ドライブレコーダー映像の整理や、記録映像のアーカイブ化にぜひ役立ててください。

コメント