Merging several videos with audio channel and without audio

2

1

I need to merge very different videos into a one output video. Input videos can have different resolutions, framerate, channels and so on. So some videos can be without audio channel and should be merged with video with audio channel. I do not know beforehand if it is with or without audio channel So I use ffmpeg with -filter_complex to make videos the same frame size and next filter concat to merge them. (also I need to cut input videos but let me skip this part here)

ffmpeg.exe -i "withAudio.flv" -i "noAudio.mpg" \
-filter_complex \
    "[0:v]scale=1280:720, setsar=1/1, setpts=PTS-STARTPTS[v0]; \
    [1:v]scale=1280:720, setsar=1/1, setpts=PTS-STARTPTS[v1]; \
    [v0][0:a] [v1][1:a] concat=n=2:v=1:a=1[v][a]" \
 -map "[v]" -map "[a]" -vcodec libx264 -b 512k -acodec libfaac -ar 44100 -ab 128k  \
-pix_fmt yuv420p -movflags faststart -y "result.mp4"

And in result I get an error about missing channel

Stream specifier ':a' in filtergraph description [0:v]scale=1280:720, setsar=1/1
, setpts=PTS-STARTPTS[v0]; [1:v]scale=1280:720, setsar=1/1, setpts=PTS-STARTPTS[
v1];  [v0][0:a] [v1][1:a] concat=n=2:v=1:a=1[v][a] matches no streams.

Full

ffmpeg version 2.8.6 Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 4.9.3 (GCC)
  configuration: --prefix=/opt/xtendx/local --arch=x86 --target-os=mingw32 --cross-prefix=i686-w64-mingw32- --pkg-config=pkg-config --disable-pthreads --enable-w32threads --extra-libs=-lws2_32 --extra-libs=-lwinmm --extra-libs=-lgdi32 --enable-static --disable-shared --disable-debug --disable-indevs --disable-outdevs --disable-iconv --disable-bzlib --disable-ffplay --disable-ffserver --enable-gpl --enable-version3 --enable-nonfree --enable-librtmp --enable-libmp3lame --enable-libfaac --enable-libfdk-aac --enable-libx264 --enable-libvpx --disable-libxcb --disable-libxcb-shm --disable-libxcb-xfixes --disable-libxcb-shape --enable-decoder=prores_lgpl --disable-decoder=prores --enable-runtime-cpudetect --disable-openssl
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, flv, from 'withAudio.flv':
  Metadata:
    starttime       : 0
    totalduration   : 30
    totaldatarate   : 484
    bytelength      : 1846185
    canseekontime   : true
    sourcedata      : B4A7D0D44HH1361885066111689
    purl            :
    pmsg            :
    httphostheader  : r15---sn-1gi7zn7s.c.youtube.com
  Duration: 00:00:30.48, start: 0.000000, bitrate: 484 kb/s
    Stream #0:0: Video: h264 (Main), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 388 kb
/s, 25 fps, 25 tbr, 1k tbn, 50 tbc
    Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 99 kb/s
Input #1, mpeg, from 'noAudio.mpg':
  Duration: 00:00:29.96, start: 0.500000, bitrate: 8040 kb/s
    Stream #1:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 64:4
5 DAR 16:9], 8000 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc


Stream specifier ':a' in filtergraph description [0:v]scale=1280:720, setsar=1/1
, setpts=PTS-STARTPTS[v0]; [1:v]scale=1280:720, setsar=1/1, setpts=PTS-STARTPTS[
v1];  [v0][0:a] [v1][1:a] concat=n=2:v=1:a=1[v][a] matches no streams.

From the FFmpeg documentation for concat filter:

The filter works on segments of synchronized video and audio streams.
All segments must have the same number of streams of eachtype, 
and that will also be the number of streams at output.

So how can I build the command to merge several videos with different channels number ?

Alex V

Posted 2016-02-24T16:51:41.850

Reputation: 21

Answers

3

FFmpeg is expecting an audio stream to pair with the 2nd video. Since there isn't one, you'll have to supply a dummy one.

Since you aren't sure if the inputs have audio, run this command for each input:

ffmpeg -i <input> -f lavfi -i anullsrc -c:v copy \
-map 0:v -map 0:a? -map 1:a -shortest <output>

And then, with the processed files

ffmpeg.exe -i <input1> -i <input2> \
-filter_complex \
"[0:v]scale=1280:720, setsar=1/1, setpts=PTS-STARTPTS[v0]; \
 [1:v]scale=1280:720, setsar=1/1, setpts=PTS-STARTPTS[v1]; \
 [v0][0:a] [v1][1:a] concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -vcodec libx264 -b:v 512k -pix_fmt yuv420p \
-map "[a]" -acodec libfaac -b:a 128k -ar 44100 \
-movflags faststart -y "result.mp4"

Gyan

Posted 2016-02-24T16:51:41.850

Reputation: 21 016

Problem is that I do not know beforehand if video has sound or not. so I do not know what exactly stream should be replaced. – Alex V – 2016-02-25T09:43:39.103

You'll have to probe each input and check for presence of Audio – Gyan – 2016-02-25T10:27:30.333

Is there any chance to do this with one command? – Alex V – 2016-02-25T12:59:22.207

Not that I know. But the edited workflow should work with agnostic inputs. – Gyan – 2016-02-25T13:14:42.233

Thank you! This answer pointed me in the right direction for a problem I had to day related to scaling and combining videos of different sizes :) – Sverrir Sigmundarson – 2018-02-18T16:04:20.557