mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Switch back to av 13.1.0 (#129699)
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": ["ha-av==10.1.1", "Pillow==10.4.0"]
|
||||
"requirements": ["av==13.1.0", "Pillow==10.4.0"]
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ from .const import (
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from av import Packet
|
||||
from av.video.codeccontext import VideoCodecContext
|
||||
from av import Packet, VideoCodecContext
|
||||
|
||||
from homeassistant.components.camera import DynamicStreamSettings
|
||||
|
||||
@ -509,9 +508,8 @@ class KeyFrameConverter:
|
||||
frames = self._codec_context.decode(None)
|
||||
break
|
||||
except EOFError:
|
||||
_LOGGER.debug("Codec context needs flushing, attempting to reopen")
|
||||
self._codec_context.close()
|
||||
self._codec_context.open()
|
||||
_LOGGER.debug("Codec context needs flushing")
|
||||
self._codec_context.flush_buffers()
|
||||
else:
|
||||
_LOGGER.debug("Unable to decode keyframe")
|
||||
return
|
||||
|
@ -7,5 +7,5 @@
|
||||
"integration_type": "system",
|
||||
"iot_class": "local_push",
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["PyTurboJPEG==1.7.5", "ha-av==10.1.1", "numpy==1.26.4"]
|
||||
"requirements": ["PyTurboJPEG==1.7.5", "av==13.1.0", "numpy==1.26.4"]
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ 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)),
|
||||
"video_track_timescale": str(int(1 / source_v.time_base)), # type: ignore[operator]
|
||||
"movflags": "frag_keyframe+empty_moov",
|
||||
"min_frag_duration": str(self.stream_settings.min_segment_duration),
|
||||
}
|
||||
@ -132,21 +132,23 @@ class RecorderOutput(StreamOutput):
|
||||
last_stream_id = segment.stream_id
|
||||
pts_adjuster["video"] = int(
|
||||
(running_duration - source.start_time)
|
||||
/ (av.time_base * source_v.time_base)
|
||||
/ (av.time_base * source_v.time_base) # type: ignore[operator]
|
||||
)
|
||||
if source_a:
|
||||
pts_adjuster["audio"] = int(
|
||||
(running_duration - source.start_time)
|
||||
/ (av.time_base * source_a.time_base)
|
||||
/ (av.time_base * source_a.time_base) # type: ignore[operator]
|
||||
)
|
||||
|
||||
# Remux video
|
||||
for packet in source.demux():
|
||||
if packet.dts is None:
|
||||
if packet.pts is None:
|
||||
continue
|
||||
packet.pts += pts_adjuster[packet.stream.type]
|
||||
packet.dts += pts_adjuster[packet.stream.type]
|
||||
packet.stream = output_v if packet.stream.type == "video" else output_a
|
||||
packet.pts += pts_adjuster[packet.stream.type] # type: ignore[operator]
|
||||
packet.dts += pts_adjuster[packet.stream.type] # type: ignore[operator]
|
||||
stream = output_v if packet.stream.type == "video" else output_a
|
||||
assert stream
|
||||
packet.stream = stream
|
||||
output.mux(packet)
|
||||
|
||||
running_duration += source.duration - source.start_time
|
||||
|
@ -16,7 +16,6 @@ import av
|
||||
import av.audio
|
||||
import av.container
|
||||
import av.stream
|
||||
import av.video
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util import dt as dt_util
|
||||
@ -53,8 +52,8 @@ class StreamWorkerError(Exception):
|
||||
|
||||
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]
|
||||
if err.filename is not None:
|
||||
parts = [str(err.type), err.strerror] # type: ignore[attr-defined]
|
||||
if err.filename:
|
||||
parts.append(redact_credentials(err.filename))
|
||||
return ", ".join(parts)
|
||||
|
||||
@ -130,19 +129,19 @@ class StreamMuxer:
|
||||
_segment_start_dts: int
|
||||
_memory_file: BytesIO
|
||||
_av_output: av.container.OutputContainer
|
||||
_output_video_stream: av.video.VideoStream
|
||||
_output_video_stream: av.VideoStream
|
||||
_output_audio_stream: av.audio.AudioStream | None
|
||||
_segment: Segment | None
|
||||
# the following 2 member variables are used for Part formation
|
||||
_memory_file_pos: int
|
||||
_part_start_dts: int
|
||||
_part_start_dts: float
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
video_stream: av.video.VideoStream,
|
||||
video_stream: av.VideoStream,
|
||||
audio_stream: av.audio.AudioStream | None,
|
||||
audio_bsf: av.BitStreamFilter | None,
|
||||
audio_bsf: str | None,
|
||||
stream_state: StreamState,
|
||||
stream_settings: StreamSettings,
|
||||
) -> None:
|
||||
@ -161,11 +160,11 @@ class StreamMuxer:
|
||||
self,
|
||||
memory_file: BytesIO,
|
||||
sequence: int,
|
||||
input_vstream: av.video.VideoStream,
|
||||
input_vstream: av.VideoStream,
|
||||
input_astream: av.audio.AudioStream | None,
|
||||
) -> tuple[
|
||||
av.container.OutputContainer,
|
||||
av.video.VideoStream,
|
||||
av.VideoStream,
|
||||
av.audio.AudioStream | None,
|
||||
]:
|
||||
"""Make a new av OutputContainer and add output streams."""
|
||||
@ -182,7 +181,7 @@ class StreamMuxer:
|
||||
# in test_durations
|
||||
"avoid_negative_ts": "make_non_negative",
|
||||
"fragment_index": str(sequence + 1),
|
||||
"video_track_timescale": str(int(1 / input_vstream.time_base)),
|
||||
"video_track_timescale": str(int(1 / input_vstream.time_base)), # type: ignore[operator]
|
||||
# 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
|
||||
@ -233,12 +232,11 @@ class StreamMuxer:
|
||||
output_astream = None
|
||||
if input_astream:
|
||||
if self._audio_bsf:
|
||||
self._audio_bsf_context = self._audio_bsf.create()
|
||||
self._audio_bsf_context.set_input_stream(input_astream)
|
||||
output_astream = container.add_stream(
|
||||
template=self._audio_bsf_context or input_astream
|
||||
)
|
||||
return container, output_vstream, output_astream
|
||||
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]
|
||||
|
||||
def reset(self, video_dts: int) -> None:
|
||||
"""Initialize a new stream segment."""
|
||||
@ -279,11 +277,11 @@ class StreamMuxer:
|
||||
self._part_has_keyframe |= packet.is_keyframe
|
||||
|
||||
elif packet.stream == self._input_audio_stream:
|
||||
assert self._output_audio_stream
|
||||
if self._audio_bsf_context:
|
||||
self._audio_bsf_context.send(packet)
|
||||
while packet := self._audio_bsf_context.recv():
|
||||
packet.stream = self._output_audio_stream
|
||||
self._av_output.mux(packet)
|
||||
for audio_packet in self._audio_bsf_context.filter(packet):
|
||||
audio_packet.stream = self._output_audio_stream
|
||||
self._av_output.mux(audio_packet)
|
||||
return
|
||||
packet.stream = self._output_audio_stream
|
||||
self._av_output.mux(packet)
|
||||
@ -465,7 +463,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:
|
||||
if self._missing_dts >= MAX_MISSING_DTS: # type: ignore[unreachable]
|
||||
raise StreamWorkerError(
|
||||
f"No dts in {MAX_MISSING_DTS+1} consecutive packets"
|
||||
)
|
||||
@ -492,7 +490,7 @@ def is_keyframe(packet: av.Packet) -> Any:
|
||||
|
||||
def get_audio_bitstream_filter(
|
||||
packets: Iterator[av.Packet], audio_stream: Any
|
||||
) -> av.BitStreamFilterContext | None:
|
||||
) -> str | None:
|
||||
"""Return the aac_adtstoasc bitstream filter if ADTS AAC is detected."""
|
||||
if not audio_stream:
|
||||
return None
|
||||
@ -509,7 +507,7 @@ def get_audio_bitstream_filter(
|
||||
_LOGGER.debug(
|
||||
"ADTS AAC detected. Adding aac_adtstoaac bitstream filter"
|
||||
)
|
||||
return av.BitStreamFilter("aac_adtstoasc")
|
||||
return "aac_adtstoasc"
|
||||
break
|
||||
return None
|
||||
|
||||
@ -547,7 +545,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
|
||||
audio_stream = None # type: ignore[unreachable]
|
||||
# Disable ll-hls for hls inputs
|
||||
if container.format.name == "hls":
|
||||
for field in fields(StreamSettings):
|
||||
@ -562,8 +560,8 @@ def stream_worker(
|
||||
stream_state.diagnostics.set_value("audio_codec", audio_stream.name)
|
||||
|
||||
dts_validator = TimestampValidator(
|
||||
int(1 / video_stream.time_base),
|
||||
int(1 / audio_stream.time_base) if audio_stream else 1,
|
||||
int(1 / video_stream.time_base), # type: ignore[operator]
|
||||
int(1 / audio_stream.time_base) if audio_stream else 1, # type: ignore[operator]
|
||||
)
|
||||
container_packets = PeekIterator(
|
||||
filter(dts_validator.is_valid, container.demux((video_stream, audio_stream)))
|
||||
|
@ -13,6 +13,7 @@ async-interrupt==1.2.0
|
||||
async-upnp-client==0.41.0
|
||||
atomicwrites-homeassistant==1.4.1
|
||||
attrs==24.2.0
|
||||
av==13.1.0
|
||||
awesomeversion==24.6.0
|
||||
bcrypt==4.2.0
|
||||
bleak-retry-connector==3.6.0
|
||||
@ -27,7 +28,6 @@ cryptography==43.0.1
|
||||
dbus-fast==2.24.3
|
||||
fnv-hash-fast==1.0.2
|
||||
go2rtc-client==0.0.1b3
|
||||
ha-av==10.1.1
|
||||
ha-ffmpeg==3.2.1
|
||||
habluetooth==3.6.0
|
||||
hass-nabucasa==0.83.0
|
||||
|
@ -526,6 +526,10 @@ autarco==3.1.0
|
||||
# homeassistant.components.husqvarna_automower_ble
|
||||
automower-ble==0.2.0
|
||||
|
||||
# homeassistant.components.generic
|
||||
# homeassistant.components.stream
|
||||
av==13.1.0
|
||||
|
||||
# homeassistant.components.avea
|
||||
# avea==1.5.1
|
||||
|
||||
@ -1064,10 +1068,6 @@ guppy3==3.1.4.post1
|
||||
# homeassistant.components.iaqualink
|
||||
h2==4.1.0
|
||||
|
||||
# homeassistant.components.generic
|
||||
# homeassistant.components.stream
|
||||
ha-av==10.1.1
|
||||
|
||||
# homeassistant.components.ffmpeg
|
||||
ha-ffmpeg==3.2.1
|
||||
|
||||
|
@ -481,6 +481,10 @@ autarco==3.1.0
|
||||
# homeassistant.components.husqvarna_automower_ble
|
||||
automower-ble==0.2.0
|
||||
|
||||
# homeassistant.components.generic
|
||||
# homeassistant.components.stream
|
||||
av==13.1.0
|
||||
|
||||
# homeassistant.components.axis
|
||||
axis==63
|
||||
|
||||
@ -902,10 +906,6 @@ guppy3==3.1.4.post1
|
||||
# homeassistant.components.iaqualink
|
||||
h2==4.1.0
|
||||
|
||||
# homeassistant.components.generic
|
||||
# homeassistant.components.stream
|
||||
ha-av==10.1.1
|
||||
|
||||
# homeassistant.components.ffmpeg
|
||||
ha-ffmpeg==3.2.1
|
||||
|
||||
|
Reference in New Issue
Block a user