bash script for ffmpeg conversion does not loop

2020-06-06 08:41发布

问题:

I have this bash script for a batch conversion of some mp4 files:

#!/bin/bash
ls dr*.mp4 | grep -v -E "\.[^\.]+\." | sed "s/.mp4//g" | while read f 
do
    TARGET="$f.ffmpeg.mp4"
    if ! [ -f $TARGET ]
    then
        echo $TARGET
        ffmpeg  -nostdin -i $f.mp4 -s 320x180 -vc h264 -acodec copy -f mp4 -y $TARGET
    fi

    TARGET="$f.ffmpeg.flv"
    if ! [ -f $TARGET ]
    then
        echo $TARGET
        ffmpeg  -nostdin -i $f.mp4 -s 320x180 -acodec copy -y $TARGET
    fi

    TARGET="$f.jpg"
    if ! [ -f $TARGET ]
    then
        echo $TARGET
        ffmpeg -nostdin -i $f.ffmpeg.mp4 -ss 0 -vframes 1 -f image2 $TARGET
    fi

    TARGET="$f.ffmpeg.ogv"
    if ! [ -f $TARGET ]
    then
        echo $TARGET
        ffmpeg  -nostdin -i $f.mp4 -s 320x176 -ar 11025 -acodec libvorbis -y $TARGET
    fi
done 

It runs once but does and converts the input file name to 4 different formats, but does not loop to the next input file name. I tried to shuffle the order of the various conversions, but still the script runs exactly once for one file name. I tried to run ffmpeg with the -nostdin flag, but it says

"Unrecognized option 'nostdin'"

The ffmpeg version is ffmpeg version 0.10.6-6:0.10.6-0ubuntu0jon1~lucid2 - I just update the ffmpeg package from http://ppa.launchpad.net/jon-severinsson/ffmpeg/ubuntu and cannot find an newer version. The base system is

Distributor ID: Ubuntu 
Description:    Ubuntu 10.04.1 LTS 
Release:        10.04 
Codename:       lucid

回答1:

Don't parse the Output of ls, you can use globbing instead. You should also quote your variables to account for possible whitespace in the filenames:

for input in dr*.mp4; do
    output=${input%.mp4}.ffmpeg.mp4
    [ -f "${output}" ] || ffmpeg -nostdin -i "${input}" -s 320x180 -vc h264 -acodec copy -f mp4 -y "${output}"

    output=${input%.mp4}.ffmpeg.flv
    [ -f "${output}" ] || ffmpeg -nostdin -i "${input}" -s 320x180 -acodec copy -y "${output}"

    [...]
done

As for the error you get, according to the ChangeLog the -nostdin option got added in ffmpeg 1.0, so you need update your ffmpeg installation from 0.1x to 1.0.x.



回答2:

I ran into the same problem with a while loop and it was because I was missing the -nostdin flag on one of my ffmpeg commands. I think because read reads from standard input that having an ffmpeg command in there was eating some of the data. In my case, my while loop was like:

find /tmp/dir -name '*-video' | while read -r file; do
    # note: I forgot -nostdin on the ffmpeg command
    ffmpeg -i "$file" -filter:v "amazing_filtergraph" out.mp4
done

And I'd get an error about tmp/dir/1-video not found (notice the beginning forward slash was missing from the path). As soon as I added -nostdin the problem was resolved.

Also note, on your while loop, you pretty much always want to use the -r flag otherwise some unexpected newline continuations can occur.