wiki:

Concatenate


Version 6 (modified by burek, 7 years ago) (diff)

Added "important" section because of the bug trac ticket

Description

The following script can be used to concatenate multiple input media files (containing audio/video streams) into one output file (just like as if all the inputs were played in a playlist, one after another). It is based on this FAQ item: How can I join video files.

If you find any bugs, feel free to correct the script, add yourself to the list of contributors and change the version string to reflect your change(s) or email the author with your patch, whatever you find more convenient.

Important

Recently, a bug was discovered in ffmpeg, which prevents this script from the normal functioning. Since the bug trac ticket is still not confirmed as a bug, it can happen that this issue is not considered a bug, so it might not even be resolved. If that happens, the only way to successfully run the script will be to use real files, instead of named pipes (fifos). If you want to contribute to help resolve this issue, please reply to that bug trac ticket and try to give your opinion about the subject. It might influence the solution to be found more quickly.

So, if you really need this to work for you, try using real files, instead of fifos (named pipes). Fifos are declared in this script using "mkfifo name_and_path_of_the_fifo", so just try to comment out those lines and hopefully real files will be created, so the process will not end up in the deadlock. It will also help if you read this FAQ item, to understand what does the script do (it just automates that process): http://ffmpeg.org/faq.html#Concatenating-using-raw-audio-and-video

If that doesn't help, please read that FAQ item and do it all manually... I'm really sorry this can't be as automated as we all would like it to be, but that's the way the things are in this moment.

Instructions

Save the script in a file named "mmcat" (or some other name), make it executable (chmod +x mmcat) and run it, using the syntax:

./mmcat <input1> <input2> <input3> ... <output>

Script

#!/bin/bash

################################################################################
#
# Script name: MultiMedia Concat Script (mmcat)
# Author: burek (burek021@gmail.com)
# License: GNU/GPL, see http://www.gnu.org/copyleft/gpl.html
# Date: 2012-07-14
#
# This script concatenates (joins, merges) several audio/video inputs into one
# final output (just like as if all the inputs were played in a playlist, one
# after another).
#
# All input files must have at least one audio and at least one video stream.
# If not, you can easily add audio silence, using FFmpeg. Just search the
# internet for "ffmpeg add silence".
#
# The script makes use of FFmpeg tool (www.ffmpeg.org) and is free for use under
# the GPL license. The inspiration for this script came from this FAQ item:
# http://ffmpeg.org/faq.html#How-can-I-join-video-files_003f
#
# If you find any bugs, please send me an e-mail so I can fix it.
#
################################################################################
#
# General syntax: mmcat <input1> <input2> <input3> ... <output>
#
# For example: mmcat file1.flv file2.flv output.flv
# would create "output.flv" out of "file1.flv" and "file2.flv".
#
################################################################################

# change this to what you need !!!
EXTRA_OPTIONS='-vcodec libx264 -crf 23 -preset medium -acodec aac -strict experimental -ac 2 -ar 44100 -ab 128k'

################################################################################
#
# NO NEED TO TOUCH ANYTHING AFTER THIS LINE!
#
################################################################################

# the version of the script
VERSION=1.1

# location of temp folder
TMP=/tmp

################################################################################

echo "MultiMedia Concat Script v$VERSION (mmcat) - A script to concatenate multiple multimedia files."
echo "Based on FFmpeg - www.ffmpeg.org"
echo "Don't forget to edit this script and change EXTRA_OPTIONS"
echo ""

################################################################################
# syntax check (has to have at least 3 params: infile1, infile2, outfile
################################################################################
if [ -z $3 ]; then
	echo "Syntax: $0 <input1> <input2> <input3> ... <output>"
	exit 1
fi

################################################################################
# get all the command line parameters, except for the last one, which is output
################################################################################
# $first  - first parameter
# $last   - last parameter (output file)
# $inputs - all the inputs, except the first input, because 1st input is
#           handled separately
################################################################################
first=${@:1:1}
last=${@:$#:1}
len=$(($#-2))
inputs=${@:2:$len}

# remove all previous tmp fifos (if exist)
rm -f $TMP/mcs_*

################################################################################
# decode first input differently, because the video header does not have to be
# kept for each video input, only the header from the first video is needed
################################################################################
mkfifo $TMP/mcs_a1 $TMP/mcs_v1
ffmpeg -y -i $first\
	-vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a1\
	-an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_v1 2>/dev/null &

################################################################################
# decode all the other inputs, remove first line of video (header) with tail
# $all_a and $all_v are lists of all a/v fifos, to be used by "cat" later on
################################################################################
all_a=$TMP/mcs_a1
all_v=$TMP/mcs_v1
i=2
for f in $inputs
do
	mkfifo $TMP/mcs_a$i $TMP/mcs_v$i $TMP/mcs_t$i
	ffmpeg -y -i $f \
		-vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a$i\
		-an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_t$i 2>/dev/null &
	tail $TMP/mcs_t$i -n +2 > $TMP/mcs_v$i &
	all_a="$all_a $TMP/mcs_a$i"
	all_v="$all_v $TMP/mcs_v$i"
	let i++
done

################################################################################
# concatenate all raw audio/video inputs into one audio/video
################################################################################
mkfifo $TMP/mcs_a_all
mkfifo $TMP/mcs_v_all
cat $all_a > $TMP/mcs_a_all &
cat $all_v > $TMP/mcs_v_all &

################################################################################
# finally, encode the raw concatenated audio/video into something useful
################################################################################
ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i $TMP/mcs_a_all \
       -f yuv4mpegpipe -vcodec rawvideo -i $TMP/mcs_v_all \
	$EXTRA_OPTIONS \
	$last

################################################################################
# remove all fifos
################################################################################
rm -f $TMP/mcs_*

Attachments (2)

Download all attachments as: .zip