ffmpeg从大型视频bash中选择子剪辑并创建输出文件名

时间:2018-06-29 17:13:19

标签: bash video ffmpeg

我在Mac终端上使用bash命令。对于目录中的250个.mp4文件中的每个文件,我需要创建一个新的输出文件,该文件从每个输入文件中提取4个子剪辑:第一个子剪辑(从第二个10到20),第二个子剪辑(在输入文件的33%阶段为10秒) ,第3个子剪辑(在输入文件的66%处为10秒)和第4个子剪辑(在输入文件结束前30秒开始为10秒)。每个输入文件的长度大约为10-15分钟。

我尝试了一个输入文件,以下bash脚本有效:

#!/bin/bash
for file in *.mp4; do ffmpeg -i "$file" -vf "select='between(t, 10, 20) + between(t, 197, 207) + between(t, 393, 403) + between(t, 570,580)',
setpts=N/FRAME_RATE/TB" -qscale 0 -af "aselect='between(t, 10, 20) + 
between(t, 197, 207) + between(t, 393, 403) + between(t, 570, 580)', 
asetpts=N/SR/TB" outputfile.mp4; done

但是,我不知道如何在250个mp4文件中循环播放。具体来说,我有2个问题:

  1. 上面的代码显示了我从用于测试代码的输入文件中手动检查的特定秒数。我需要根据上述时间将代码自动化。
  2. 将输出文件命名为与输入文件相同,但后缀为“ _1”

总而言之,我有一个目录,其中输入文件的长度在10-15分钟之间:

inputfile1.mp4
inputfile2.mp4
inputfile3.mp4
.......
inputfile250.mp4

我想将输入文件和输出文件放在同一目录:

inputfile1.mp4
inputfile1_1.mp4 #this is 40 seconds long
inputfile2.mp4
inputfile2_1.mp4 #this is 40 seconds long
inputfile3.mp4
inputfile3_1.mp4 #this is 40 seconds long
.......
inputfile250.mp4
inputfile250_1.mp4 #this is 40 seconds long

非常感谢您。

1 个答案:

答案 0 :(得分:0)

单线执行不会提高可读性。

所以,您正在做的是:

#!/bin/bash
for file in *.mp4; do
    ffmpeg -i "$file" \
        -vf "select='between(t, 10, 20) \
        + between(t, 197, 207) + between(t, 393, 403) \
        + between(t, 570,580)', \
        setpts=N/FRAME_RATE/TB" \
        -qscale 0 \ 
        -af "aselect='between(t, 10, 20) \
        + between(t, 197, 207) \
        + between(t, 393, 403) \
        + between(t, 570, 580)', \
        asetpts=N/SR/TB" \
        outputfile.mp4
done

要详细介绍:

for file in *.mp4; do

这意味着,您将对目录中的每个文件执行ffmpeg。正如Shelter指出的那样,这有效地循环了所有不同的文件。但是,由于您正在写入固定的文件名(outputfile.mp4),因此仅保留一个输出文件:循环中最后一个mp4的简化版本。

因此,如果将输出写入不同的文件,则会看到实际上ffmpeg对所有输入文件都已执行。

如果不确定循环,请尝试插入echo来告诉您发生了什么情况。

关于输出文件的变量:${file%.mp4}_1.mp4可能会做。

所以,这意味着:

#!/bin/bash
for file in *.mp4; do
    outputfile=${file%.mp4}_1.mp4
    echo "Doing $file -> $outputfile"
    # the ffmpeg command
done