Skip to content

Instantly share code, notes, and snippets.

@bsidhom
Created March 14, 2023 04:21
Show Gist options
  • Save bsidhom/d02e7fb4ffab55a48240385c3f4d35b8 to your computer and use it in GitHub Desktop.
Save bsidhom/d02e7fb4ffab55a48240385c3f4d35b8 to your computer and use it in GitHub Desktop.
Update video timestamps to match timestamp data in associated JSON files if they don't already match
#!/usr/bin/env python3
# Update video timestamps to match timestamp metadata in associated JSON files.
import asyncio
import datetime
import json
import os
import os.path
import subprocess
async def main():
for file in os.listdir("."):
if os.path.isfile(file):
base, ext = os.path.splitext(file)
if ext.lower() != ".json":
continue
timestamp = get_json_timestamp(file)
if timestamp is None:
raise Exception(f"timestamp missing for {base}")
video_file = base + ".mp4"
if not os.path.isfile(video_file):
raise Exception(f"missing video file for {base}")
video_timestamp = await get_video_timestamp(video_file)
if timestamp == video_timestamp:
continue
await update_timestamp(video_file, timestamp)
def get_json_timestamp(file):
with open(file) as f:
j = json.load(f)
timestamp = j.get("timestamp")
return parse_timestamp(timestamp)
async def get_video_timestamp(file):
p = await asyncio.create_subprocess_exec("ffprobe",
"-v",
"quiet",
"-print_format",
"json",
"-show_format",
"-show_streams",
file,
stdout=subprocess.PIPE)
s = await p.stdout.read()
await p.wait()
j = json.loads(s)
timestamp = j.get("format").get("tags").get("creation_time")
return parse_timestamp(timestamp)
def parse_timestamp(s):
dt = datetime.datetime.fromisoformat(s)
return dt.astimezone(datetime.timezone.utc)
async def update_timestamp(file, timestamp):
orig_file = file + ".orig"
temp_file = "temp." + file
args = [
"-i", file, "-c", "copy", "-map_metadata", "0", "-metadata",
f"creation_time={timestamp.isoformat()}", temp_file
]
p = await asyncio.create_subprocess_exec("ffmpeg", *args)
await p.wait()
os.rename(file, orig_file)
os.rename(temp_file, file)
if __name__ == "__main__":
asyncio.run(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment