refactor: update FFmpegRTSPReader to use JPG format for single frame updates and improve image quality
All checks were successful
Build Worker Base and Application Images / check-base-changes (push) Successful in 7s
Build Worker Base and Application Images / build-base (push) Has been skipped
Build Worker Base and Application Images / build-docker (push) Successful in 2m48s
Build Worker Base and Application Images / deploy-stack (push) Successful in 10s
All checks were successful
Build Worker Base and Application Images / check-base-changes (push) Successful in 7s
Build Worker Base and Application Images / build-base (push) Has been skipped
Build Worker Base and Application Images / build-docker (push) Successful in 2m48s
Build Worker Base and Application Images / deploy-stack (push) Successful in 10s
This commit is contained in:
parent
95c39a008f
commit
73c3367681
1 changed files with 20 additions and 22 deletions
|
@ -94,16 +94,19 @@ class FFmpegRTSPReader:
|
||||||
self.temp_file = f"/tmp/claude/camera_{self.camera_id.replace(' ', '_')}.raw"
|
self.temp_file = f"/tmp/claude/camera_{self.camera_id.replace(' ', '_')}.raw"
|
||||||
os.makedirs("/tmp/claude", exist_ok=True)
|
os.makedirs("/tmp/claude", exist_ok=True)
|
||||||
|
|
||||||
|
# Change to JPG format which properly supports -update 1
|
||||||
|
self.temp_file = f"/tmp/claude/camera_{self.camera_id.replace(' ', '_')}.jpg"
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
'ffmpeg',
|
'ffmpeg',
|
||||||
'-hwaccel', 'cuda',
|
'-hwaccel', 'cuda',
|
||||||
'-hwaccel_device', '0',
|
'-hwaccel_device', '0',
|
||||||
'-rtsp_transport', 'tcp',
|
'-rtsp_transport', 'tcp',
|
||||||
'-i', self.rtsp_url,
|
'-i', self.rtsp_url,
|
||||||
'-f', 'rawvideo',
|
'-f', 'image2',
|
||||||
'-pix_fmt', 'bgr24',
|
'-update', '1', # This actually works with image2 format
|
||||||
|
'-q:v', '2', # High quality JPEG
|
||||||
'-an', # No audio
|
'-an', # No audio
|
||||||
'-update', '1', # Update single frame in place
|
|
||||||
'-y', # Overwrite output file
|
'-y', # Overwrite output file
|
||||||
self.temp_file
|
self.temp_file
|
||||||
]
|
]
|
||||||
|
@ -173,32 +176,27 @@ class FFmpegRTSPReader:
|
||||||
if self.frame_ready_event.wait(timeout=restart_check_interval):
|
if self.frame_ready_event.wait(timeout=restart_check_interval):
|
||||||
self.frame_ready_event.clear()
|
self.frame_ready_event.clear()
|
||||||
|
|
||||||
# Read current frame with concurrency safety
|
# Read JPEG frame with concurrency safety
|
||||||
try:
|
try:
|
||||||
# Try to read frame multiple times to handle race conditions
|
# Try to read JPEG multiple times to handle race conditions
|
||||||
frame_data = None
|
frame = None
|
||||||
for attempt in range(3):
|
for attempt in range(3):
|
||||||
try:
|
try:
|
||||||
with open(self.temp_file, 'rb') as f:
|
# Read and decode JPEG directly
|
||||||
frame_data = f.read(bytes_per_frame)
|
frame = cv2.imread(self.temp_file)
|
||||||
|
|
||||||
# Validate we got a complete frame
|
if frame is not None and frame.shape == (self.height, self.width, 3):
|
||||||
if len(frame_data) == bytes_per_frame:
|
break
|
||||||
break
|
else:
|
||||||
else:
|
logger.debug(f"Camera {self.camera_id}: Invalid frame shape or None, attempt {attempt+1}")
|
||||||
logger.debug(f"Camera {self.camera_id}: Partial read {len(frame_data)}/{bytes_per_frame}, attempt {attempt+1}")
|
time.sleep(0.01) # Brief wait before retry
|
||||||
time.sleep(0.01) # Brief wait before retry
|
|
||||||
|
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
logger.debug(f"Camera {self.camera_id}: Read error on attempt {attempt+1}: {e}")
|
logger.debug(f"Camera {self.camera_id}: Read error on attempt {attempt+1}: {e}")
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
if frame_data and len(frame_data) == bytes_per_frame:
|
if frame is not None:
|
||||||
# Convert to numpy array
|
# Call frame callback directly
|
||||||
frame = np.frombuffer(frame_data, dtype=np.uint8)
|
|
||||||
frame = frame.reshape((self.height, self.width, 3))
|
|
||||||
|
|
||||||
# Call frame callback directly - trust the retry logic caught corruption
|
|
||||||
if self.frame_callback:
|
if self.frame_callback:
|
||||||
self.frame_callback(self.camera_id, frame)
|
self.frame_callback(self.camera_id, frame)
|
||||||
|
|
||||||
|
@ -207,10 +205,10 @@ class FFmpegRTSPReader:
|
||||||
# Log progress
|
# Log progress
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if current_time - last_log_time >= 30:
|
if current_time - last_log_time >= 30:
|
||||||
logger.info(f"Camera {self.camera_id}: {frame_count} frames processed reactively")
|
logger.info(f"Camera {self.camera_id}: {frame_count} JPEG frames processed reactively")
|
||||||
last_log_time = current_time
|
last_log_time = current_time
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Camera {self.camera_id}: Failed to read complete frame after retries")
|
logger.debug(f"Camera {self.camera_id}: Failed to read valid JPEG after retries")
|
||||||
|
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
logger.debug(f"Camera {self.camera_id}: File read error: {e}")
|
logger.debug(f"Camera {self.camera_id}: File read error: {e}")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue