Fix durations and decrase keyframe interval to ensure smooth scrubbing

This commit is contained in:
Nick Mowen 2023-11-29 07:53:58 -07:00
parent 186403cd3e
commit 637e118018
2 changed files with 23 additions and 26 deletions

View File

@ -27,9 +27,8 @@ logger = logging.getLogger(__name__)
FOLDER_PREVIEW_FRAMES = "preview_frames"
PREVIEW_OUTPUT_FPS = 1
PREVIEW_SEGMENT_DURATION = 3600 # one hour
PREVIEW_KEYFRAME_INTERVAL = (
PREVIEW_SEGMENT_DURATION / 10
) # maximum of 8 keyframes per segment
# important to have lower keyframe to maintain scrubbing performance
PREVIEW_KEYFRAME_INTERVAL = 60
def get_cache_image_name(camera: str, frame_time: float) -> str:
@ -50,7 +49,7 @@ class FFMpegConverter(threading.Thread):
inter_process_queue: mp.Queue,
):
threading.Thread.__init__(self)
self.name = f"{config.name}_output_converter"
self.name = f"{config.name}_preview_converter"
self.camera = config.name
self.frame_times = frame_times
self.inter_process_queue = inter_process_queue
@ -69,18 +68,23 @@ class FFMpegConverter(threading.Thread):
def run(self) -> None:
# generate input list
last = self.frame_times[0]
item_count = len(self.frame_times)
playlist = []
for t in self.frame_times:
playlist.append(f"file '{get_cache_image_name(self.camera, t)}'")
playlist.append(f"duration {t - last}")
last = t
for t_idx in range(0, item_count):
if t_idx == item_count - 1:
# last frame does not get a duration
playlist.append(
f"file '{get_cache_image_name(self.camera, self.frame_times[t_idx])}'"
)
continue
# last frame must be included again with no duration
playlist.append(
f"file '{get_cache_image_name(self.camera, self.frame_times[-1])}'"
)
playlist.append(
f"file '{get_cache_image_name(self.camera, self.frame_times[t_idx])}'"
)
playlist.append(
f"duration {self.frame_times[t_idx + 1] - self.frame_times[t_idx]}"
)
p = sp.run(
self.ffmpeg_cmd.split(" "),
@ -98,7 +102,7 @@ class FFMpegConverter(threading.Thread):
(
INSERT_PREVIEW,
{
Previews.id: f"{end}-{start}",
Previews.id: f"{self.camera}_{end}",
Previews.camera: self.camera,
Previews.path: self.path,
Previews.start_time: start,
@ -176,8 +180,7 @@ class PreviewRecorder:
self.last_output_time = frame_time
return True
# TODO think of real motion box logic to use
if len(motion_boxes) % 2 == 1:
if len(motion_boxes) > 0:
self.last_output_time = frame_time
return True

View File

@ -312,17 +312,14 @@ def yuv_crop_and_resize(frame, region, height=None):
# copy u2
yuv_cropped_frame[
size + uv_channel_y_offset : size + uv_channel_y_offset + uv_crop_height,
size // 2
+ uv_channel_x_offset : size // 2
size // 2 + uv_channel_x_offset : size // 2
+ uv_channel_x_offset
+ uv_crop_width,
] = frame[u2[1] : u2[3], u2[0] : u2[2]]
# copy v1
yuv_cropped_frame[
size
+ size // 4
+ uv_channel_y_offset : size
size + size // 4 + uv_channel_y_offset : size
+ size // 4
+ uv_channel_y_offset
+ uv_crop_height,
@ -331,14 +328,11 @@ def yuv_crop_and_resize(frame, region, height=None):
# copy v2
yuv_cropped_frame[
size
+ size // 4
+ uv_channel_y_offset : size
size + size // 4 + uv_channel_y_offset : size
+ size // 4
+ uv_channel_y_offset
+ uv_crop_height,
size // 2
+ uv_channel_x_offset : size // 2
size // 2 + uv_channel_x_offset : size // 2
+ uv_channel_x_offset
+ uv_crop_width,
] = frame[v2[1] : v2[3], v2[0] : v2[2]]