ffmpegでGoProの撮影日時を修正
タイムゾーンが無視されて記録されたGoProの動画の日時情報をffmpegで修正する
日時情報の取得
ffmpeg
では-i
オプションでファイルを指定して実行すればメタ情報を含む動画情報を表示してくれます。今回は下記例のcreation_time
を修正していきます
% ffmpeg -i GH010179.MP4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'GH010179.MP4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 2020-08-21T15:59:12.000000Z
encoder : Lavf58.47.100
Duration: 00:00:12.71, start: 0.000000, bitrate: 60623 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], 60428 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc (default)
Metadata:
creation_time : 2020-08-21T15:59:12.000000Z
handler_name : GoPro AVC
timecode : 08:58:40:06
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default)
Metadata:
creation_time : 2020-08-21T15:59:12.000000Z
handler_name : GoPro AAC
Stream #0:2(eng): Data: none (tmcd / 0x64636D74), 0 kb/s
Metadata:
creation_time : 2020-08-21T15:59:12.000000Z
handler_name : GoPro AVC
timecode : 08:58:40:06
日時取得 (Python)
参考までに、下記はPythonからcreation_timeを取得するサンプルコードです。datetime.fromisoformat()
関数で日時文字列を読み込みます。その際末尾の”Z”はフォーマットエラーを発生させるため取り除きます
def get_creation_time(mp4_file, ffmpeg=ffmpeg_path):
cmd = [ffmpeg, '-i', mp4_file]
ret = subprocess.run(cmd, capture_output=True, encoding='utf8')
for line in ret.stderr.splitlines():
if m:= re.match(r'\s*creation_time\s*:\s*(\S+)Z', line):
return datetime.fromisoformat(m.group(1))
return None
日時更新
続いてffmpeg
の-metadata
オプションでメタ情報を変更していきます。この際動画情報自体の再エンコードなどは行わないため-c copy
オプションを指定します。注意点として、ffmpeg
は既存ファイルのメタ情報の上書き保存はできないため、メタ情報を変更した新規ファイルの作成が必要になります。
% ffmpeg -i GH010179.MP4 -metadata creation_time="2020-08-21T23:59:12.000000Z" GH010179_new.MP4
日時更新 (python)
参考までに、こちらもpythonからffmpegを実行するサンプルコードです。こちらでは最初に元ファイルをold_*
にリネームしてから、元の名前で新規ファイルを作成しています
def set_creation_time(mp4_file, new_c_time, ffmpeg=ffmpeg_path):
old_file = os.path.join(os.path.dirname(mp4_file),
'old_' + os.path.basename(mp4_file))
success = False
try:
os.rename(mp4_file, old_file)
cmd = [ffmpeg, '-i', old_file, '-c', 'copy']
cmd.extend(['-metadata', f"creation_time={new_c_time.isoformat()}Z"])
cmd.append(mp4_file)
ret = subprocess.run(cmd)
if ret.returncode == 0:
success = True
finally:
if not success:
print(f'Rename back {old_file} to {mp4_file}')
os.rename(old_file, mp4_file)
Pythonでまとめて処理
タイムゾーンを修正する際にffmpeg
を一つ一つのファイルに対して実行していくのは面倒なため、pythonなどのスクリプトで処理します。上記の2つの関数を使えばJSTへの修正も容易に行えます
for mp4_file in files:
c_time = get_creation_time(mp4_file)
new_c_time = c_time - 9 # JSTはUTC+9
set_creation_time(mp4_file, new_c_time)
最近のコメント