Zvika
Zvika

Reputation: 1702

How to set the quality of an mp3 Codec with PyAV

I wrote a simple code to create a .mp3 file from any audio input, using PyAV. It's working (pasted at the end of the question). However, when using ffmpeg it's possible to set the quality of the .mp3 file, and I'd like to do this as well in my code. According to the ffmpeg documentation :

q (-V)

Set constant quality setting for VBR. This option is valid only using the ffmpeg command-line tool. For library interface users, use global_quality.

So, the question is how do I use global_quality with PyAV?

I found it at PyAV documentation, listed as Wrapped C Types and Functions, under struct AVCodecContext, but I still don't understand how to use this.

I tried creating an AudioCodecContext (which is the closest thing to AVCodecContext I found) with c = av.Codec('mp3').create(), but it doesn't seem to have a global_quality field.

My existing function:

    def encode_audio_to_mp3(input_file_path, output_file_path):
        input_container = av.open(input_file_path)
        output_container = av.open(output_file_path, 'w')
        output_stream = output_container.add_stream('mp3')
    
        for in_packet in input_container.demux():
            for in_frame in in_packet.decode():
                for out_packet in output_stream.encode(in_frame):
                    output_container.mux(out_packet)
    
        # Flush stream
        for packet in output_stream.encode():
            output_container.mux(packet)
    
        output_container.close()
        input_container.close()

Upvotes: 2

Views: 426

Answers (1)

WyattBlue
WyattBlue

Reputation: 631

You can set the audio stream's bitrate, which controls the quality.

import av


def encode_audio_to_mp3(input_path: str, output_path: str) -> None:
    input_ = av.open(input_path)
    output_container = av.open(output_path, "w")

    input_stream = input_.streams.audio[0]
    output_stream = output_container.add_stream("mp3")

    # Set the bitrate for the output stream
    output_stream.bit_rate = 50_000

    for packet in input_.demux(input_stream):
        for frame in packet.decode():
            for out_packet in output_stream.encode(frame):
                output_container.mux(out_packet)

    # Flush stream
    for packet in output_stream.encode():
        output_container.mux(packet)

    output_container.close()
    input_.close()

Upvotes: 1

Related Questions