almost back to working state with rust transport
This commit is contained in:
@@ -178,15 +178,45 @@ def extract_scene_frames(input_path, output_dir, scene_threshold=0.10,
|
||||
return stdout.decode("utf-8", errors="replace"), stderr.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def detect_scenes_from_pipe(scene_threshold=0.10, flush_frames=2, fps=30):
|
||||
"""Scene-detect from piped raw H.264 on stdin. Returns a node for run_async.
|
||||
|
||||
Used when Rust server provides a live H.264 stream via Unix socket.
|
||||
Caller bridges the socket to ffmpeg's stdin and reads stdout/stderr:
|
||||
- stdin: raw H.264 from the socket
|
||||
- stdout: MJPEG pipe (JPEG frames on scene change)
|
||||
- stderr: showinfo lines with pts_time timestamps
|
||||
"""
|
||||
stream = ffmpeg.input("pipe:0", f="h264", framerate=fps, hwaccel="cuda")
|
||||
scene_expr = f"gt(scene,{scene_threshold})"
|
||||
if flush_frames > 0:
|
||||
mod_val = 1 + flush_frames
|
||||
flush_expr = f"eq(n,prev_selected_n+1)*mod(selected_n,{mod_val})"
|
||||
select_expr = f"{scene_expr}+{flush_expr}"
|
||||
else:
|
||||
select_expr = scene_expr
|
||||
scene_stream = stream.filter("select", select_expr).filter("showinfo")
|
||||
return ffmpeg.output(
|
||||
scene_stream, "pipe:1",
|
||||
f="image2pipe", vcodec="mjpeg",
|
||||
flush_packets=1, strict="unofficial",
|
||||
**{"q:v": "2", "fps_mode": "passthrough"},
|
||||
).global_args(*GLOBAL_ARGS)
|
||||
|
||||
|
||||
def extract_audio_chunk(input_path, output_path, start_time=0.0, duration=None):
|
||||
"""Extract audio from recording as 16kHz mono WAV (optimal for Whisper).
|
||||
|
||||
Uses input-level seeking (-ss before -i) for fast keyframe-based seek.
|
||||
Supports fMP4 (auto-detect) and raw AAC files (explicit format hint).
|
||||
Returns (stdout, stderr) as decoded strings.
|
||||
"""
|
||||
kwargs = {"ss": start_time}
|
||||
if duration is not None:
|
||||
kwargs["t"] = duration
|
||||
# Raw AAC files need explicit format hint
|
||||
if str(input_path).endswith(".aac"):
|
||||
kwargs["f"] = "aac"
|
||||
stream = ffmpeg.input(str(input_path), **kwargs)
|
||||
output = (
|
||||
ffmpeg.output(
|
||||
@@ -219,10 +249,11 @@ def extract_frame_at(input_path, output_path, timestamp):
|
||||
output.run(capture_stdout=True, capture_stderr=True)
|
||||
|
||||
|
||||
def run_async(output_node, pipe_stdout=False, pipe_stderr=False):
|
||||
def run_async(output_node, pipe_stdin=False, pipe_stdout=False, pipe_stderr=False):
|
||||
"""Start an ffmpeg pipeline asynchronously via ffmpeg-python's run_async."""
|
||||
log.info("run_async: %s", " ".join(output_node.compile()))
|
||||
return output_node.run_async(
|
||||
pipe_stdin=pipe_stdin,
|
||||
pipe_stdout=pipe_stdout,
|
||||
pipe_stderr=pipe_stderr,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user