fix(videos): real ffmpeg progress via -progress pipe, exclude .converting.mp4

- ffmpeg -progress pipe:1 streams out_time_ms lines; we parse them in the
  reading loop so % = out_time_s / duration_s (actual encode position)
- find_video_files() skips *.converting.mp4 temp files so they are never
  listed, uploaded, or shown in the UI

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Mathieu Moran
2026-08-10 02:13:45 -04:00
co-authored by Copilot
parent afce229310
commit b711d421cc
2 changed files with 22 additions and 5 deletions
+19 -4
View File
@@ -71,19 +71,33 @@ def _convert_bg(relative_path):
if relative_path in _converting:
_converting[relative_path]["duration_s"] = duration_s
_converting[relative_path]["tmp_path"] = tmp_path
_converting[relative_path]["out_time_s"] = 0.0
cmd = [
"ffmpeg", "-nostdin", "-loglevel", "error", "-y",
"-i", source_path,
"-c:v", "h264_v4l2m2m",
"-b:v", "4M", # 4 Mbps — good quality, ~100MB per 3-min clip
"-b:v", "4M",
"-c:a", "aac",
"-b:a", "128k",
"-movflags", "faststart",
"-f", "mp4",
"-progress", "pipe:1",
tmp_path,
]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
proc.wait() # real thread — blocking wait is fine
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
text=True, bufsize=1)
# Read progress lines from stdout
for line in proc.stdout:
line = line.strip()
if line.startswith("out_time_ms="):
try:
ms = int(line.split("=", 1)[1])
with _converting_lock:
if relative_path in _converting:
_converting[relative_path]["out_time_s"] = ms / 1_000_000.0
except (ValueError, IndexError):
pass
proc.wait()
if proc.returncode == 0 and os.path.isfile(tmp_path) and os.path.getsize(tmp_path) > 0:
os.replace(tmp_path, mp4_path)
# Delete original now that MP4 is ready
@@ -152,7 +166,8 @@ def list_local_videos():
if converting and conv_info:
elapsed = time.time() - conv_info["started_at"]
duration_s = conv_info.get("duration_s", 0)
pct = min(round(elapsed / duration_s * 100), 99) if duration_s > 0 else 0
out_time_s = conv_info.get("out_time_s", 0.0)
pct = min(round(out_time_s / duration_s * 100), 99) if duration_s > 0 else 0
convert_progress = {
"elapsed_s": int(elapsed),
"pct": pct,