Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch back to av 13.1.0 #129699

Merged
merged 6 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/generic/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
8 changes: 3 additions & 5 deletions homeassistant/components/stream/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
)

if TYPE_CHECKING:
from av import Packet
from av.video.codeccontext import VideoCodecContext
from av import Packet, VideoCodecContext

from homeassistant.components.camera import DynamicStreamSettings

Expand Down Expand Up @@ -509,9 +508,8 @@ def _generate_image(self, width: int | None, height: int | None) -> None:
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
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/stream/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
16 changes: 9 additions & 7 deletions homeassistant/components/stream/recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def write_segment(segment: Segment) -> None:
# 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),
}
Expand All @@ -132,21 +132,23 @@ def write_segment(segment: Segment) -> None:
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
Expand Down
50 changes: 24 additions & 26 deletions homeassistant/components/stream/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
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
Expand Down Expand Up @@ -53,8 +52,8 @@

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)

Expand Down Expand Up @@ -130,19 +129,19 @@
_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:
Expand All @@ -161,11 +160,11 @@
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."""
Expand All @@ -182,7 +181,7 @@
# 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
Expand Down Expand Up @@ -233,12 +232,11 @@
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(

Check warning on line 235 in homeassistant/components/stream/worker.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/stream/worker.py#L235

Added line #L235 was not covered by tests
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."""
Expand Down Expand Up @@ -279,11 +277,11 @@
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)

Check warning on line 284 in homeassistant/components/stream/worker.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/stream/worker.py#L282-L284

Added lines #L282 - L284 were not covered by tests
return
packet.stream = self._output_audio_stream
self._av_output.mux(packet)
Expand Down Expand Up @@ -465,7 +463,7 @@
"""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"
)
Expand All @@ -492,7 +490,7 @@

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
Expand All @@ -509,7 +507,7 @@
_LOGGER.debug(
"ADTS AAC detected. Adding aac_adtstoaac bitstream filter"
)
return av.BitStreamFilter("aac_adtstoasc")
return "aac_adtstoasc"

Check warning on line 510 in homeassistant/components/stream/worker.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/stream/worker.py#L510

Added line #L510 was not covered by tests
break
return None

Expand Down Expand Up @@ -547,7 +545,7 @@
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]

Check warning on line 548 in homeassistant/components/stream/worker.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/stream/worker.py#L548

Added line #L548 was not covered by tests
# Disable ll-hls for hls inputs
if container.format.name == "hls":
for field in fields(StreamSettings):
Expand All @@ -562,8 +560,8 @@
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)))
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
8 changes: 4 additions & 4 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down