apply ffmpeg to many files

2019-05-10 01:05发布

问题:

I have written simple script:

#!/bin/bash
find . -name "*.m4a" | while read filename;
do
    new_filename=$(echo "$filename" | sed "s/^\(.*\)m4a$/\1flac/g");
    if [ ! -f "$new_filename" ]
    then
            #ffmpeg -i "$filename" -acodec flac "$new_filename" > /dev/null 2>&1;
            #wait $!;
            echo "$filename";
            echo "$new_filename";
    fi
done

it outputs correct result:

./Equilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/04 - Met.m4a
./Equilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/04 - Met.flac
./Equilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/02 - Nach Dem Winter.m4a
./Equilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/02 - Nach Dem Winter.flac

if uncomment ffmpeg and wait:

./Equilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/04 - Met.m4a
./Equilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/04 - Met.flac
uilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/02 - Nach Dem Winter.m4a
uilibrium, ALAC [GER] viking.folk/2003 - Demo 2003, ALAC/02 - Nach Dem Winter.flac

And no flacs has been done!

PS

#!/bin/bash
find . -name "*.m4a" | while read filename;
do
    new_filename=$(echo "$filename" | sed "s/^\(.*\)m4a$/\1flac/g");
    if [ ! -f "$new_filename" ]
    then
            ffmpeg -i "$filename" -acodec flac "$new_filename";
            echo "$filename";
            echo "$new_filename";
    fi
    sleep 5;
done

1) encode start but suddenly stop with no error messages

2) encode couldn't start because of "uilibrium" instead of "./Equilibrium"

3) = 1)

4) = 2)

...

last) correctly

回答1:

suddenly found a solution:

#!/bin/bash
find . -name "*.m4a" | while read filename;
do
        new_filename=$(echo "$filename" | sed "s/^\(.*\)m4a$/\1flac/g");
        if [ ! -f "$new_filename" ]
        then
                ffmpeg -i "$filename" -acodec flac "$new_filename" &
                wait $!;
        fi
done

I don't know why, but if start process in background (&) and than wait for it (wait $!) all works correctly!



回答2:

Might I suggest that you can provide the following param to ffmpeg. It will process only the current file before moving onto the next file.

ffmpeg's -nostdin option avoids attempting to read user input from stdin otherwise the video file itself is interpreted.

ffmpeg -i <filename> ... -nostdin

The best part about using the above is that you can continue to use verbosity:

ffmpeg -i <filename> ... -nostdin -loglevel panic 

OR if you would rather report the output to a file do so this way:

# Custom log name (optional)
# FFREPORT=./${filename}-$(date +%h.%m.%s).log
ffmpeg -i <filename> ... -nostdin -report

You can also use a combination of the two as well.



回答3:

Two problems I can see:

ffmpeg -i "$filename" -acodec flac "$new_filename" > /dev/null 2>&1;

Could be printing an error message that you can't see because you're doing > /dev/null 2>&1, which will silence any errors.

And

wait $!

won't do anything useful, because $! is only defined if you ran a command in the background (i.e. something with &).



回答4:

Oh, euh, just please simplify your sed, it won't correct your bug, but will be more readeable :-P

$ echo m4a.m4a | sed 's/m4a$/flac/g'
m4a.flac


标签: bash ffmpeg