剪切多个视频的结尾
Cut end of multiple videos
我需要一个脚本来截断多个视频的最后 6 秒。这些视频确实都有不同的长度。
我在网上找不到任何有用的东西。
有人知道怎么做吗?
谢谢
你必须使用迂回的方式来实现这个,
ffmpeg -i file.mp4 -itsoffset 6 \
-i file.mp4 -c copy -map 0:a:0 -map 1 \
-shortest -f nut - | \
ffmpeg -y -i - -c copy -map 0 -map -0:0 -ss 6 trimmed.mp4
这 运行 两个 ffmpeg 进程通过管道连接,尽管您可以使用两个 ffmpeg 命令 运行 一个接一个地完成。
第一个命令提取文件两次并将第二个输入的时间戳偏移 6 秒。它映射来自第一个输入的音频流和来自第二个输入的所有流。第一个命令的输出设置为以最短的流结束,这是来自第一个输入的音频流。副作用是第二个输入的最后 6 秒被切断。在第二个过程中,除了第一个音频流之外的所有流都被复制到一个新的容器中。
如果您不确定文件是否有音频,可以将 -map 0:a:0
替换为 -map 0:0
一种方法,使用ffprobe
获取输入时长,bc
计算所需输出时长,ffmpeg
执行切割。此方法不要求输入包含音频流,但它需要两个额外的工具(ffprobe
和 bc
),而不仅仅是 ffmpeg
.
未提及您首选的脚本语言,因此我假设 bash 可以。按要求以脚本形式:
#!/bin/bash
for f in *.mp4; do
cut_duration=6
input_duration=$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "$f")
output_duration=$(bc <<< "$input_duration"-"$cut_duration")
ffmpeg -i "$f" -map 0 -c copy -t "$output_duration" output/"$f"
done
或作为单行:
for f in *.mp4; do ffmpeg -i "$f" -map 0 -c copy -t "$(bc <<< "$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "$f")"-6)" output/"$f"; done
windows 批处理文件几乎不可能做到这一点。这是 Powershell 的脚本:
$ListsFiles = Get-ChildItem "D:\VIDEOS\" -Filter *.avi;
Foreach ($file in $ListsFiles){
$input_d = [math]::round((ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $file.Fullname));
$output_duration=$input_d-5;
$ArgumentList = '-i "{0}" -map 0 -c copy -t {1} "D:\VIDEOS\output\{2}"' -f $file.Fullname, $output_duration, $file;
Write-Host -ForegroundColor Green -Object $ArgumentList;
Start-Process -FilePath ffmpeg -ArgumentList $ArgumentList -Wait -NoNewWindow;
}
我需要一个脚本来截断多个视频的最后 6 秒。这些视频确实都有不同的长度。
我在网上找不到任何有用的东西。
有人知道怎么做吗? 谢谢
你必须使用迂回的方式来实现这个,
ffmpeg -i file.mp4 -itsoffset 6 \
-i file.mp4 -c copy -map 0:a:0 -map 1 \
-shortest -f nut - | \
ffmpeg -y -i - -c copy -map 0 -map -0:0 -ss 6 trimmed.mp4
这 运行 两个 ffmpeg 进程通过管道连接,尽管您可以使用两个 ffmpeg 命令 运行 一个接一个地完成。
第一个命令提取文件两次并将第二个输入的时间戳偏移 6 秒。它映射来自第一个输入的音频流和来自第二个输入的所有流。第一个命令的输出设置为以最短的流结束,这是来自第一个输入的音频流。副作用是第二个输入的最后 6 秒被切断。在第二个过程中,除了第一个音频流之外的所有流都被复制到一个新的容器中。
如果您不确定文件是否有音频,可以将 -map 0:a:0
替换为 -map 0:0
一种方法,使用ffprobe
获取输入时长,bc
计算所需输出时长,ffmpeg
执行切割。此方法不要求输入包含音频流,但它需要两个额外的工具(ffprobe
和 bc
),而不仅仅是 ffmpeg
.
未提及您首选的脚本语言,因此我假设 bash 可以。按要求以脚本形式:
#!/bin/bash
for f in *.mp4; do
cut_duration=6
input_duration=$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "$f")
output_duration=$(bc <<< "$input_duration"-"$cut_duration")
ffmpeg -i "$f" -map 0 -c copy -t "$output_duration" output/"$f"
done
或作为单行:
for f in *.mp4; do ffmpeg -i "$f" -map 0 -c copy -t "$(bc <<< "$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "$f")"-6)" output/"$f"; done
windows 批处理文件几乎不可能做到这一点。这是 Powershell 的脚本:
$ListsFiles = Get-ChildItem "D:\VIDEOS\" -Filter *.avi;
Foreach ($file in $ListsFiles){
$input_d = [math]::round((ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $file.Fullname));
$output_duration=$input_d-5;
$ArgumentList = '-i "{0}" -map 0 -c copy -t {1} "D:\VIDEOS\output\{2}"' -f $file.Fullname, $output_duration, $file;
Write-Host -ForegroundColor Green -Object $ArgumentList;
Start-Process -FilePath ffmpeg -ArgumentList $ArgumentList -Wait -NoNewWindow;
}