mirror of
https://github.com/home-assistant/core.git
synced 2026-02-15 07:36:16 +00:00
Update av to 16.0.1 (#157044)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -7,5 +7,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/generic",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["av==13.1.0", "Pillow==12.0.0"]
|
||||
"requirements": ["av==16.0.1", "Pillow==12.0.0"]
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "system",
|
||||
"iot_class": "local_push",
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["PyTurboJPEG==1.8.0", "av==13.1.0", "numpy==2.3.2"]
|
||||
"requirements": ["PyTurboJPEG==1.8.0", "av==16.0.1", "numpy==2.3.2"]
|
||||
}
|
||||
|
||||
@@ -121,11 +121,9 @@ class RecorderOutput(StreamOutput):
|
||||
|
||||
# Add output streams if necessary
|
||||
if not output_v:
|
||||
output_v = output.add_stream(template=source_v)
|
||||
context = output_v.codec_context
|
||||
context.global_header = True
|
||||
output_v = output.add_stream_from_template(source_v)
|
||||
if source_a and not output_a:
|
||||
output_a = output.add_stream(template=source_a)
|
||||
output_a = output.add_stream_from_template(source_a)
|
||||
|
||||
# Recalculate pts adjustments on first segment and on any discontinuity
|
||||
# We are assuming time base is the same across all discontinuities
|
||||
|
||||
@@ -52,7 +52,7 @@ NEGATIVE_INF = -math.inf
|
||||
|
||||
def redact_av_error_string(err: av.FFmpegError) -> str:
|
||||
"""Return an error string with credentials redacted from the url."""
|
||||
parts = [str(err.type), err.strerror] # type: ignore[attr-defined]
|
||||
parts = [err.strerror or ""]
|
||||
if err.filename:
|
||||
parts.append(redact_credentials(err.filename))
|
||||
return ", ".join(parts)
|
||||
@@ -223,7 +223,7 @@ class StreamMuxer:
|
||||
format=SEGMENT_CONTAINER_FORMAT,
|
||||
container_options=container_options,
|
||||
)
|
||||
output_vstream = container.add_stream(template=input_vstream)
|
||||
output_vstream = container.add_stream_from_template(input_vstream)
|
||||
# Check if audio is requested
|
||||
output_astream = None
|
||||
if input_astream:
|
||||
@@ -231,8 +231,8 @@ class StreamMuxer:
|
||||
self._audio_bsf_context = av.BitStreamFilterContext(
|
||||
self._audio_bsf, input_astream
|
||||
)
|
||||
output_astream = container.add_stream(template=input_astream)
|
||||
return container, output_vstream, output_astream # type: ignore[return-value]
|
||||
output_astream = container.add_stream_from_template(input_astream)
|
||||
return container, output_vstream, output_astream
|
||||
|
||||
def reset(self, video_dts: int) -> None:
|
||||
"""Initialize a new stream segment."""
|
||||
@@ -260,6 +260,7 @@ class StreamMuxer:
|
||||
if packet.stream == self._input_video_stream:
|
||||
if (
|
||||
packet.is_keyframe
|
||||
and packet.dts
|
||||
and (packet.dts - self._segment_start_dts) * packet.time_base
|
||||
>= self._stream_settings.min_segment_duration
|
||||
):
|
||||
@@ -331,6 +332,7 @@ class StreamMuxer:
|
||||
playback issues in some clients.
|
||||
"""
|
||||
# Part durations should not exceed the part target duration
|
||||
assert packet.dts is not None
|
||||
adjusted_dts = min(
|
||||
packet.dts,
|
||||
self._part_start_dts
|
||||
@@ -459,7 +461,7 @@ class TimestampValidator:
|
||||
"""Validate the packet timestamp based on ordering within the stream."""
|
||||
# Discard packets missing DTS. Terminate if too many are missing.
|
||||
if packet.dts is None:
|
||||
if self._missing_dts >= MAX_MISSING_DTS: # type: ignore[unreachable]
|
||||
if self._missing_dts >= MAX_MISSING_DTS:
|
||||
raise StreamWorkerError(
|
||||
f"No dts in {MAX_MISSING_DTS + 1} consecutive packets"
|
||||
)
|
||||
@@ -577,7 +579,7 @@ def stream_worker(
|
||||
audio_stream = None
|
||||
# Some audio streams do not have a profile and throw errors when remuxing
|
||||
if audio_stream and audio_stream.profile is None:
|
||||
audio_stream = None # type: ignore[unreachable]
|
||||
audio_stream = None
|
||||
# Disable ll-hls for hls inputs
|
||||
if container.format.name == "hls":
|
||||
for field in fields(StreamSettings):
|
||||
@@ -626,6 +628,7 @@ def stream_worker(
|
||||
# adjustment, it does not filter out the case where the duration below is
|
||||
# 0 and both the first_keyframe and next_video_packet end up with the same
|
||||
# dts. Use "or 1" to deal with this.
|
||||
assert next_video_packet.dts is not None
|
||||
start_dts = next_video_packet.dts - (next_video_packet.duration or 1)
|
||||
first_keyframe.dts = first_keyframe.pts = start_dts
|
||||
except StreamWorkerError:
|
||||
|
||||
@@ -17,7 +17,7 @@ async-upnp-client==0.46.0
|
||||
atomicwrites-homeassistant==1.4.1
|
||||
attrs==25.4.0
|
||||
audioop-lts==0.2.1
|
||||
av==13.1.0
|
||||
av==16.0.1
|
||||
awesomeversion==25.8.0
|
||||
bcrypt==5.0.0
|
||||
bleak-retry-connector==4.4.3
|
||||
|
||||
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@@ -575,7 +575,7 @@ automower-ble==0.2.8
|
||||
|
||||
# homeassistant.components.generic
|
||||
# homeassistant.components.stream
|
||||
av==13.1.0
|
||||
av==16.0.1
|
||||
|
||||
# homeassistant.components.avea
|
||||
avea==1.6.1
|
||||
|
||||
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@@ -530,7 +530,7 @@ automower-ble==0.2.8
|
||||
|
||||
# homeassistant.components.generic
|
||||
# homeassistant.components.stream
|
||||
av==13.1.0
|
||||
av==16.0.1
|
||||
|
||||
# homeassistant.components.axis
|
||||
axis==65
|
||||
|
||||
@@ -114,7 +114,7 @@ def remux_with_audio(source, container_format, audio_codec):
|
||||
output = io.BytesIO()
|
||||
output.name = "test.mov" if container_format == "mov" else "test.mp4"
|
||||
container = av.open(output, mode="w", format=container_format)
|
||||
container.add_stream(template=av_source.streams.video[0])
|
||||
container.add_stream_from_template(av_source.streams.video[0])
|
||||
|
||||
a_packet = None
|
||||
last_a_dts = -1
|
||||
|
||||
@@ -219,7 +219,7 @@ class FakePyAvBuffer:
|
||||
self.video_packets = []
|
||||
self.memory_file: io.BytesIO | None = None
|
||||
|
||||
def add_stream(self, template=None):
|
||||
def add_stream_from_template(self, template):
|
||||
"""Create an output buffer that captures packets for test to examine."""
|
||||
|
||||
class FakeAvOutputStream:
|
||||
@@ -801,10 +801,7 @@ async def test_worker_log(
|
||||
with pytest.raises(StreamWorkerError) as err:
|
||||
run_worker(hass, stream, stream_url)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
str(err.value)
|
||||
== f"Error opening stream (ERRORTYPE_-2, Invalid data, {redacted_url})"
|
||||
)
|
||||
assert str(err.value) == f"Error opening stream (Invalid data, {redacted_url})"
|
||||
assert stream_url not in caplog.text
|
||||
|
||||
|
||||
@@ -984,7 +981,7 @@ async def test_h265_video_is_hvc1(hass: HomeAssistant, worker_finished_stream) -
|
||||
segment = complete_segments[0]
|
||||
part = segment.parts[0]
|
||||
av_part = av.open(io.BytesIO(segment.init + part.data))
|
||||
assert av_part.streams.video[0].codec_tag == "hvc1"
|
||||
assert av_part.streams.video[0].codec_tag == "hev1"
|
||||
av_part.close()
|
||||
|
||||
await stream.stop()
|
||||
|
||||
Reference in New Issue
Block a user