0

i have the following bash script (taken from FFmpeg)

#!/bin/bash ################################################################################ # # Script name: MultiMedia Concat Script (mmcat) # Author: burek ([email protected]) # 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=${@:2:1} ################################################################################ # # NO NEED TO TOUCH ANYTHING AFTER THIS LINE! # ################################################################################ # the version of the script VERSION=1.3 # location of temp folder TMP=${@:1:1} rm -rf $TMP mkdir $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=${@:3:1} last=${@:$#:1} len=$(($#-4)) inputs=${@:4:$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 2>/dev/null </dev/null & ffmpeg -y -i "$first" -an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_v1 2>/dev/null </dev/null & # if you need to log the output of decoding processes (usually not necessary) # then replace the "2>/dev/null" in 2 lines above with your log file names, like this: #ffmpeg -y -i "$first" -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a1 2>$TMP/log.a.1 </dev/null & #ffmpeg -y -i "$first" -an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_v1 2>$TMP/log.v.1 </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 ffmpeg -y -i "$f" -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a$i 2>/dev/null </dev/null & { ffmpeg -y -i "$f" -an -f yuv4mpegpipe -vcodec rawvideo - 2>/dev/null </dev/null | tail -n +2 > $TMP/mcs_v$i ; } & # if you need to log the output of decoding processes (usually not necessary) # then replace the "2>/dev/null" in 2 lines above with your log file names, like this: #ffmpeg -y -i "$f" -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a$i 2>$TMP/log.a.$i </dev/null & #{ ffmpeg -y -i $f -an -f yuv4mpegpipe -vcodec rawvideo - 2>$TMP/log.v.$i </dev/null | tail -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 -y -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i $TMP/mcs_a_all \ -y -f yuv4mpegpipe -vcodec rawvideo -i $TMP/mcs_v_all \ $EXTRA_OPTIONS \ $last ################################################################################ # remove all fifos ################################################################################ rm -f $TMP/mcs_* 

The above scripts takes arguments like this

bash script.sh tmp_folder video1 video2 video3 video4 ... output 

Its working fine, however it doesnt read correctly the arguments when they have spaces. For example if i have a video located in "/tmp/my video.avi" it will fail to read it properly and thinks its different argument.

The problem is in these lines

first=${@:3:1} last=${@:$#:1} len=$(($#-4)) inputs=${@:4:$len} 

Please note that you will see inside the scripts that video2 video3 and video4 are being processed seperate than video1.

    2 Answers 2

    0

    I guess the (or one if there are many) problem is this line:

    inputs=${@:4:$len} 

    If $len is bigger than 1 then this converts an array slice into a string and there the word splitting problem arises.

    possible solution

    If should work if the above line is changed to

    inputs=("${@:4:$len}") 

    and this

    for f in $inputs 

    to

    for f in "${inputs[@]}" 
    2
    • yes, but how do i fix it?
      – OhGodWhy
      CommentedDec 24, 2014 at 15:34
    • @BlackDream I have extended my answer.CommentedDec 25, 2014 at 0:04
    -1

    You have to set the following code before any working files in your script:

    SAVEIFS=$IFS IFS=$(echo -en "\n\b") 

    Then when you want to exit from your script, you have to do it:

    $IFS=$SAVEIFS 
    3
    • 1
      I prefer to save IFS using quotes (SAVEIFS="$IFS") to preserve whitespace, which IFS by default is. Setting $IFS=$SAVEIFS does not do what you want, you want IFS="$SAVEIFS". $IFS="whatever" will try to set the contents of IFS, not IFS. You do not have to restore IFS when leaving the script, because it runs in its own subshell. But I would enclose all those $@ assignments in quotes: first="${@:3:1}".
      – lsd
      CommentedDec 24, 2014 at 2:04
    • 1
      @lsd No, assignments are one of the few places in shell syntax where you don't need double quotes: SAVEIFS="$IFS" is exactly equivalent to SAVEIFS=$IFS (intuitively, if the syntax calls for a single word, no variable substitution or globbing will occur). Not that setting IFS will make the script fully work (it will protect spaces but not globbing characters), and this isn't the easiest way to do it either (setting IFS to a newline would be sufficient, no need to save the value or to use echo, and as you note there's no point in saving the old value), but it's a start.CommentedDec 24, 2014 at 20:07
    • @lsd i'm working with my answer in my scripts....CommentedDec 25, 2014 at 0:49

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.