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:
+3
-1
@@ -232,10 +232,12 @@ def unmount_device(mount_point=DEFAULT_MOUNT_POINT):
|
|||||||
|
|
||||||
def find_video_files(source_folder):
|
def find_video_files(source_folder):
|
||||||
"""Walk source_folder, returning (absolute_path, relative_path) for every
|
"""Walk source_folder, returning (absolute_path, relative_path) for every
|
||||||
file whose extension looks like a video, regardless of folder layout."""
|
file whose extension looks like a video, excluding in-progress conversion temps."""
|
||||||
found = []
|
found = []
|
||||||
for root, _dirs, files in os.walk(source_folder):
|
for root, _dirs, files in os.walk(source_folder):
|
||||||
for file in files:
|
for file in files:
|
||||||
|
if file.endswith(".converting.mp4"):
|
||||||
|
continue
|
||||||
if os.path.splitext(file)[1].lower() in VIDEO_EXTENSIONS:
|
if os.path.splitext(file)[1].lower() in VIDEO_EXTENSIONS:
|
||||||
abs_path = os.path.join(root, file)
|
abs_path = os.path.join(root, file)
|
||||||
rel_path = os.path.relpath(abs_path, source_folder)
|
rel_path = os.path.relpath(abs_path, source_folder)
|
||||||
|
|||||||
+19
-4
@@ -71,19 +71,33 @@ def _convert_bg(relative_path):
|
|||||||
if relative_path in _converting:
|
if relative_path in _converting:
|
||||||
_converting[relative_path]["duration_s"] = duration_s
|
_converting[relative_path]["duration_s"] = duration_s
|
||||||
_converting[relative_path]["tmp_path"] = tmp_path
|
_converting[relative_path]["tmp_path"] = tmp_path
|
||||||
|
_converting[relative_path]["out_time_s"] = 0.0
|
||||||
cmd = [
|
cmd = [
|
||||||
"ffmpeg", "-nostdin", "-loglevel", "error", "-y",
|
"ffmpeg", "-nostdin", "-loglevel", "error", "-y",
|
||||||
"-i", source_path,
|
"-i", source_path,
|
||||||
"-c:v", "h264_v4l2m2m",
|
"-c:v", "h264_v4l2m2m",
|
||||||
"-b:v", "4M", # 4 Mbps — good quality, ~100MB per 3-min clip
|
"-b:v", "4M",
|
||||||
"-c:a", "aac",
|
"-c:a", "aac",
|
||||||
"-b:a", "128k",
|
"-b:a", "128k",
|
||||||
"-movflags", "faststart",
|
"-movflags", "faststart",
|
||||||
"-f", "mp4",
|
"-f", "mp4",
|
||||||
|
"-progress", "pipe:1",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
]
|
]
|
||||||
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
|
||||||
proc.wait() # real thread — blocking wait is fine
|
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:
|
if proc.returncode == 0 and os.path.isfile(tmp_path) and os.path.getsize(tmp_path) > 0:
|
||||||
os.replace(tmp_path, mp4_path)
|
os.replace(tmp_path, mp4_path)
|
||||||
# Delete original now that MP4 is ready
|
# Delete original now that MP4 is ready
|
||||||
@@ -152,7 +166,8 @@ def list_local_videos():
|
|||||||
if converting and conv_info:
|
if converting and conv_info:
|
||||||
elapsed = time.time() - conv_info["started_at"]
|
elapsed = time.time() - conv_info["started_at"]
|
||||||
duration_s = conv_info.get("duration_s", 0)
|
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 = {
|
convert_progress = {
|
||||||
"elapsed_s": int(elapsed),
|
"elapsed_s": int(elapsed),
|
||||||
"pct": pct,
|
"pct": pct,
|
||||||
|
|||||||
Reference in New Issue
Block a user