Bash Script – ‘while read’ Loop Losing Characters, Is FFmpeg to Blame?

bash-scriptingffmpeglinux

I am looping through a text file, using 'while read'. I read three variables from each line – two filenames and a decimal number. I know that this works in a vanilla setup (loop, read line, echo line, extract variables, nothing else), because I have tested it on my input file.

I am getting an odd result, though, once I add in the meat of my routine – which is a call to ffmpeg to merge the audio and video streams represented by the filenames. Successive 'read' operations omit leading characters from the line. I read here that calls for 'read' input within a 'while read' loop can cause problems, and wonder if the ffmpeg call is doing something that confuses bash, but this seems unlikely and bizarre!
NB: I don't really understand the ffmpeg call – I got it from an answer to another question.

Any help would be appreciated!

The first 'read' works as expected (and the ffmpeg command completes):

LINE  1
vidsNeedingSound/448£generic@06_10_16-09_30_47.mp4 soundToAdd/448£generic@06_10_16-12_11_54.wav 6.988354
V: vidsNeedingSound/448£generic@06_10_16-09_30_47.mp4   A: soundToAdd/448£generic@06_10_16-12_11_54.wav   D: 6.988354

The second 'read' loses 36 characters from the beginning of the line (and the ffmpeg command fails because the file represented by the variable V which takes the first item of the line doesn't point at a file):

LINE  2
6-09_30_47.mp4 soundToAdd/452£generic@06_10_16-12_11_54.wav 9.64663
V: 6-09_30_47.mp4   A: soundToAdd/452...

The third 'read' works as expected (and the ffmpeg command completes):

LINE  3
vidsNeedingSound/452£left@06_10_16-09_30_47.mp4 soundToAdd/452£left@06_10_16-12_11_54.wav 9.862118
V: vidsNeedingSound/452£left@06_10_16-09_30_47.mp4   A: soundToAdd/452...

The fourth 'read' loses 37 character (one more than the last fail) from the beginning of the line (and the ffmpeg command fails):

LINE  4
09_30_47.mp4 soundToAdd/452£right@06_10_16-12_11_54.wav 9.431392
V: 09_30_47.mp4   A: soundToAdd/452....

That's the pattern. When not preceded by a successful call to ffmpeg, the 'read' works as expected. After each successive successful ffmpeg call, characters are omitted from the beginning of the line: 36 characters to begin with, then 37, 38, 39…

The clincher is that when ffmpeg fails after a 'successful' read (due to another problem), the following 'read' works as expected.

CONCLUSION: a successful ffmpeg call results in a read fail on the next iteration through the loop.

Why does this happen, and how can I stop it?

Here's my code:

# Loop through lines in the merge file
IT_COUNT=1
while read MERGE_LINE           
    do         
    echo "LINE " $IT_COUNT
    ((IT_COUNT+=1))
    echo $MERGE_LINE   # testing use
    read VID_FILE AUD_FILE DURATION <<< "$MERGE_LINE" # Get the data from each line
    echo "V: $VID_FILE   A: $AUD_FILE   D: $DURATION"         # testing use
....
    # add audio to video
    ffmpeg -i $VID_FILE -i $AUD_FILE -filter_complex "aevalsrc=0:d=$AUD_SHIFT[s1];[s1][1:a]concat=n=2:v=0:a=1[aout]" -c:v copy -map 0:v -map [aout] $FILE_OUT -hide_banner

done <$MERGE_FILE  

Thanks for looking!

Best Answer

Use -nostdin option in ffmpeg. From FFmpeg documentation:

Enable interaction on standard input. On by default unless standard input is used as an input. To explicitly disable interaction you need to specify -nostdin.

Disabling interaction on standard input is useful, for example, if ffmpeg is in the background process group. Roughly the same result can be achieved with ffmpeg ... < /dev/null but it requires a shell.

Related Question