FFmpeg可以同时对多个文件进行编码吗?

FFmpeg可以同时对多个文件进行编码吗?,ffmpeg,Ffmpeg,我正在编写一个shell脚本,对给定目录中的音频文件进行编码,并将.flac文件输出到另一个目录。我的概念验证逐个循环遍历每个文件,并通过ffmpeg运行它。我怀疑有一种方法可以在一个命令中将整个输入文件列表传递给ffmpeg,但我还没有弄明白 我当前的版本如下所示: #!/bin/sh encode_album() { local artist=$1; shift local album=$1; shift local in_dir="${HOME}/Music/ra

我正在编写一个shell脚本,对给定目录中的音频文件进行编码,并将.flac文件输出到另一个目录。我的概念验证逐个循环遍历每个文件,并通过ffmpeg运行它。我怀疑有一种方法可以在一个命令中将整个输入文件列表传递给ffmpeg,但我还没有弄明白

我当前的版本如下所示:

#!/bin/sh

encode_album() {
    local artist=$1; shift
    local album=$1; shift
    local in_dir="${HOME}/Music/raw-imports/${artist}/${album}"
    local out_dir="${HOME}/Music/library/${artist}/${album}"

    mkdir -p "${out_dir}"

    find "${in_dir}" -type f -name *.aiff | while IFS= read -r in_file; do
        local track_name=$(basename "${in_file}" .aiff)
        local out_file="${out_dir}/${track_name}.flac"

        encode_track "${in_file}" "${out_file}"
    done
}

encode_track() {
    local in_file=$1; shift
    local out_file=$1; shift

    </dev/null ffmpeg -i "${in_file}" -codec:a flac "${out_file}"
}

encode_album "Rolf Lislevand" "La Mascarade"
#/垃圾箱/垃圾箱
encode_相册(){
本地艺人=$1;班次
本地相册=$1;移位
本地in_dir=“${HOME}/Music/raw imports/${artist}/${album}”
local out_dir=“${HOME}/Music/library/${artist}/${album}”
mkdir-p“${out_dir}”
查找“${in_dir}”-键入f-name*.aiff |,而IFS=read-r in_file;do
本地曲目\u name=$(basename“${in\u file}”.aiff)
本地输出文件=“${out\u dir}/${track\u name}.flac”
对轨道“${in\u file}”${out\u file}”进行编码
完成
}
编码轨道(){
本地输入文件=$1;移位
本地输出文件=$1;移位

是的,您可以使用批处理。 有关更多信息,请参见此处:

基本语法是

ffmpeg -i input1
       -i input2
       ...
       -i inputn
       -map 0 -f flac out1.flac
       -map 1 -f flac out2.flac
       ...
       -map n-1 -f flac outn.flac

如果有帮助,您可以使用或修改以下脚本。
ffmpeg
的内置批处理语法对于许多文件来说可能有点笨拙,因此我认为尝试使用它而不是逐个循环没有多大好处,并且该脚本做了一些默认情况下在ffmpeg中无法完成的事情,包括自动递归和目标位置中的目录结构

完全公开,我是作者

投寄时的代码:

#!/bin/bash

########################
# CONSTANTS
########################
# The requested output sample rate.
MAX_SR=$1
# The specified output file extension
OUTFILE_EXT=$2
# The specified volume boost for output file
VOL_BOOST=$3
# Don't go below this sample rate:
MIN_SR=44100
# The directory to output converted files to. Use trailing slash. Needs manual escaping (not quotes)
# if this is customized and there are special chars (spaces, etc) in the pathname supplied, eg: 
# OUT_DIR=~/Music/iTunes/iTunes\ Media/Automatically\ Add\ to\ iTunes.localized/
OUT_DIR=~/batch_resampled/

########################
# UTILITY FUNCTIONS
########################
# Send string to stderr
err() {
    >&2 echo "$1"
}

# Display usage info
print_usage() {
    err ""
    err "USAGE: "$(basename $0)" <sample_rate> <outfile_extension> [vol_adjust_db]"
    err ""
    err "Converts all supported audio files in the current directory to the format corresponding "
    err "to the given file extension (don't include the dot), at the speciied sample rate (in Hz). "
    err "To specify a maximum output sample rate, where any input file of a greater rate gets downsampled "
    err "to the nearest even multiple of either 44100 or 48000, add an 'm' to the end of the number, "
    err "eg. '96000m'. If an input file has a sample rate that is already below this, it will not be upsampled. "
    err ""
    err "An optional volume adjust (in dB) can be given (positive number for boost, "
    err "negative for cut). "
    err ""
    err "Renames file basenames on conversion and doesn't re-convert already "
    err "converted files on subsequent runs."
    err ""
    err "Supported infile types: flac,dsf,dff,wav,aiff,m4a,mp3"
    err "Supported outfile types: flac,wav,aiff,m4a(alac),mp3"
    err ""
}

########################
# ARGS CHECKING
########################
if [[ -z "$OUTFILE_EXT" || $OUTFILE_EXT == "dsf" || $OUTFILE_EXT == "dff" ]]
then
    print_usage
    exit 1
fi

########################
# GLOBALS
########################
# Added to the end of the file basename
suffix=""
# Args to pass to the resampler
filter_args=""
pre_filter_args=""
# Args for the output file, like codec
out_args=""
# Volume filter level. Setting to 0dB explicitly seems to prevent replaygain-related clipping.
# Also comes in handy for boosting DSD file levels on conversion to PCM.
vol_level=""
# The sample rate of each input file
infile_sr=""
# The sample format of each input file
infile_sfmt=""
# Output file name
output_file=""
# Level of any errors encountered.
error_level=0
# Lowest factor of input file
lowest_factor=0
# Destination sample rate of a given output file
dest_sr=$MAX_SR

########################
# FUNCTIONS
########################
# Recalculate sample rate to nearest even multiple
# of 44.1/48K, depending on the input file's sample rate and the max sample rate given
recalc_sr() {
    infile_sr=$1
    lowest_factor=$2
    max_sr=$(echo $MAX_SR | sed 's/m$//')
    dest_sr=0

    # Make sure our output sample rate is a multiple of either 44.1K or 48K
    if [[ ! $(($max_sr % 44100)) -eq 0 && ! $(($max_sr % 48000)) -eq 0 ]]
    then
        err "ERROR: Only even multiples of 44100 and 48000 are allowed to be specified for maximum output sample rates!"
        return 2
    fi

    # If the input is already at or below the specified max...
    if [[ $infile_sr -le $max_sr ]]
    then
        # Nothing to calculate. Keep sr the same
        dest_sr=$infile_sr

        err "INFO: Input sample rate <= output rate. Will not be upsampled."
        echo "$dest_sr"
        return 0
    # If user specified the min sr as the max
    elif [[ $max_sr -eq $MIN_SR ]]
    then
        # Downsample even if not even multiple
        dest_sr=$max_sr

        err "INFO: No even multiple available below minimum rate of ${MIN_SR}, so downsampling to ${MIN_SR}."
        echo "$dest_sr"
        return 0
    else
        # Find closest even multiple below the max. Takes advantage of the dropping of decimals by bash for easy math.
        dest_sr=$(( ($max_sr/$lowest_factor)*$lowest_factor ))

        err "INFO: Downsampling to even multiple of ${lowest_factor}"
        echo "$dest_sr"
        return 0
    fi
}

# Takes input file sample rate as the only param.
# Determines whether this is an even multiple or 44.1K or 48K
# Delegates to the recalc_sr function and passes through the results via echo's
find_lowest_factor() {
    infile_sr=$1

    if [[ $infile_sr && $(($infile_sr % 44100)) -eq 0 ]]
    then
        echo "44100"
        return 0
    elif [[ $infile_sr && $(($infile_sr % 48000)) -eq 0 ]]
    then
        echo "48000"
        return 0
    else
        err "ERROR: Only multiples of 44100 and 48000 are allowed for input sample rates when in maximum mode!"
        return 1
    fi
}

# Takes an input file as the only argument and converts it
# based on certain conditions, or returns an error if necessary
conv() {
    # The input file with "./" stripped from the beginning
    item=${1#./}

    err "item: $item"

    # Get some specifics about this input file
    # To see all info about a particular input file on the command line, type ffprobe -v error -show_streams <file>
    infile_sfmt=$(ffprobe -v error -select_streams a:0 -show_entries stream=sample_fmt -of default=noprint_wrappers=1:nokey=1 "$item" \
        | xargs echo -n)
    infile_sr=$(ffprobe -v error -select_streams a:0 -show_entries stream=sample_rate -of default=noprint_wrappers=1:nokey=1 "$item" \
        | xargs echo -n)

    # If user appended an "m" for "maximum" to the end of
    # the sample rate param, find nearest even multiple of
    # this infile's sample rate
    if [[ $MAX_SR =~ m$ ]]
    then
        err "INFO: Maximum sample rate specified for output. Recalculating destination sample rate"

        # Get lowest factor from infile sr and skip this file on error
        if ! lowest_factor=$(find_lowest_factor $infile_sr)
        then
            error_level=1
            err "SKIPPING ${item}..."
            return 0
        fi

        # Get destination sample rate for this file. Stop all conversion on error
        if ! dest_sr=$(recalc_sr $infile_sr $lowest_factor)
        then
            error_level=2
            err "FATAL"
            return 1
        fi
    fi

    # Append a marker to the end of the output filename indicating new sample rate
    suffix="_ff"$(($dest_sr / 1000))"k"
    filter_args="aresample=resampler=soxr:precision=32:dither_method=triangular:osr=${dest_sr}"

    # Double pass for signed to signed resampling, as ffmpeg has some kind of problem
    # with this while setting the output sample rate of a signed audio codec type w sox. 
    # This way it gets double dithered with sox, which seems to be the best way of 
    # avoiding the bug, which causes pops in the converted audio.
    if [[ $infile_sfmt =~ ^s[0-9]+ && ($item =~ .flac$ || $item =~ .m[^\.]+$) ]]
    then
        pre_filter_args="aresample=resampler=soxr:precision=32:dither_method=triangular,"
    fi

    # Set the right output codec/sfmt for m4a, wav, aif, flac
    if [[ $OUTFILE_EXT == "aiff" ]]
    then
        out_args="-acodec pcm_${infile_sfmt}be"
    elif [[ $OUTFILE_EXT == "wav" ]]
    then
        out_args="-acodec pcm_${infile_sfmt}le"
    elif [[ $OUTFILE_EXT == "m4a" ]]
    then
        out_args="-acodec alac"
    # For some reason (perhaps bc of the precision set in sox resampler),
    # signed pcm files are having their bit depth increased from 16 to 24 if we
    # don't specify to keep the sample format the same.
    elif [[ $OUTFILE_EXT == "flac" && $infile_sfmt =~ ^s[0-9]+ ]]
    then
        if [[ $infile_sfmt =~ p$ ]]
        then
            # Flac doesn't support the "p" variants of signed sample fmts
            infile_sfmt=${infile_sfmt%p}
        fi
        out_args="-sample_fmt ${infile_sfmt}"
    fi

    # Prepend output directory, strip infile extension, add suffix, add outfile extension
    output_file=${OUT_DIR}${item%.*}${suffix}.${OUTFILE_EXT}

    # Skip if we've already created this output file and it's not zero-size
    if [[ -e $output_file && -s $output_file ]]
    then
        err "INFO: Output file already exists!"
        err "SKIPPING ${output_file}"
        return 0
    fi

    # Print some info about the output file to be created
    err "filter_args: $pre_filter_args$filter_args$vol_level"
    err "out_args: $out_args"
    err "output_file: $output_file"

    # Where the magic happens
    ffmpeg -y -i "$item" -af "$pre_filter_args$filter_args$vol_level" $out_args "$output_file"

    return 0
}

########################
# DRIVER CODE
########################
# Set volume boost/cut if given as argument
if [[ $VOL_BOOST ]]
then
    vol_level=",volume=${3}dB"
fi

# Recreate the directory structure from the input dir in the output dir
# First create the output directory in case there are no subdirectories in CWD
mkdir "$OUT_DIR"
find . -mindepth 1 -type d -exec mkdir -p -- "${OUT_DIR}{}" \;

# Recursively loop through all supported audio files, call the conv function on each
# Using brace expansion to search both the current dir, and subdirs
for item in ./{*,**/*}.{flac,dsf,dff,wav,aiff,m4a,mp3}
do 
    # Skip unexpanded globs
    if [[ -e $item ]] 
    then 
        # Reset some file-specific resampler args
        pre_filter_args=""
        out_args=""

        # If we got a fatal error on trying to convert this file...
        if ! conv "$item"
        then
            # Exit loop
            break
        fi
    fi
done

# Not doing anything specific with the various error levels for now. Just checking for existence.
if [[ $error_level -ne 0 ]]
then
    err ""
    err "WARNING: Errors were encountered. Some or all files may not have been converted"
    print_usage
    exit 1
else
    exit 0
fi
!/bin/bash
########################
#常数
########################
#请求的输出采样率。
MAX_SR=$1
#指定的输出文件扩展名
OUTFILE_EXT=$2
#为输出文件指定的卷提升
音量增加=3美元
#不要低于此采样率:
MIN_SR=44100
#要将转换后的文件输出到的目录。使用尾随斜杠。需要手动转义(非引号)
#如果这是自定义的,并且提供的路径名中有特殊字符(空格等),例如:
#OUT\u DIR=~/Music/iTunes/iTunes\Media/Automatically\Add\to\iTunes.localized/
OUT\u DIR=~/batch\u重采样/
########################
#效用函数
########################
#将字符串发送到stderr
err(){
>&2回显“$1”
}
#显示使用信息
打印_用法(){
错误“”
错误“用法:$(基本名称$0)”[vol\u adjust\u db]
错误“”
err“将当前目录中所有受支持的音频文件转换为相应的格式”
err”到给定的文件扩展名(不包括点),以指定的采样率(以Hz为单位)
err“指定最大输出采样率,其中任何速率更高的输入文件都会进行下采样”
err“在数字末尾加上一个'm',直到44100或48000中最接近的偶数倍
错误“例如96000m”。如果输入文件的采样率已低于此值,则不会对其进行上采样
错误“”
err“可以提供可选的音量调整(以dB为单位)(增压为正数,”
错误“切割为负数”)
错误“”
错误“在转换时重命名文件基名,但尚未重新转换”
err“在后续运行中转换的文件”
错误“”
错误“支持的填充类型:flac、dsf、dff、wav、aiff、m4a、mp3”
err“支持的输出文件类型:flac、wav、aiff、m4a(alac)、mp3”
错误“”
}
########################
#参数检查
########################
如果[-z“$OUTFILE_EXT”|$OUTFILE_EXT==“dsf”|$OUTFILE_EXT==“dff”]
然后
打印使用
出口1
fi
########################
#全球的
########################
#添加到文件basename的末尾
后缀=“”
#要传递给重采样器的参数
筛选器_args=“”
pre_filter_args=“”
#输出文件的参数,如编解码器
out_args=“”
#卷筛选器级别。显式设置为0dB似乎会阻止与replaygain相关的剪辑。
#在转换到PCM时,还可以方便地提高DSD文件级别。
vol_level=“”
#每个输入文件的采样率
infle_sr=“”
#每个输入文件的示例格式
infle_sfmt=“”
#输出文件名
output_file=“”
#遇到的任何错误的级别。
错误\u级别=0
#输入文件的最低因子
最低系数=0
#给定输出文件的目标采样率
dest_sr=$MAX_sr
########################
#功能
########################
#重新计算采样率至最接近的偶数倍
#44.1/48K,具体取决于输入文件的采样率和给定的最大采样率
recalc_sr(){
填充率=1美元
最低_系数=2美元
max_sr=$(echo$max_sr | sed's/m$/'))
dest_sr=0
#确保我们的输出采样率为44.1K或48K的倍数
如果[[!$($max_sr%44100))-eq 0&!$($max_sr%48000))-eq 0]]
然后
err“ERROR:最大输出采样率只允许指定44100和48000的偶数倍!”
返回2
fi
#如果输入已经达到或低于指定的最大值。。。
如果[$infle_sr-le$max_sr]]
然后
#无需计算。保持sr不变
dest_sr=$infle_sr

犯错误"信息:输入采样率该线程中的每个示例都是关于逐个循环文件,就像我已经在做的一样。我想知道ffmpeg是否支持类似
ffmpeg-I file1 file2 file3…-编解码器:flac out1 out2 out3…
您可以将类似类型的多个文件转换为另一种相同类型的文件,如:ls*.avi|xargs-I{}ffmpeg-I{}{}.mp3您还可以在这里看到多个输出:在windows上,如果我在不同的文件夹中有长文件,是否可以将文本文件的路径提供给ffmpeg而不是“-I input1-I input2…”?为什么这段代码同时对所有文件进行编码?如何告诉cmd交替编码文件?