consisten one behind

This commit is contained in:
2026-04-03 11:36:59 -03:00
parent 741bf995a8
commit 101ed10ca1
2 changed files with 5 additions and 12 deletions

View File

@@ -97,13 +97,13 @@ def receive_record_relay_and_detect(stream_url, output_path, relay_url,
) )
# Scene detection: CUDA decode (GPU) → select filter (CPU, lightweight) # Scene detection: CUDA decode (GPU) → select filter (CPU, lightweight)
# → showinfo → MJPEG piped to stdout (avoids image2 muxer one-frame buffer) # → showinfo → MJPEG piped to stdout
select_expr = f"gt(scene,{scene_threshold})" select_expr = f"gt(scene,{scene_threshold})"
scene_stream = stream.filter("select", select_expr).filter("showinfo") scene_stream = stream.filter("select", select_expr).filter("showinfo")
scene_out = ffmpeg.output( scene_out = ffmpeg.output(
scene_stream, "pipe:1", scene_stream, "pipe:1",
f="image2pipe", vcodec="mjpeg", f="image2pipe", vcodec="mjpeg",
vsync="vfr", flush_packets=1, **{"q:v": "2"}, flush_packets=1, **{"q:v": "2", "fps_mode": "passthrough"},
) )
return ffmpeg.merge_outputs(file_out, relay_out, scene_out).global_args(*GLOBAL_ARGS) return ffmpeg.merge_outputs(file_out, relay_out, scene_out).global_args(*GLOBAL_ARGS)

View File

@@ -10,10 +10,8 @@ Architecture:
import json import json
import logging import logging
import os
import re import re
import time import time
from queue import Queue, Empty
from threading import Thread from threading import Thread
from cht.config import ( from cht.config import (
@@ -244,10 +242,9 @@ class StreamManager:
- stderr: parses showinfo lines, queues pts_time values - stderr: parses showinfo lines, queues pts_time values
- stdout: reads JPEG frames from pipe, pairs with queued timestamps, - stdout: reads JPEG frames from pipe, pairs with queued timestamps,
writes files to disk, fires callbacks immediately writes files to disk, fires callbacks immediately
showinfo fires before the JPEG encoder, so timestamps are always
queued before the corresponding JPEG data arrives on stdout.
""" """
from queue import Queue, Empty
import os
ts_queue = Queue() ts_queue = Queue()
def _read_stderr(): def _read_stderr():
@@ -269,13 +266,10 @@ class StreamManager:
buf = b"" buf = b""
raw_fd = proc.stdout.fileno() raw_fd = proc.stdout.fileno()
while True: while True:
# os.read on the raw fd returns as soon as ANY data is available
# (no Python buffered-IO blocking waiting to fill a buffer)
chunk = os.read(raw_fd, 65536) chunk = os.read(raw_fd, 65536)
if not chunk: if not chunk:
break break
buf += chunk buf += chunk
# Split JPEG frames by SOI (0xFFD8) and EOI (0xFFD9) markers
while True: while True:
soi = buf.find(b"\xff\xd8") soi = buf.find(b"\xff\xd8")
if soi < 0: if soi < 0:
@@ -283,12 +277,11 @@ class StreamManager:
break break
eoi = buf.find(b"\xff\xd9", soi + 2) eoi = buf.find(b"\xff\xd9", soi + 2)
if eoi < 0: if eoi < 0:
buf = buf[soi:] # keep from SOI, need more data buf = buf[soi:]
break break
jpeg_data = buf[soi:eoi + 2] jpeg_data = buf[soi:eoi + 2]
buf = buf[eoi + 2:] buf = buf[eoi + 2:]
# Get timestamp (showinfo fires before encode, so it's queued)
try: try:
pts_time = ts_queue.get(timeout=2.0) pts_time = ts_queue.get(timeout=2.0)
except Empty: except Empty: