diff --git a/frigate/http.py b/frigate/http.py index 0325a5578..a6d2f374c 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -28,7 +28,7 @@ from playhouse.shortcuts import model_to_dict from frigate.const import CLIPS_DIR from frigate.models import Event, Recordings from frigate.stats import stats_snapshot -from frigate.util import get_keyframe_timestamps_and_adjusted_offset +from frigate.util import get_adjusted_offset from frigate.version import VERSION logger = logging.getLogger(__name__) @@ -847,24 +847,16 @@ def vod_ts(camera, start_ts, end_ts): for recording in recordings: clip = {"type": "source", "path": recording.path} duration = int(recording.duration * 1000) + clip["keyFrameDurations"] = [duration] + # Determine if offset is needed for first clip - target_offset = ( - int((start_ts - recording.start_time) * 1000) - if recording.start_time < start_ts - else 0 - ) - # If we are clipping, we need to find the keyframe before start_ts and start - # from there. Otherwise we may lose data and our durations will be incorrect. - # Also get the keyframe timestamps so we can use "keyFrameDurations" below. - keyframe_timestamps, offset = get_keyframe_timestamps_and_adjusted_offset( - recording.path, target_offset - ) - if keyframe_timestamps: - clip["keyFrameDurations"] = [ - j - i for i, j in zip(keyframe_timestamps[:-1], keyframe_timestamps[1:]) - ] + [duration - keyframe_timestamps[-1]] - clip["clipFrom"] = offset - duration -= offset + if (target_offset := int((start_ts - recording.start_time) * 1000)) > 0: + # If we are clipping, we need to find the keyframe before start_ts and start + # from there. Otherwise we may lose data and our durations will be incorrect. + offset = get_adjusted_offset(recording.path, target_offset) + clip["clipFrom"] = offset + duration -= offset + # Determine if we need to end the last clip early if recording.end_time > end_ts: duration -= int((recording.end_time - end_ts) * 1000) diff --git a/frigate/util.py b/frigate/util.py index 075edc3a6..8520789d9 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -692,15 +692,13 @@ class SharedMemoryFrameManager(FrameManager): del self.shm_store[name] -def get_keyframe_timestamps_and_adjusted_offset( - source: str, target_offset: int -) -> tuple[list[int], int]: - """Get timestamp metadata from the source. +def get_adjusted_offset(source: str, target_offset: int) -> int: + """Get the timestamp of the nearest keyframe before target_offset. This is used to pass information to the VOD module and is useful for codec variants - with long or variable keyframe intervals. - Returns a tuple of: 1) the keyframe timestamp locations for this source - and 2) the timestamp of the nearest keyframe before target_offset.""" + with long or variable keyframe intervals.""" + if target_offset == 0: + return 0 ffprobe_cmd = [ "ffprobe", "-skip_frame", @@ -717,10 +715,8 @@ def get_keyframe_timestamps_and_adjusted_offset( ] p = sp.run(ffprobe_cmd, capture_output=True) keyframe_timestamps = [int(1000 * float(pts)) for pts in p.stdout.split()] - if target_offset == 0: - return keyframe_timestamps, 0 for ts in reversed(keyframe_timestamps): if ts <= target_offset: - return keyframe_timestamps, ts + return ts logger.warning("Couldn't find starting keyframe for VOD clip") - return keyframe_timestamps, 0 + return 0