flush configurable
This commit is contained in:
@@ -64,7 +64,7 @@ def receive_record_and_relay(stream_url, output_path, relay_url):
|
||||
|
||||
|
||||
def receive_record_relay_and_detect(stream_url, output_path, relay_url,
|
||||
scene_threshold=0.10):
|
||||
scene_threshold=0.10, flush_frames=2):
|
||||
"""Single process: receive TCP → record fMP4 + relay UDP + scene detect.
|
||||
|
||||
One ffmpeg process, three output branches from the same TCP input:
|
||||
@@ -99,14 +99,16 @@ def receive_record_relay_and_detect(stream_url, output_path, relay_url,
|
||||
# Scene detection: CUDA decode (GPU) → select filter (CPU, lightweight)
|
||||
# → showinfo → MJPEG piped to stdout
|
||||
#
|
||||
# Flush trick: select the scene-change frame AND the next 2 frames.
|
||||
# The pipeline has 2 levels of buffering (encoder + muxer), so we
|
||||
# need 2 flush frames to push the real scene-change frame out.
|
||||
# mod(selected_n,3) prevents chaining: after 2 flushes, selected_n
|
||||
# hits a multiple of 3 and the chain stops.
|
||||
scene_expr = f"gt(scene,{scene_threshold})"
|
||||
flush_expr = "eq(n,prev_selected_n+1)*mod(selected_n,3)"
|
||||
select_expr = f"{scene_expr}+{flush_expr}"
|
||||
if flush_frames > 0:
|
||||
# Flush trick: select extra frames after each scene change to push
|
||||
# the real frame through the encoder+muxer buffer pipeline.
|
||||
# mod(selected_n, 1+flush_frames) prevents chaining.
|
||||
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")
|
||||
scene_out = ffmpeg.output(
|
||||
scene_stream, "pipe:1",
|
||||
|
||||
@@ -19,6 +19,7 @@ from cht.config import (
|
||||
STREAM_PORT,
|
||||
RELAY_PORT,
|
||||
SCENE_THRESHOLD,
|
||||
SCENE_FLUSH_FRAMES,
|
||||
SESSIONS_DIR,
|
||||
AUDIO_EXTRACT_INTERVAL,
|
||||
AUDIO_SAFETY_MARGIN,
|
||||
@@ -197,6 +198,7 @@ class StreamManager:
|
||||
node = ff.receive_record_relay_and_detect(
|
||||
self.stream_url, self.recording_path, self.relay_url,
|
||||
scene_threshold=self.scene_threshold,
|
||||
flush_frames=SCENE_FLUSH_FRAMES,
|
||||
)
|
||||
proc = ff.run_async(node, pipe_stdout=True, pipe_stderr=True)
|
||||
self._procs["recorder"] = proc
|
||||
|
||||
Reference in New Issue
Block a user