2222.. code-block::
2323
2424 VideoDemuxer -> VideoPacketDecoder -> ColorConverter
25- Packet RawFrame RGB Frame
25+ Packet RawFrame RGB Frame
2626
2727The blocks are passive: they never create threads, and they release the GIL.
2828You decide how they are composed, on which threads, and where to stop. Below
2929we illustrate a few things this enables: overlapping stages on multiple
3030threads, accessing raw (YUV) frames, and decoding streams of unknown -
3131possibly infinite - length.
3232
33- Audio works the same way, through ``AudioDemuxer`` and ``AudioConverter``; we
34- come back to it at the end.
33+ Audio works the same way, through ``AudioDemuxer``, ``AudioPacketDecoder`` and
34+ ``AudioConverter``; we come back to it at the end.
3535"""
3636
3737# %%
@@ -435,17 +435,22 @@ def start_live_stream():
435435# Audio
436436# -----
437437#
438- # Audio has the same three stages, and ``PacketDecoder`` is the same block :
438+ # Audio has the same three stages:
439439#
440440# .. code-block::
441441#
442- # AudioDemuxer -> PacketDecoder -> AudioConverter
443- # Packet RawAudioSamples AudioSamples
442+ # AudioDemuxer -> AudioPacketDecoder -> AudioConverter
443+ # Packet RawAudioSamples AudioSamples
444444#
445- # What ``PacketDecoder`` hands out follows the demuxer it was built from, so
446- # audio comes out as ``RawAudioSamples``: the codec's own samples, in the codec's
447- # own sample type, as a ``[num_channels, num_samples]`` tensor.
448- from torchcodec .decoders ._blocks import AudioConverter , AudioDemuxer
445+ # Decoding is the same operation either way, so the two packet decoders are a
446+ # single class in C++; they are separate in Python because what they hand out
447+ # isn't. Audio comes out as ``RawAudioSamples``: the codec's own samples, in
448+ # the codec's own sample type, as a ``[num_channels, num_samples]`` tensor.
449+ from torchcodec .decoders ._blocks import (
450+ AudioConverter ,
451+ AudioDemuxer ,
452+ AudioPacketDecoder ,
453+ )
449454
450455audio_path = temp_dir / "audio.wav"
451456subprocess .run (
@@ -458,7 +463,7 @@ def start_live_stream():
458463)
459464
460465demuxer = AudioDemuxer (audio_path )
461- packet_decoder = PacketDecoder (demuxer )
466+ packet_decoder = AudioPacketDecoder (demuxer )
462467raw = next (iter (packet_decoder .decode (next (iter (demuxer )))))
463468print (f"{ raw .sample_format = } , { raw .data .dtype = } , { raw .data .shape = } , "
464469 f"{ raw .sample_rate = } " )
@@ -475,7 +480,7 @@ def start_live_stream():
475480# can return fewer samples than it was given, and why the pipeline ends with
476481# ``drain()``. Leave that call out and you lose the end of the stream.
477482demuxer = AudioDemuxer (audio_path )
478- packet_decoder = PacketDecoder (demuxer )
483+ packet_decoder = AudioPacketDecoder (demuxer )
479484audio_converter = AudioConverter (sample_rate = 16_000 , num_channels = 1 )
480485
481486chunks = []
0 commit comments