FFmpeg - 修剪开始和结束的固定量

FFmpeg - 修剪开始和结束的固定量

我是专业的视频编辑,但不熟练使用 FFmpeg,所以请多多包涵。我有一大批视频,长度各不相同,我想在开头和结尾处分别剪掉 10 秒。

我知道有一个“-sseof”命令可以根据视频的结尾查找时间码。但是,我只能让它给出结尾的部分,而不是指定时间之前的部分。例如,这只给出最后 10 秒:

ffmpeg -sseof -10 -i test.mp4 outputB.mp4

我想要的完全相反,一切都直到最后 10 秒。

我真的很想从一开始就将它与修剪结合起来。我的理想配方如下:

ffmpeg -i test.mp4 -ss 10 -to -sseof -10 output.mp4

但那不管用。有什么建议吗?谢谢!

编辑:

Mulvya 建议的解决方案对我有用!这是我在整个文件夹上运行脚本时使用的公式,从每个剪辑的开头剪切 4.25 秒,从结尾剪切 17.8 秒(这些值需要在几个地方分别更改,但它有效)。

for file in *.mp4; do ffmpeg -i $file -filter_complex "[0]split[s1][s2]; [s1]trim=4.25,setpts=PTS-STARTPTS,fifo[bv]; [s2]trim=4.25,setpts=(PTS-STARTPTS)+17.8/TB,fifo[v]; [bv][v]overlay=shortest=1,trim=17.8,setpts=PTS-STARTPTS[fv]; [0]volume=0[b];[0]adelay=17800|17800[a]; [b][a]amix=duration=first,volume=2,atrim=22.05,asetpts=PTS-STARTPTS[fa]" -map "[fv]" -map "[fa]" "${file%.mp4}-trimmed.mp4"; done

多谢!

答案1

有一种明智的方法和一种疯狂的方法可以做到这一点。明智的方法是事先在单独的命令中探测持续时间,然后使用该信息塑造实际的修剪命令。

探测命令:

ffprobe -v 0 -show_entries format=duration -of compact=p=0:nk=1 in.mp4

这将产生单行输出:

194.834000

所以你的命令现在是

ffmpeg -ss 10 -t 174.834 -i test.mp4 outputB.mp4

在哪里t = total duration - 20 sec


疯狂的方式比较慢,但是只需要一个命令。

ffmpeg -i in.mp4 -filter_complex
       "[0]split[s1][s2];
        [s1]trim=10,setpts=PTS-STARTPTS,fifo[bv];
        [s2]trim=10,setpts=(PTS-STARTPTS)+10/TB,fifo[v];
        [bv][v]overlay=shortest=1,trim=10,setpts=PTS-STARTPTS[fv];
        [0]volume=0[b];[0]adelay=10000|10000[a];
        [b][a]amix=duration=first,volume=2,atrim=20,asetpts=PTS-STARTPTS[fa]"
-map "[fv]" -map "[fa]" trimmed.mp4

答案2

我需要@nvd 写的内容,因此我改进了它:

#!/usr/bin/env bash

function help {
  printf "$1
Saves original file with the .saved mid-extension

Usage example 1: strip 10 seconds at the beginning only, save original as in.saved.mp3:
  $(basename $0) in.mp3 10

Usage example 2: strip 10 seconds at the beginning and 15 seconds at the end:
  $(basename $0) in.mp4 10 15
"
  exit 2
}

if [ "$1" = -h ]; then help; fi
if [ -z "$2" ]; then help 'Error: the length of time to strip from beginning must be specified.\n'; fi

MEDIA_FILE_ORIGINAL="$1"
MEDIA_FILE_CHOPPED="${1%.*}.chopped.${1##*.}"
MEDIA_FILE_SAVED="${1%.*}.saved.${1##*.}"
BEGIN_LENGTH="$2"
END_LENGTH=0
if [ "$3" ]; then END_LENGTH="$3"; fi

duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$MEDIA_FILE_ORIGINAL")
newDuration=$(python3 -c "print($duration - ($BEGIN_LENGTH + $END_LENGTH))")

ffmpeg -ss "$BEGIN_LENGTH" -t $newDuration -i "$MEDIA_FILE_ORIGINAL" -c copy "$MEDIA_FILE_CHOPPED"
if [ $? = 0 ]; then
  mv "$MEDIA_FILE_ORIGINAL" "$MEDIA_FILE_SAVED"
  mv "$MEDIA_FILE_CHOPPED" "$MEDIA_FILE_ORIGINAL"
fi

答案3

前两个答案是此处 Windows CMD 脚本的答案。它是修订版 1,并假设以下内容:

  1. CONVERT.CMD(本文中的内容)位于与文件相同的目录中。
  2. 脚本开头的变量是正确的(即文件类型和路径)

已测试,运行正常。在 Windows 10 上创建。

@echo on

@REM This basic CMD file is designed to live within the exact directory in which
@REM the files live.  This is for simplicity.  It can be edited to do more.
@REM

@REM SET MISC. VARIABLES USED IN SCRIPT
@REM
set _vFileType=mp4
set _vTrimOffFront=6
set _vTrimOffRear=6
set _ffmpegPath=C:\ffmpeg-20170308-3016e91-win64-static\bin


@REM CREATE EDITED DIRECTORY IF IT DOESN'T EXIST
@REM  - Used to copy edited files using existing file names if user chooses to do so
@REM
if not exist .\EDITED mkdir .\EDITED

@REM DETECT PROBLEMS
@REM
dir /b | findstr "'"
if %ERRORLEVEL% EQU 0 ( 
cls
echo !!! ERROR - FOUND APOSTROPHE !!!
echo.
echo     - Please remove characters from filename^(s^).
echo.
dir /b | findstr "'"
pause
exit
)


@REM FOR LOOP TO EDIT FILES AND DROP IN TO .\EDITED FOLDER
@REM
for /f "delims=" %%g in ('dir ^/b *.^%_vFileType%') do call :proc_ProcessFiles "%%g"


EXIT


@rem    THIS IS THE END OF THE SCRIPT!  ANYTHING BELOW THIS IS A PROCEDURE USED IN THE SCRIPT ABOVE
@rem    THIS IS THE END OF THE SCRIPT!  ANYTHING BELOW THIS IS A PROCEDURE USED IN THE SCRIPT ABOVE
@rem    THIS IS THE END OF THE SCRIPT!  ANYTHING BELOW THIS IS A PROCEDURE USED IN THE SCRIPT ABOVE
@rem   *******************************************************************************************************
@rem   *******************************************************************************************************
@rem   *******************************************************************************************************
@rem    THIS IS THE END OF THE SCRIPT!  ANYTHING BELOW THIS IS A PROCEDURE USED IN THE SCRIPT ABOVE
@rem    THIS IS THE END OF THE SCRIPT!  ANYTHING BELOW THIS IS A PROCEDURE USED IN THE SCRIPT ABOVE
@rem    THIS IS THE END OF THE SCRIPT!  ANYTHING BELOW THIS IS A PROCEDURE USED IN THE SCRIPT ABOVE



:proc_ProcessFiles
set _vFilenameTemp=%1

@REM FOR LOOP TO DETERMINE DURATION OF RESPECTIVE FILE AND THEN PROCESS SAID FILE
@REM   Note: Output of FFPROBE gives decimal number for length of video, however this can't be used in CMD files--so, only the integer is saved.
@REM         - If 1525.12524 is returned, then only 1525 is assigned to the variable.
@REM
for /f "delims=. tokens=1" %%h in ('%_ffmpegPath%\ffprobe.exe -v 0 -show_entries format^=duration -of compact^=p^=0^:nk^=1 %_vFilenameTemp%') do set _vFileLengthTemp=%%h


@REM SET THE AMOUNT TO TRIM OFF OF THE END OF THE FILE. DETERMINED BY USING VARIABLES SPECIFIED AT BEGINNING OF FILE. 
@REM
:: echo %_vFilenameTemp:~1,-1%
:: echo %_vFileLengthTemp%
set /a _vFileLengthTemp="%_vFileLengthTemp%-%_vTrimOffRear%-%_vTrimOffFront%"
:: echo %_vFileLengthTemp%


@REM DO CONVERSION OF FILE USING VARIABLES CREATED ABOVE
@REM
%_ffmpegPath%\ffmpeg.exe -ss %_vTrimOffFront% -t %_vFileLengthTemp% -i %_vFilenameTemp% -vcodec copy -acodec copy ".\EDITED\EDITED-%_vFilenameTemp:~1,-1%"

GOTO:EOF

图片——运行脚本之前。

图片——运行脚本后。

答案4

它的简单脚本(“strip-video.sh”):

#!/usr/bin/env bash

duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$1")
newDuration=$(python3 -c "print($duration - ($3 + $4))")

ffmpeg -ss $3 -t $newDuration -i "$1" -c copy "$2"

使用示例(删除开头10秒和结尾15秒):

strip-video.sh "in.mp4" "out.mp4" 10 15

相关内容