トップ «前の日記(2017年09月17日) 最新 次の日記(2017年09月24日)» 編集

Masa's blog

検索キーワード:

2017年09月21日 Script to merge movies left-right or top-bottom [長年日記]

_ mergemovies.sh

Script to merge two movies into left-right or top-bottom.

#! /bin/sh
#
if [ "X$1" = "X-h" -o "X$1" = "X--help" ]
then
	echo "Usage: $0 -l left_movie -r right_movie -o output_movie [options]"
	echo "       $0 -t top_movie -b bottom_movie -o output_movie [options]"
	echo "Merge movies into output_movie."
        echo ""
	echo "-l LEFT_MOVIE          movie file for left side"
	echo "-r RIGHT_MOVIE         movie file for right side"
	echo "-t TOP_MOVIE           movie file for top side"
	echo "-b BOTTOM_MOVIE        movie file for bottom side"
	echo "-o OUTPUT_MOVIE        movie file for output"
	echo "-a AUDIO_INPUT         lr   for left and right (default)"
	echo "                       l    for left"
	echo "                       r    for right"
	echo "                       tb   for top and bottom (default)"
	echo "                       t    for top"
	echo "                       b    for bottom"
	echo "                       none for no audio"
	echo "-bv VIDEO_BITRATE      bitrate for video (e.g. 2000k)"
	echo "-ba AUDIO_BITRATE      bitrate for audio (e.g. 192k)"
	echo "-vl VOLUME             amplitude for left volume (e.g. 1.2)"
	echo "                       -vr for right"
	echo "                       -vt for top"
	echo "                       -vb for bottom"
	echo "-fr FRAME_RATE         frame rate (e.g. 29.97)"
	echo "-sz SIZE               size for output (e.g. 1920x1080)"
	echo "-stl STARTTIME         start time for left movie (e.g. HH:MM:SS[.mmm])"
	echo "                       -str for right"
	echo "                       -stt for top"
	echo "                       -stb for bottom"
	echo "-etl ENDTIME           endtime for left movie (e.g. HH:MM:SS[.mmm])"
	echo "                       -etr for right"
	echo "                       -ett for top"
	echo "                       -etb for bottom"
	echo "-ell ELAPSTIME         elapstime for left movie (e.g. HH:MM:SS[.mmm])"
	echo "                       -elr for right"
	echo "                       -elt for top"
	echo "                       -elb for bottom"
        exit 0
fi

function preconvert(){
	input=$1; shift
	output=$1; shift
	pw=$1; shift
	ph=$1; shift
	vbitrate=$1; shift
	abitrate=$1; shift
	starttime=$1; shift
	endtime_with_opt=$1; shift
	volume=$1; shift
	framerate=$1

	iwh=`ffmpeg -i ${input} 2>&1 | egrep 'Stream.*Video' | sed -e 's/^.* \([0-9][0-9]*x[0-9][0-9]*\)[^0-9].*$/\1/g'`
	iw=`echo ${iwh} | cut -dx -f1`
	ih=`echo ${iwh} | cut -dx -f2`

	cond=`echo ${iw}*${ph}/${ih}/${pw} | bc`

	if [ ${cond} -gt 0 ]
	then
		sw=${pw}
		sh=`echo ${pw}*${ih}/${iw} | bc`
		padw=0
		padh=`echo "(${ph} - ${sh})/2" | bc`
	else
		sh=${ph}
		sw=`echo ${ph}*${iw}/${ih} | bc`
		padh=0
		padw=`echo "(${pw} - ${sw})/2" | bc`
	fi

	ffmpeg -i ${input} -ss ${starttime} ${endtime_with_opt} -vcodec h264 -b:v ${vbitrate} -r ${framerate} -strict -2 -acodec aac -b:a ${abitrate} -vol ${volume} -filter_complex "[0:v]scale=${sw}:${sh},pad=${pw}:${ph}:${padw}:${padh}" -y ${output}
}

left_movie=""
right_movie=""
top_movie=""
bottom_movie=""
output_movie=""
audio_input=""
video_bitrate="2000k"
audio_bitrate="192k"
left_volume="256"
right_volume="256"
top_volume="256"
bottom_volume="256"
frame_rate="3000/1001"
size="640x360"
left_starttime="00:00:00"
left_endelapstime="-t 24:00:00"
right_starttime="00:00:00"
right_endelapstime="-t 24:00:00"
top_starttime="00:00:00"
top_endelapstime="-t 24:00:00"
bottom_starttime="00:00:00"
bottom_endelapstime="-t 24:00:00"

while [ $# -ne 0 ]
do
	case $1 in
	-l)
		shift
		left_movie="$1"
		;;
	-r)
		shift
		right_movie="$1"
		;;
	-t)
		shift
		top_movie="$1"
		;;
	-b)
		shift
		bottom_movie="$1"
		;;
	-o)
		shift
		output_movie="$1"
		;;
	-a)
		shift
		audio_input="$1"
		;;
	-bv)
		shift
		video_bitrate="$1"
		;;
	-ba)
		shift
		audio_bitrate="$1"
		;;
	-vl)
		shift
		vol=`echo 256 \* $1 | bc | sed -e 's/\..*$//'`
		left_volume="${vol}"
		;;
	-vr)
		shift
		vol=`echo 256 \* $1 | bc | sed -e 's/\..*$//'`
		right_volume="${vol}"
		;;
	-vt)
		shift
		vol=`echo 256 \* $1 | bc | sed -e 's/\..*$//'`
		top_volume="${vol}"
		;;
	-vb)
		shift
		vol=`echo 256 \* $1 | bc | sed -e 's/\..*$//'`
		bottom_volume="${vol}"
		;;
	-fr)
		shift
		frame_rate="$1"
		;;
	-sz)
		shift
		size="$1"
		;;
	-stl)
		shift
		left_starttime="$1"
		;;
	-etl)
		shift
		left_endelapstime="-to $1"
		;;
	-ell)
		shift
		left_endelapstime="-t $1"
		;;
	-str)
		shift
		right_starttime="$1"
		;;
	-etr)
		shift
		right_endelapstime="-to $1"
		;;
	-elr)
		shift
		right_endelapstime="-t $1"
		;;
	-stt)
		shift
		top_starttime="$1"
		;;
	-ett)
		shift
		top_endelapstime="-to $1"
		;;
	-elt)
		shift
		top_endelapstime="-t $1"
		;;
	-stb)
		shift
		bottom_starttime="$1"
		;;
	-etb)
		shift
		bottom_endelapstime="-to $1"
		;;
	-elb)
		shift
		bottom_endelapstime="-t $1"
		;;
	esac
	shift
done

if [ "X${audio_input}" = "X" ]
then
	if [ "X${left_movie}" = "X" ]
	then
		audio_input="tb"
	else
		audio_input="lr"
	fi
fi

pw=`echo ${size} | cut -dx -f1`
ph=`echo ${size} | cut -dx -f2`

if [ "X${left_movie}" = "X" ]
then
	half_ph=`echo ${ph}/2 | bc`
	preconvert ${top_movie} /tmp/mergemovie.$$.1.tmp.mp4 ${pw} ${half_ph} ${video_bitrate} ${audio_bitrate} ${top_starttime} "${top_endelapstime}" ${top_volume} ${frame_rate}
	preconvert ${bottom_movie} /tmp/mergemovie.$$.2.tmp.mp4 ${pw} ${half_ph} ${video_bitrate} ${audio_bitrate} ${bottom_starttime} "${bottom_endelapstime}" ${bottom_volume} ${frame_rate}
else
	half_pw=`echo ${pw}/2 | bc`
	preconvert ${left_movie} /tmp/mergemovie.$$.1.tmp.mp4 ${half_pw} ${ph} ${video_bitrate} ${audio_bitrate} ${left_starttime} "${left_endelapstime}" ${left_volume} ${frame_rate}
	preconvert ${right_movie} /tmp/mergemovie.$$.2.tmp.mp4 ${half_pw} ${ph} ${video_bitrate} ${audio_bitrate} ${right_starttime} "${right_endelapstime}" ${right_volume} ${frame_rate}
fi

ffmpeg -i /tmp/mergemovie.$$.1.tmp.mp4 -strict -2 -acodec copy -vn -y /tmp/mergemovie.$$.3.tmp.wav.mp4
ffmpeg -i /tmp/mergemovie.$$.2.tmp.mp4 -strict -2 -acodec copy -vn -y /tmp/mergemovie.$$.4.tmp.wav.mp4

case ${audio_input} in
lr|tb)
	ffmpeg -i /tmp/mergemovie.$$.3.tmp.wav.mp4 -i /tmp/mergemovie.$$.4.tmp.wav.mp4 -strict -2 -acodec aac -b:a ${audio_bitrate} -filter_complex amix=inputs=2 -y /tmp/mergemovie.$$.5.tmp.wav.mp4
	;;
l|t)
	mv /tmp/mergemovie.$$.3.tmp.wav.mp4 /tmp/mergemovie.$$.5.tmp.wav.mp4
	;;
r|b)
	mv /tmp/mergemovie.$$.4.tmp.wav.mp4 /tmp/mergemovie.$$.5.tmp.wav.mp4
	;;
esac

ffmpeg -i /tmp/mergemovie.$$.1.tmp.mp4 -vcodec copy -strict -2 -an -y /tmp/mergemovie.$$.6.tmp.mp4
ffmpeg -i /tmp/mergemovie.$$.2.tmp.mp4 -vcodec copy -strict -2 -an -y /tmp/mergemovie.$$.7.tmp.mp4
if [ "X${left_movie}" = "X" ]
then
	ffmpeg -i /tmp/mergemovie.$$.6.tmp.mp4 -i /tmp/mergemovie.$$.7.tmp.mp4 -strict -2 -vcodec h264 -b:v ${video_bitrate} -filter_complex "[0:v]pad=iw:ih*2[v1];[v1][1:v]overlay=0:H/2" -y /tmp/mergemovie.$$.8.tmp.mp4
else
	ffmpeg -i /tmp/mergemovie.$$.6.tmp.mp4 -i /tmp/mergemovie.$$.7.tmp.mp4 -strict -2 -vcodec h264 -b:v ${video_bitrate} -filter_complex "[0:v]pad=iw*2:ih[v1];[v1][1:v]overlay=W/2:0" -y /tmp/mergemovie.$$.8.tmp.mp4
fi

if [ "X${audio_input}" = "Xnone" ]
then
	mv /tmp/mergemovie.$$.8.tmp.mp4 ${output_movie}
else
	ffmpeg -i /tmp/mergemovie.$$.8.tmp.mp4 -i /tmp/mergemovie.$$.5.tmp.wav.mp4 -strict -2 -vcodec copy -acodec copy -y ${output_movie}
fi

rm -f /tmp/mergemovie.$$.*.tmp.mp4 /tmp/mergemovie.$$.*.tmp.wav.mp4