Add audio to video using FFmpeg

28

15

I’m trying to add sound to a video using FFmpeg, but for some reason, when I play the resulting file, it doesn't have any sound. I also tried doing it with an aac audio file, as well as leaving out -acodec copy and giving it a wav file.

Here is the complete output:

C:\Users\SM-Audio\Desktop>ffmpeg -i PrintingCDs.mp4 -i AudioPrintCDs.mp3 -acodec
 copy -vcodec copy PrintCDs1.mp4
ffmpeg version N-48886-g5ce023b Copyright (c) 2000-2013 the FFmpeg developers
  built on Jan 14 2013 19:16:33 with gcc 4.7.2 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-av
isynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enab
le-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable-libg
sm --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --e
nable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --e
nable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-aacenc --en
able-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable
-libxavs --enable-libxvid --enable-zlib --enable-filter=frei0r
  libavutil      52. 14.100 / 52. 14.100
  libavcodec     54. 89.100 / 54. 89.100
  libavformat    54. 59.107 / 54. 59.107
  libavdevice    54.  3.102 / 54.  3.102
  libavfilter     3. 32.100 /  3. 32.100
  libswscale      2.  1.103 /  2.  1.103
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'PrintingCDs.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-05-01 13:35:52
  Duration: 00:02:35.57, start: 0.000000, bitrate: 585 kb/s
    Stream #0:0(eng): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 1024x
768 [SAR 1:1 DAR 4:3], 457 kb/s, 10 fps, 10 tbr, 30k tbn, 30 tbc
    Metadata:
      creation_time   : 2013-05-01 13:35:53
      handler_name    : Mainconcept MP4 Video Media Handler
    Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 22050 Hz, mono, fltp, 126
kb/s
    Metadata:
      creation_time   : 2013-05-01 13:35:53
      handler_name    : Mainconcept MP4 Sound Media Handler
[mp3 @ 003dd6c0] max_analyze_duration 5000000 reached at 5015510 microseconds
Input #1, mp3, from 'AudioPrintCDs.mp3':
  Metadata:
    encoder         : Lavf54.59.107
  Duration: 00:02:36.21, start: 0.000000, bitrate: 64 kb/s
    Stream #1:0: Audio: mp3, 44100 Hz, mono, s16p, 64 kb/s
File 'PrintCDs1.mp4' already exists. Overwrite ? [y/N] y
Output #0, mp4, to 'PrintCDs1.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    encoder         : Lavf54.59.107
    Stream #0:0(eng): Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 1024x768 [S
AR 1:1 DAR 4:3], q=2-31, 457 kb/s, 10 fps, 30k tbn, 30k tbc
    Metadata:
      creation_time   : 2013-05-01 13:35:53
      handler_name    : Mainconcept MP4 Video Media Handler
    Stream #0:1(eng): Audio: aac ([64][0][0][0] / 0x0040), 22050 Hz, mono, 126 k
b/s
    Metadata:
      creation_time   : 2013-05-01 13:35:53
      handler_name    : Mainconcept MP4 Sound Media Handler
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame= 1555 fps=0.0 q=-1.0 Lsize=   11133kB time=00:02:35.57 bitrate= 586.2kbits
/s
video:8674kB audio:2408kB subtitle:0 global headers:0kB muxing overhead 0.459569
%

Arlen Beiler

Posted 2013-05-01T16:35:51.890

Reputation: 1 108

Note that the command in the question is completely sufficient in case of merging an mp4 video-only file without embedded audio track with a separate mp4 audio-only file. – Vadzim – 2018-01-03T21:08:45.247

Refer to this question How to add a new audio (not mixing) into a video using ffmpeg?

– Kris Roofe – 2019-08-06T07:49:28.197

Answers

53

By default, FFmpeg will only take one audio and one video stream. In your case that's taken from the first file only.

You need to map the streams correctly:

ffmpeg -i input.mp4 -i input.mp3 -c copy -map 0:v:0 -map 1:a:0 output.mp4

Some notes:

  • The order mapping options determine which streams from the input are mapped to the output.
  • 0:v:0 is the first video stream of the first file and 1:a:0 is the first audio stream of the second file. The v/a are not strictly necessary, but in case your input files contain multiple streams, that helps to disambiguate. More info about mapping can be found on the FFmpeg Wiki.
  • If your audio stream is longer than the video file, or vice-versa, you can use the -shortest option to have ffmpeg stop the conversion when the shorter of the two ends.
  • -c copy copies the audio and video streams. This means that the process will be fast and the quality will be the same. But when adding, say, WAV audio to an existing video file, it'd be better to compress that audio first. For example:

    ffmpeg -i input.mp4 -i input.wav -c:v copy -map 0:v:0 -map 1:a:0 -c:a aac -b:a 192k output.mp4
    

    Here, we only copy the video stream (-c:v copy), and re-encode the audio stream with the ffmpeg built-in AAC encoder (-c:a aac) at 192 kBit/s.

  • If your output format does not support a particular codec (e.g., when adding WAV to MP4, or AAC to AVI, etc.), re-encoding is also required.

slhck

Posted 2013-05-01T16:35:51.890

Reputation: 182 472

1out of curiosity what if the audio or video length are not same! does video remains same and audio length automatically matches with video size! – Akash Dubey – 2017-05-25T13:09:21.673

1@Akash ffmpeg will always use the longer of the two streams and add black video or silent audio at the end. Unless you specify the -shortest option, in which case the shortest stream terminates the encoding process. – slhck – 2017-05-25T13:24:23.727

Thanks for quick reply, May I know where to add -shortest in the above command whether it goes like this - ffmpeg -i input.mp4 -i input.mp3 -c copy -map 0:0 -map 1:0 -shortest output.mp4 – Akash Dubey – 2017-05-25T13:25:58.173

1@AkashDubey That's how you use it, yes. Anywhere between -i <input> and the output file. – slhck – 2017-05-25T13:38:35.283

I have used this command for changing audio stream of a video file but it throws : Output file #0 does not contain any stream – Akash Dubey – 2017-05-26T10:00:12.550

Output #0, mp4, to 'ffmpeg -i /document/video:4632 -i /document/audio:4650 -c copy -map 0:v:0 -map 1:a:0 /storage/emulated/0/output.mp4': Output file #0 does not contain any stream – Akash Dubey – 2017-05-26T10:06:48.373

@AkashDubey Please ask a new question including the full command-line log. Make sure your input files actually contain audio and video, and that you use a recent ffmpeg version. – slhck – 2017-05-26T11:20:03.130

@slhck : https://superuser.com/q/1213107/729054

– Akash Dubey – 2017-05-26T11:24:28.410

@slhck What if the input audio file is shorter than the input video file, but I want the output video file to always have the same duration as the input video file, while having the audio content to loop ? – android developer – 2019-02-24T12:55:29.797

1

@androiddeveloper You can use the -stream_loop option for the audio part: https://video.stackexchange.com/a/23402/525

– slhck – 2019-02-25T09:15:34.167

@slhck Thank you . I got it here: https://superuser.com/a/1319950/152400 , https://github.com/umair13adil/KotlinFFMpeg/issues/11 . Gave you +1 for helping .

– android developer – 2019-02-25T09:58:15.177

1Thank you very much, that works perfect. What's the -c copy? Is that shorthand for -acodec copy -vcodec copy? – Arlen Beiler – 2013-05-01T16:52:10.777

1Yeah, basically it tells it to copy all kinds of streams – this also includes subtitles. – slhck – 2013-05-01T16:54:32.563

To see how the streams are named/referenced in your input videos (e.g. if you have a video with multichannel audio), you can just start ffmpeg with one or several input file(s) – and nothing else. Than all the streams are listed and named 0:0, 0:1, 0:2, 1:0, 1:1 and so on. Example: ffmpeg -i videofile.mp4 -i anothervideofile.mp4 – erik – 2014-02-17T15:52:38.243