updates
Build and Push Docker Images / build-and-push (push) Successful in 22s

This commit is contained in:
2026-02-11 23:11:41 +01:00
parent 016e0cee0c
commit e92ccd757a
3 changed files with 52 additions and 27 deletions
+38 -16
View File
@@ -1,9 +1,12 @@
"""Video streaming: preferred-audio remux and live channel concat."""
from __future__ import annotations
import json
import logging
import subprocess
import tempfile
from collections.abc import Iterator
from pathlib import Path
from urllib.parse import unquote
@@ -107,45 +110,64 @@ def get_preferred_audio_stream_index(path: Path) -> int | None:
return None
def stream_file_with_preferred_audio(path: Path, wfile) -> bool:
def try_remux_preferred_audio(path: Path) -> tuple[bytes, Iterator[bytes]] | None:
"""
Stream the file via FFmpeg with only video and the preferred audio track.
Returns True if streaming was started, False if caller should fall back to raw file.
Start FFmpeg remux with preferred audio. Returns (first_chunk, rest_iterator) if
FFmpeg produces output, else None. Caller must send headers only after getting
a non-None result, then write first_chunk and iterate rest.
"""
audio_idx = get_preferred_audio_stream_index(path)
if audio_idx is None:
return False
return None
try:
proc = subprocess.Popen(
[
"ffmpeg",
"-i", str(path),
"-map", "0:v",
"-map", "0:v:0",
"-map", f"0:{audio_idx}",
"-c", "copy",
"-f", "mp4",
"-movflags", "frag_keyframe+empty_moov+default_base_moof",
"-max_muxing_queue_size", "1024",
"-",
],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
stderr=subprocess.PIPE,
start_new_session=True,
)
while True:
chunk = proc.stdout.read(65536)
if not chunk:
break
wfile.write(chunk)
wfile.flush()
proc.wait(timeout=1)
except (OSError, subprocess.TimeoutExpired):
first = proc.stdout.read(65536)
if not first:
proc.wait(timeout=5)
if proc.returncode != 0:
err = proc.stderr.read().decode("utf-8", errors="replace")[-500:]
logger.warning("FFmpeg remux failed (exit %s): %s", proc.returncode, err)
return None
def rest():
try:
while True:
chunk = proc.stdout.read(65536)
if not chunk:
break
yield chunk
finally:
proc.wait(timeout=5)
try:
proc.terminate()
proc.wait(timeout=2)
except Exception:
pass
return (first, rest())
except (OSError, subprocess.TimeoutExpired) as e:
logger.warning("FFmpeg remux error: %s", e)
try:
proc.terminate()
proc.wait(timeout=2)
except Exception:
pass
return False
return True
return None
def _escape_path(p: Path) -> str: