PyAV-Org / PyAV

Pythonic bindings for FFmpeg's libraries.
https://pyav.basswood-io.com/
BSD 3-Clause "New" or "Revised" License
2.54k stars 366 forks source link

Cannot set number of audio channels on output stream starting with PyAV version 13.0.0. #1627

Closed druzsan closed 2 weeks ago

druzsan commented 2 weeks ago

Overview

My goal is to write out an array of data as an audio file with the given sampling rate, format, codec and number of channels (mono, stereo, 5.1, 7.1 etc).

I am doing this in the following way (sampling rate, audio length, format and codec don't matter here):

import av
import av.audio
import numpy as np

sampling_rate = 44800
length = 5
num_channels = 6

data = np.random.random((num_channels, length * sampling_rate))

# "dblp" matches with float64 data types, "5.1" matches with (6, n) data size
frame = av.audio.AudioFrame.from_ndarray(data, "dblp", "5.1")
frame.rate = sampling_rate

with av.open("output.flac", "w", "flac") as container:
    stream = container.add_stream("flac", sampling_rate)
    stream.channels = num_channels
    container.mux(stream.encode(frame))
    container.mux(stream.encode(None))

Actual behavior

Up until version 12.3.0 this worked just as expected, but starting from the version 13.0.0 channels couldn't be set on a stream anymore.

Traceback:

Traceback (most recent call last):
  File "/home/alexander/dev/pyav/./test.py", line 23, in <module>
    stream.channels = num_channels
  File "av/stream.pyx", line 111, in av.stream.Stream.__setattr__
AttributeError: attribute 'channels' of 'av.audio.codeccontext.AudioCodecContext' objects is not writable

I tried stream = container.add_stream("flac", sampling_rate, channels=num_channels) instead of setting channels afterwards - works with version 12.3.0 but doesn't work with versions 13.0.0 and 13.1.0.

The other possibility would be to pass options to container.add_stream, but only the string values are allowed there.

If I leave it as is without setting channels on the stream, I always get stereo audio regardless of my data format.

Is there another way to set channels on an output stream?

Versions