Glam Prestige Journal

Bright entertainment trends with youth appeal.

I want to merge mp4 files via the concat demuxer and cannot get it to work with a script.

I am using the script from another AskUbuntu answer, called concatmp4 here:

#!/usr/bin/env bash
if [ $# -lt 1 ]; then echo "Usage: `basename $0` input_1.mp4 input_2.mp4 ... output.mp4" exit 0
fi
ARGS=("$@") # determine all arguments
output=${ARGS[${#ARGS[@]}-1]} # get the last argument (output file)
unset ARGS[${#ARGS[@]}-1] # drop it from the array
(for f in "${ARGS[@]}"; do echo "file '$f'"; done) | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy $output

However, when I run it on mp4 files, I always get

$ concatmp4 Itazuraguma_no_Gloomy_01.mp4 Itazuraguma_no_Gloomy_02.mp4 test.mp4
ffmpeg version 4.4-6ubuntu5 Copyright (c) 2000-2021 the FFmpeg developers built with gcc 11 (Ubuntu 11.2.0-7ubuntu1) configuration: --prefix=/usr --extra-version=6ubuntu5 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56. 70.100 / 56. 70.100 libavcodec 58.134.100 / 58.134.100 libavformat 58. 76.100 / 58. 76.100 libavdevice 58. 13.100 / 58. 13.100 libavfilter 7.110.100 / 7.110.100 libswscale 5. 9.100 / 5. 9.100 libswresample 3. 9.100 / 3. 9.100 libpostproc 55. 9.100 / 55. 9.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x55f2ed650200] Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible!
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x55f2ed650200] moov atom not found
[concat @ 0x55f2ed63e440] Impossible to open 'pipe:Itazuraguma_no_Gloomy_01.mp4'
pipe:: Invalid data found when processing input

When I modify the script's last line to (for f in "${ARGS[@]}"; do echo "file '$f'"; done) > input.text, and then run ffmpeg -f concat -i input.text -c copy output.mp4 from the command line, it works (!). Just to clarify, when I use -c copy in the script, the error is the same.

It also works when the script goes via a temp file:

... # lines after the 'unset' line in the original:
tmpfile="${output%.mp4}.tmp"
(for f in "${ARGS[@]}"; do echo "file '$f'"; done) > "$tmpfile"
ffmpeg -f concat -safe 0 -i "$tmpfile" -c copy "$output"
rm "$tmpfile"

What is needed to make the script work?

1 Answer

According to the bug tracker of ffmpeg, there were changes in the newer versions. Since the release between 4.2.2 and 4.3.2, the handling of relative URLs have been fixed to make it compatible with the official recommendations.

If there are bare file names in the concat script, the files are supposed to reside in the same directory (and of course protocol) as the script. Which, of course, is not possible for pipe:, but still applies. If the script is saved in a temp file, its protocol changes to 'file' and the old way works because of that change.

The piped input needs to specify both the concat file and the protocol file: in the concat code.

Example for now necessary input via pipe protocol: file file:'input_01.mp4' instead of the old file 'input_01.mp4'.

The new version of the script needs to be changed to

#!/usr/bin/env bash
if [ $# -lt 1 ]; then echo "Usage: `basename $0` input_1.mp4 input_2.mp4 ... output.mp4" exit 0
fi
ARGS=("$@") # determine all arguments
output=${ARGS[${#ARGS[@]}-1]} # get the last argument (output file)
unset ARGS[${#ARGS[@]}-1] # drop it from the array
(for f in "${ARGS[@]}"; do echo "file file:'$f'"; done) | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -c:v copy -c:a copy $output

to work.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy