Skip to content
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
13 changes: 13 additions & 0 deletions av/audio/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ def encode(self, frame: AudioFrame | None = None):

return packets

def encode_lazy(self, frame: AudioFrame | None = None):
"""
Encode an :class:`.AudioFrame` and yield each :class:`.Packet` as it is produced.

.. seealso:: This is mostly a passthrough to :meth:`.CodecContext.encode_lazy`.
"""
self._assert_has_codec_context(lib.AVERROR_ENCODER_NOT_FOUND)
packet: Packet
for packet in self.codec_context.encode_lazy(frame):
packet._stream = self
packet.ptr.stream_index = self.ptr.index
yield packet

@cython.ccall
def decode(self, packet: Packet | None = None):
"""
Expand Down
2 changes: 2 additions & 0 deletions av/audio/stream.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections.abc import Iterator
from typing import Literal

from av.packet import Packet
Expand All @@ -19,6 +20,7 @@ class _Layout:
class AudioStream(Stream):
codec_context: AudioCodecContext
def encode(self, frame: AudioFrame | None = None) -> list[Packet]: ...
def encode_lazy(self, frame: AudioFrame | None = None) -> Iterator[Packet]: ...
def decode(self, packet: Packet | None = None) -> list[AudioFrame]: ...

# From codec context
Expand Down
13 changes: 13 additions & 0 deletions av/video/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ def encode(self, frame: VideoFrame | None = None):
packet.ptr.stream_index = self.ptr.index
return packets

def encode_lazy(self, frame: VideoFrame | None = None):
"""
Encode an :class:`.VideoFrame` and yield each :class:`.Packet` as it is produced.

.. seealso:: This is mostly a passthrough to :meth:`.CodecContext.encode_lazy`.
"""
self._assert_has_codec_context(lib.AVERROR_ENCODER_NOT_FOUND)
packet: Packet
for packet in self.codec_context.encode_lazy(frame):
packet._stream = self
packet.ptr.stream_index = self.ptr.index
yield packet

@cython.ccall
def decode(self, packet: Packet | None = None):
"""
Expand Down
32 changes: 32 additions & 0 deletions tests/test_encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,38 @@ def test_stream_index(self) -> None:
assert apacket.stream is astream
assert apacket.stream_index == 1

def test_stream_index_lazy(self) -> None:
with av.open(self.sandboxed("output_lazy.mov"), "w") as output:
astream = output.add_stream("mp2", 48000)
astream.layout = "stereo"
astream.format = "s16"

vstream = output.add_stream("mpeg4", 24)
vstream.pix_fmt = "yuv420p"
vstream.width = 320
vstream.height = 240

assert astream.index == 0
assert vstream.index == 1

vpackets = list(vstream.encode_lazy(VideoFrame(320, 240, "yuv420p")))
vpackets += list(vstream.encode_lazy(None))
assert vpackets
for vpacket in vpackets:
assert vpacket.stream is vstream
assert vpacket.stream_index == 1

apackets = []
for i in range(10):
aframe = AudioFrame("s16", "stereo", samples=astream.frame_size or 1000)
aframe.sample_rate = 48000
apackets += list(astream.encode_lazy(aframe))
apackets += list(astream.encode_lazy(None))
assert apackets
for apacket in apackets:
assert apacket.stream is astream
assert apacket.stream_index == 0

def test_stream_audio_resample(self) -> None:
with av.open(self.sandboxed("output.mov"), "w") as output:
vstream = output.add_stream("mpeg4", 24)
Expand Down
Loading