When PyAv is used to open the alsa audio device. How I can specify used codec and not the ffmpeg default one because that is wrong. By default it will use pcm_s16le
and I need to use pcm_s32le
. I can record from my device with following ffmpeg command:
ffmpeg -f alsa -acodec pcm_s32le -i dmic_sv alsaout.wav
but not with
ffmpeg -f alsa -i dmic_sv alsaout.wav
Which will give me following error:
[alsa @ 0x12061c0] cannot set sample format 0x10000 2 (Invalid argument)
dmic_sv: Input/output error
How to transfer the working command to PyAv av.open() function? There is stream_options
but it doesn't seem to work. I tried
stream_options = [{'-acodec': 'pcm_s32le'}]
av.open('dmic_sv', format='alsa', mode='r', stream_options=stream_options)
And I get the same as above.
av.error.OSError: [Errno 5] Input/output error: 'dmic_sv'; last error log: [alsa] cannot set sample format 0x10000 2 (Invalid argument)
How to do this?
I'll answer my own question because I figured it out. I read ffmpeg source code and saw that when using alsa audio device and codec is not specified ffmpeg will default to use signed 16-bit pcm samples. Code here. By further exploring the source code the codec value comes from AVFormatContext::audio_codec_id struct field.
Now figuring out that PyAV using Cython to use FFmpeg and by reading PyAV source code of Container class I noticed it holds AVFormatContext
in it's self.ptr
variable. Then reading InputContainer
source code and especially before calling avformat_open_input function to open the alsa device. Specifying the used audio codec is not supported by PyAV.
I forked the library and ended quickly hacking the solution for me. Now the question is would it be possible to add this feature to PyAV to force the codec used for the audio? In this case when the device is using pcm samples and relying ffmpeg to use choose the default one it will always use 16-bit samples and in my case I needed to use 32-bit samples.
Hopefully this helps someone and save them the trouble I went through :) I also posted this same answer for PyAV issue here.