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

Open audio device with specifi codec instead of ffmpeg default one? #699

Closed
Kazhuu opened this issue Aug 20, 2020 · 2 comments
Closed

Open audio device with specifi codec instead of ffmpeg default one? #699

Kazhuu opened this issue Aug 20, 2020 · 2 comments

Comments

@Kazhuu
Copy link

Kazhuu commented Aug 20, 2020

I also asked this same question in StackOverflow. When I use PyAv.open() function. Is it possible to specify used codec to read data from the alsa audio device instead of relying on the default FFmpeg codec. In my case used codec is specified with -acodec command-line flag and I need to use pcm_s32le which otherwise defaults to pcm_s16le. How to convey this information using PyAv?

In the documentation there is parameter stream_options which I tried to use like this:

stream_options = [{'codec': 'pcm_s32le'}]
av.open('dmic_sv', format='alsa', mode='r', stream_options=stream_options)

Which will give me:

av.error.OSError: [Errno 5] Input/output error: 'dmic_sv'; last error log: [alsa] cannot set sample format 0x10000 2 (Invalid argument)

Which is the same behavior when I don't specify the codec.

When I read the documentation little bit more I noticed parsing in basics section. I tried to create ffmpeg background process and then read bytes from it and then use CodecConext to parse them to packets

import av

codec = av.CodecContext.create('pcm_s32le', 'r')
chunk = file_handler.read(samples * 4)
packets = codec.parse(chunk)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "av/codec/context.pyx", line 325, in av.codec.context.CodecContext.parse
ValueError: No parser for pcm_s32le

It seems parsing from byte stream for pcm_s32le is not supported. I need to be able read pcm_s32le samples and then reencode them to pcm_s16le. How to do this?

@Kazhuu
Copy link
Author

Kazhuu commented Aug 28, 2020

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.

So this issue can be closed. Hopefully this helps someone and save them the trouble I went through :)

@SoundsSerious
Copy link

Yea would love to have more pythonic access to codec & stream options!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants