我需要剪切 MP4 视频。开头部分和结尾部分以批处理方式

I need to cut MP4 videos. A part at the beginning and a part at the end in a batch fashion

我有几个培训视频。所有 .MP4。

我想删除整个文件夹开头的 3.5 秒和结尾的 4.5 秒...

我知道 ffmpeg 和 ffprobe - 但我对它们的了解和掌握都有限。

有人可以为此提供一个脚本,或者至少提供一个可以让我轻松完成此操作的程序吗?我一直在搜索,但每次都遇到死胡同或无法运行的脚本。

我也愿意使用 Linux/Windows 但不会 mac。

编辑:第一部分完成。将继续进一步研究该命令以学习批处理;这是简单的部分,如何批处理 trim 整个 MP4 文件夹:

for %%a in ("*.mp4") do ffmpeg -i "%%a" -ss 00:00:03.5 -vcodec copy -acodec copy "newfiles\%%~na.mp4"

pause

我解决了。我不介意帮助你,但我不会提供完整的解决方案。但是,我会给你一些最棘手的部分的提示。我会留给你填空。

ffmpeg会让你为所欲为。 -ss 开关指定起始位置。 -t 指定持续时间。不幸的是,没有开关或程序替换变量可以在内部对 trim-right 的视频长度执行所需的数学运算。您必须通过脚本来计算它。

首先您需要未修改视频的总长度:

for /f "tokens=2" %%x in (
    '2^>^&1 ffmpeg -i "%%~fI" ^| find /i "duration"'
) do set "length=%%x"

要计算 -t 开关的值,您可以调用 PowerShell 来确定 newLength = totalLength - (leftTrim + rightTrim)。这是秘诀:

powershell "'{0}' -f ([timespan]'%length:,=%').add([timespan]::fromseconds(-(%trim-left% + %trim-right%)))"

计算出目标长度后,将其插入 ffmpeg,如下所示:

ffmpeg -i "%%~fI" -ss %trim-left% -t %target_length% -c:v copy -c:a copy "%destination-dir%\%%~nxI"

感谢大家鼓励我继续寻找,我找到了一个完美的解决方案。这里是。恐怕即使在评论中给出的例子也让我望而却步,但我仍然会尝试阅读并自学这些命令是如何工作的。再次感谢。替换 8.25(结束 trim)和 4.25(开始 trim)并更改值,直到您对输出满意为止。

@Echo Off
SetLocal
Set "ext=mp4"
Set "opts=-v quiet"
Set "opts=%opts% -print_format "compact=print_section=0:nokey=1:escape=csv""
Set "opts=%opts% -show_entries "format=duration""
If Exist *.%ext% (If Not Exist "Trimmed\" MD Trimmed)
For %%a In (*.%ext%) Do Call :Sub "%%~a"
Exit/B

:Sub
For /f "Tokens=1* Delims=." %%a In (
    'FFProbe %opts% %1') Do (Set/A "ws=%%a-8.25" & Set "ps=%%b")
rem If %ws% Lss 20 GoTo :EOF
Set/A hh=ws/(60*60), lo=ws%%(60*60), mm=lo/60, ss=lo%%60
If %hh% Lss 10 Set hh=0%hh%
If %mm% Lss 10 Set mm=0%mm%
If %ss% Lss 10 Set ss=0%ss%
FFMpeg -i %1 -ss 00:00:04.2500 -to %hh%:%mm%:%ss%.%ps:~,3% -c:v copy -c:a copy "Trimmed\%~1"

埃里克·拉隆德的剧本很好,谢谢!

对于那些不能或不喜欢安装 ffmpeg 的人,我添加了 ffmpeg 路径变量。在我的场景中,我从开始缩短 14 秒,在结束时缩短 9 秒。

@Echo Off
SetLocal
Set "ext=mp4"
Set "opts=-v quiet"
Set "opts=%opts% -print_format "compact=print_section=0:nokey=1:escape=csv""
Set "opts=%opts% -show_entries "format=duration""
Set ffmpeg=C:\Users\user\Downloads\ffmpeg-20180102-57d0c24-win64-static\bin\
If Exist *.%ext% (If Not Exist "Trimmed\" MD Trimmed)
For %%a In (*.%ext%) Do Call :Sub "%%~a"
Exit/B

:Sub
For /f "Tokens=1* Delims=." %%a In (
    '%ffmpeg%\ffprobe %opts% %1') Do (Set/A "ws=%%a-9.00" & Set "ps=%%b")
Set/A hh=ws/(60*60), lo=ws%%(60*60), mm=lo/60, ss=lo%%60
If %hh% Lss 10 Set hh=0%hh%
If %mm% Lss 10 Set mm=0%mm%
If %ss% Lss 10 Set ss=0%ss%
%ffmpeg%\ffmpeg -i %1 -ss 00:00:14.000 -to %hh%:%mm%:%ss%.%ps,~3% -c:v copy -c:a copy "Trimmed\%~1"

op回答的一个小魔咒(由于积分低,我无法在他的评论下回复): 最后一行改为:

FFMpeg -ss 00:00:04.2500 -to %hh%:%mm%:%ss%.%ps:~,3% -i %1 -c:v copy -c:a copy -avoid_negative_ts make_zero "Trimmed\%~1"

如果您在旧电视上播放视频,这样它会切入关键帧以避免音频不同步

回应 Erkko 的回答。

Set ffmpeg=C:\Users\user\Downloads\ffmpeg-20180102-57d0c24-win64-static\bin\

我用过,

Set ffmpeg="C:\Program Files (x86)\K-Lite Codec Pack\Tools"

并且出于某种原因它无法正常工作。

我想从开始缩短 10 秒,从结束缩短 30 秒。

'%ffmpeg%\ffprobe %opts% %1') Do (Set/A "ws=%%a-30.00" & Set "ps=%%b")

%ffmpeg%\ffmpeg -i %1 -ss 00:00:10.000 -to %hh%:%mm%:%ss%.%ps:~,3% -c:v copy -c:a copy "Trimmed2\%~1"

导致开始时为 10 秒,结束时为 20 秒。我不得不将 30 更改为 40

'%ffmpeg%\ffprobe %opts% %1') Do (Set/A "ws=%%a-40.00" & Set "ps=%%b")

在结尾启用 30 秒剪辑。这是批处理的工作方式还是有错误?