From f7103da81867573b146395ab71f6e0d6cc6fe792 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 2 Nov 2024 19:03:32 +0100 Subject: [PATCH] Refactor av.open calls to support type annotations (#129688) --- homeassistant/components/stream/recorder.py | 13 ++- homeassistant/components/stream/worker.py | 107 ++++++++++---------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/homeassistant/components/stream/recorder.py b/homeassistant/components/stream/recorder.py index 6dfc09891b7..aa5e08a1594 100644 --- a/homeassistant/components/stream/recorder.py +++ b/homeassistant/components/stream/recorder.py @@ -105,17 +105,16 @@ class RecorderOutput(StreamOutput): # Create output on first segment if not output: + container_options: dict[str, str] = { + "video_track_timescale": str(int(1 / source_v.time_base)), + "movflags": "frag_keyframe+empty_moov", + "min_frag_duration": str(self.stream_settings.min_segment_duration), + } output = av.open( self.video_path + ".tmp", "w", format=RECORDER_CONTAINER_FORMAT, - container_options={ - "video_track_timescale": str(int(1 / source_v.time_base)), - "movflags": "frag_keyframe+empty_moov", - "min_frag_duration": str( - self.stream_settings.min_segment_duration - ), - }, + container_options=container_options, ) # Add output streams if necessary diff --git a/homeassistant/components/stream/worker.py b/homeassistant/components/stream/worker.py index 0d72a9b0818..1661a5b673f 100644 --- a/homeassistant/components/stream/worker.py +++ b/homeassistant/components/stream/worker.py @@ -164,63 +164,64 @@ class StreamMuxer: av.audio.stream.AudioStream | None, ]: """Make a new av OutputContainer and add output streams.""" + container_options: dict[str, str] = { + # Removed skip_sidx - see: + # https://github.com/home-assistant/core/pull/39970 + # "cmaf" flag replaces several of the movflags used, + # but too recent to use for now + "movflags": "frag_custom+empty_moov+default_base_moof+frag_discont+negative_cts_offsets+skip_trailer+delay_moov", + # Sometimes the first segment begins with negative timestamps, + # and this setting just + # adjusts the timestamps in the output from that segment to start + # from 0. Helps from having to make some adjustments + # in test_durations + "avoid_negative_ts": "make_non_negative", + "fragment_index": str(sequence + 1), + "video_track_timescale": str(int(1 / input_vstream.time_base)), + # Only do extra fragmenting if we are using ll_hls + # Let ffmpeg do the work using frag_duration + # Fragment durations may exceed the 15% allowed variance but it seems ok + **( + { + "movflags": "empty_moov+default_base_moof+frag_discont+negative_cts_offsets+skip_trailer+delay_moov", + # Create a fragment every TARGET_PART_DURATION. The data from + # each fragment is stored in a "Part" that can be combined with + # the data from all the other "Part"s, plus an init section, + # to reconstitute the data in a "Segment". + # + # The LL-HLS spec allows for a fragment's duration to be within + # the range [0.85x,1.0x] of the part target duration. We use the + # frag_duration option to tell ffmpeg to try to cut the + # fragments when they reach frag_duration. However, + # the resulting fragments can have variability in their + # durations and can end up being too short or too long. With a + # video track with no audio, the discrete nature of frames means + # that the frame at the end of a fragment will sometimes extend + # slightly beyond the desired frag_duration. + # + # If there are two tracks, as in the case of a video feed with + # audio, there is an added wrinkle as the fragment cut seems to + # be done on the first track that crosses the desired threshold, + # and cutting on the audio track may also result in a shorter + # video fragment than desired. + # + # Given this, our approach is to give ffmpeg a frag_duration + # somewhere in the middle of the range, hoping that the parts + # stay pretty well bounded, and we adjust the part durations + # a bit in the hls metadata so that everything "looks" ok. + "frag_duration": str( + int(self._stream_settings.part_target_duration * 9e5) + ), + } + if self._stream_settings.ll_hls + else {} + ), + } container = av.open( memory_file, mode="w", format=SEGMENT_CONTAINER_FORMAT, - container_options={ - # Removed skip_sidx - see: - # https://github.com/home-assistant/core/pull/39970 - # "cmaf" flag replaces several of the movflags used, - # but too recent to use for now - "movflags": "frag_custom+empty_moov+default_base_moof+frag_discont+negative_cts_offsets+skip_trailer+delay_moov", - # Sometimes the first segment begins with negative timestamps, - # and this setting just - # adjusts the timestamps in the output from that segment to start - # from 0. Helps from having to make some adjustments - # in test_durations - "avoid_negative_ts": "make_non_negative", - "fragment_index": str(sequence + 1), - "video_track_timescale": str(int(1 / input_vstream.time_base)), - # Only do extra fragmenting if we are using ll_hls - # Let ffmpeg do the work using frag_duration - # Fragment durations may exceed the 15% allowed variance but it seems ok - **( - { - "movflags": "empty_moov+default_base_moof+frag_discont+negative_cts_offsets+skip_trailer+delay_moov", - # Create a fragment every TARGET_PART_DURATION. The data from - # each fragment is stored in a "Part" that can be combined with - # the data from all the other "Part"s, plus an init section, - # to reconstitute the data in a "Segment". - # - # The LL-HLS spec allows for a fragment's duration to be within - # the range [0.85x,1.0x] of the part target duration. We use the - # frag_duration option to tell ffmpeg to try to cut the - # fragments when they reach frag_duration. However, - # the resulting fragments can have variability in their - # durations and can end up being too short or too long. With a - # video track with no audio, the discrete nature of frames means - # that the frame at the end of a fragment will sometimes extend - # slightly beyond the desired frag_duration. - # - # If there are two tracks, as in the case of a video feed with - # audio, there is an added wrinkle as the fragment cut seems to - # be done on the first track that crosses the desired threshold, - # and cutting on the audio track may also result in a shorter - # video fragment than desired. - # - # Given this, our approach is to give ffmpeg a frag_duration - # somewhere in the middle of the range, hoping that the parts - # stay pretty well bounded, and we adjust the part durations - # a bit in the hls metadata so that everything "looks" ok. - "frag_duration": str( - int(self._stream_settings.part_target_duration * 9e5) - ), - } - if self._stream_settings.ll_hls - else {} - ), - }, + container_options=container_options, ) output_vstream = container.add_stream(template=input_vstream) # Check if audio is requested