Extract audio to mp3 from mp4 using C++ (not executing ffmpeg with args)
Asked Answered
H

2

8

How can I programmatically convert (extract the audio channel) from the mp4 video file format?
I just can't find anything on the web, for using C++.

Passing command line args to LAME or MPLAYER or FFMPEG is not an option.

Hardboard answered 21/4, 2013 at 13:46 Comment(6)
LAME and FFMPEG are open source projects, so I suggest you take a peek at their sources to get you started.Ora
how about using the ffmpeg API? implementing that from scratch sounds difficult.Luting
does FFMPEG have API ???Hardboard
@Hardboard I tried to improve the grammar and removed 1 sentence because I couldn't understand what it was supposed to mean. It'd be nice if you could clarify that sentence if it was important.Jamshedpur
I am looking for code example to achieve this using ffmpeg.Jamshedpur
"does FFMPEG have API ???:" - This document describes the usage of the different libraries provided by FFmpeg (the API)Doth
N
11

You can try using ffmpeg to do it in C or C++. Here is the normal flow of steps.

  1. Init ffmpeg using av_register_all();

  2. Open input file using avformat_open_input( &informat, sourcefile, 0, 0)).

  3. Find stream info using avformat_find_stream_info(informat, 0)).

  4. Find the audio stream by iterating through streams and comparing codec_type to AVMEDIA_TYPE_AUDIO.

  5. Once you have input audio stream you can find audio decoder and open the decoder. Use avcodec_find_decoder(in_aud_strm->codec->codec_id) and avcodec_open2(in_aud_codec_ctx, in_aud_codec, NULL).

  6. Now for output file guess the outformat using av_guess_format(NULL, (const char*)outfile, NULL).

  7. Allocate context for outformat.

  8. Find output audio encoder using avcodec_find_encoder(outfmt->audio_codec).

  9. Add new stream audio stream avformat_new_stream(outformat, out_aud_codec).

  10. Fill output codec context with desired sample rate, sample fmt, channel etc.

  11. Open output file using avio_open().

  12. Write the output headers using avformat_write_header(outformat, NULL).

  13. Now in while loop start reading packet, decode only audio packet encode them and write them in opened output file. You can use av_read_frame(informat, &pkt) , avcodec_decode_audio4(in_aud_codec_ctx, pframeT, &got_vid_pkt, &pkt), avcodec_encode_audio2() and av_write_frame().

  14. Finally write trailer using av_write_trailer.

You can looking into demuxing.c and muxing.c provided in ffmpeg examples.

Nautilus answered 22/4, 2013 at 12:36 Comment(3)
Thanks i will try it. I wander if there some open source app that allready doing itHardboard
It would be very useful if you provided some code exampleJamshedpur
@Hardboard this is exactly what ffmpeg does (and it is open source). The question was how this can be done in C.Overset
O
2

Start with the transcode_aac official example. We need remarkably few changes:

  1. add a global variable at file scope:

    /* The index of audio stream that will be transcoded */
    static int audio_stream_idx = -1;
    
  2. in open_input_file(), replace lines 83-88 with

    for (audio_stream_idx = 0; audio_stream_idx < (*input_format_context)->nb_streams; audio_stream_idx++) {
    if ((*input_format_context)->streams[audio_stream_idx]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
        break;
    }
    
    if (audio_stream_idx >= (*input_format_context)->nb_streams) {
        fprintf(stderr, "Could not find an audio stream\n");
        avformat_close_input(input_format_context);
        return AVERROR_EXIT;
    }
    
  3. On lines 92 and 107, replace streams[0] with streams[audio_stream_idx].

  4. On line 181, replace hard-coded codec ID AV_CODEC_ID_AAC with

    (*output_format_context)->oformat->audio_codec
    
  5. On line 182, replace the error message:

    fprintf(stderr, "Could not find audio encoder for %s(%d).\n", (*output_format_context)->oformat->long_name, (*output_format_context)->oformat->audio_codec);
    
  6. In decode_audio_frame() we skip non-audio frames: on line 389, write

    if (error != AVERROR_EOF && input_packet.stream_index != audio_stream_idx) goto cleanup;
    

PS Note that this solution does not handle optimally the case when the audio stream does not require transcoding. Most mp4 files will have AAC or AC3 audio tracks, so make sure you build your ffmpeg with the relevant decoders and with an MP3 encoder (e.g. shine).

PPS here is the file, adapted to Adnroid.

Overset answered 7/6, 2020 at 22:10 Comment(5)
Thank you very much. I tried it on multiple mp4 files and I get "Could not find an AAC encoder." from this line.Jamshedpur
@_Static_assert how did you build your libavcodec? Actually, the message is misleading: I fixed my answer aboveOverset
I installed the library through Microsoft package manager (vcpkg). Your print statement on step 4 didn't compile, so I replaced it with if (!((output_codec = avcodec_find_encoder((*output_format_context)->oformat->audio_codec)))) {fprintf(stderr, "Could not find audio encoder for %s(%d).\n",(*output_format_context)->oformat->long_name,(*output_format_context)->audio_codec_id); And the output of the program is "Could not find audio encoder for MP3 (MPEG audio layer 3)(0)."Jamshedpur
After adding the print, the output "Could not find audio encoder for MP3 (MPEG audio layer 3)(86017)"Jamshedpur
Sorry, my copy/paste fault about this compilation error. But you got the idea. Your package manager brought you a version of ffmpeg that cannot create mp3. Probably related: github.com/microsoft/vcpkg/issues/9671Overset

© 2022 - 2024 — McMap. All rights reserved.