Files
reTraining/scripts/transcode_archive.py
T

67 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""Transcode video archive files to browser-compatible H.264 MP4 format."""
import os
import sys
import subprocess
import shutil
from pathlib import Path
VIDEO_EXTS = {".mp4", ".mkv", ".mov", ".avi", ".webm", ".m4v"}
def probe_codec(file_path: Path) -> str:
cmd = [
"ffprobe", "-v", "error", "-select_streams", "v:0",
"-show_entries", "stream=codec_name",
"-of", "default=noprint_wrappers=1:nokey=1", str(file_path)
]
res = subprocess.run(cmd, capture_output=True, text=True)
return res.stdout.strip().lower()
def transcode_video(file_path: Path):
tmp_path = file_path.with_name(f"_transcoded_{file_path.stem}.mp4")
cmd = [
"ffmpeg", "-hide_banner", "-loglevel", "error", "-y",
"-i", str(file_path),
"-c:v", "libx264", "-preset", "fast", "-crf", "22",
"-c:a", "aac", "-b:a", "128k",
"-movflags", "+faststart",
str(tmp_path)
]
res = subprocess.run(cmd)
if res.returncode == 0 and tmp_path.exists() and tmp_path.stat().st_size > 0:
# Save as .mp4
target_path = file_path.with_suffix(".mp4")
if target_path != file_path and file_path.exists():
file_path.unlink()
shutil.move(str(tmp_path), str(target_path))
print(f" ✅ Transcoded -> {target_path}")
else:
if tmp_path.exists():
tmp_path.unlink()
print(f" ❌ Failed to transcode {file_path}")
def process_archive(archive_dir: Path):
if not archive_dir.exists():
print(f"Archive directory {archive_dir} does not exist.")
return
print(f"Scanning {archive_dir} for non-H.264 videos...")
for root, _, files in os.walk(archive_dir):
for file in sorted(files):
file_path = Path(root) / file
if file_path.suffix.lower() in VIDEO_EXTS and not file.startswith("_transcoded_"):
codec = probe_codec(file_path)
if not codec:
print(f"⚠️ Could not probe codec or unreadable: {file_path}")
continue
if codec != "h264":
print(f"🔄 Converting {file_path} (current codec: {codec})...")
transcode_video(file_path)
else:
print(f" ✓ Already H.264: {file_path}")
if __name__ == "__main__":
target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("data/archive")
process_archive(target)