30

I captured a video from my camera, but I don't know exactly how long it is. I want to use FFmpeg to keep and cut only the last 7 seconds of the video. Is this possible?

I tried the command:

ffmpeg -t 00:00:07 -i input.avi -vcodec copy newfile.avi

But it only skips the first 7 seconds of the video, and displays the video flipped.

Giacomo1968
  • 58,727
NickName
  • 411

4 Answers4

27

Use the -sseof (seek relative to End of File) option.

Say you want to keep the last 7 seconds, you can use:

ffmpeg -sseof -7 -i input.mp4 -c copy output.mp4

See the documentation here.

Note: This answer was posted in 2014 when this option did not exist. It was only added in 2015 — answer updated since.

slhck
  • 235,242
17

Three different scenarios. I added the first two for clarification.

  1. Want to keep only the last N seconds of a video instead of [-ss #] use [-sseof -#]

    Example: -sseof -7

    $ ffmpeg -sseof -7 -i input.mp4 -c copy output.mp4
    

    Keeps the last 7 seconds of the video and discards the rest

  2. Want to delete the last N seconds of a video and keep the rest. (Manually enter duration).

    This option requires manual entry of end time (for automatic, see #3)

    Use -ss and -t (duration from start point) or -to (specific timestamp)

    You'll need to calculate the end time manually for this option.
    Examples:

    $ ffmpeg -ss 00:00:00 -to 01:32:00 -i input.mp4 -c copy output.mp4;
    

    Keeps the video from timestamp 00:00:00 to timestamp 01:32:00

    $ ffmpeg -ss 00:00:04 -t 01:00:00 -i input.mp4 -c copy output.mp4;
    

    Keeps the video from timestamp 00:00:04 to timestamp 01:00:04
    1 hour long video.

  3. Want to delete the last N seconds of a video and keep the rest. (Auto-detect duration of file)

    You'll need to use both ffmpeg and ffprobe, but it can all be done in terminal, with very little code.

    The only way to cut off seconds based on the end time is to get the end time. I do batch processing of videos with varied lengths, so manually looking up and inputting each duration was out of the question. I needed to automatically access the duration value and pass it to ffmpeg.

    The Magic Formula:

    duration=`ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4`
    duration=`bc $duration - seconds`
    

    Example:

    $ duration=`ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4`
    $ duration=`bc $duration - 7`
    $ ffmpeg -ss 00:00:00 -to $duration -i input.mp4 -c copy output.mp4
    

    Removes the last 7 seconds of the video.

Giacomo1968
  • 58,727
David2me
  • 171
6

Here is a bash script for convenience:

#!/bin/bash

Arguments

FILE_RAW=$1 TRIM_EOF_DURATION=${2:-1.0} # Default is 1.0 second trimmed from EOF

Prepare variables

BASE_PATH=$(dirname $(readlink -f $FILE_RAW)) FILENAME_EXT="$(basename "${FILE_RAW}")" FILENAME_ONLY="${FILENAME_EXT%.}" EXT_ONLY="${FILENAME_EXT#.}" # Or hardcode it like "mp4" FILENAME_ONLY_PATH="${BASE_PATH}/${FILENAME_ONLY}"

Trim EOF duration

INPUT_DURATION=$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "${FILENAME_ONLY_PATH}.${EXT_ONLY}") OUTPUT_DURATION=$(bc <<< "$INPUT_DURATION"-"$TRIM_EOF_DURATION") ffmpeg -i "${FILENAME_ONLY_PATH}.${EXT_ONLY}" -map 0 -c copy -t "$OUTPUT_DURATION" "${FILENAME_ONLY_PATH}Trim${TRIM_EOF_DURATION}.${EXT_ONLY}"

Note: Make script executable: chmod +x trim_video.sh

Usage (Output File: <PATH_TO_INPUT_VIDEO>_Trim_<TRIM_EOF_DURATION>.mp4)

. <PATH_TO_THIS_SCRIPT>/trim_video.sh <PATH_TO_INPUT_VIDEO> <OPTIONAL_TRIM_EOF_DURATION>

Example: Trim 7.0 seconds from EOF (Output: ~/Videos/input_video_Trim_7.0.mp4)

. ~/trim_video.sh ~/Videos/input_video.mp4 7.0
sagunms
  • 321
0

Here's a script for Windows' cmd.exe that doesn't use ffprobe (only uses ffmpeg):

@echo off  
setlocal

if "%~1"=="" (
echo Usage: %~n0 input_video_file seconds_to_remove
goto :eof
)

set "input=%~1"
set "x=%~2"
set "output=%~n1_trimmed%~x1"

REM Get duration from ffmpeg output
for /f "tokens=1,2 delims=, " %%a in ('ffmpeg -i "%input%" 2^>^&1 ^| findstr /i "Duration"') do (
set duration=%%b
)

echo Duration string: %duration%

REM Use PowerShell to get total duration in seconds
for /f "usebackq delims=" %%d in (powershell.exe -NoProfile -Command &quot;[TimeSpan]::Parse('%duration%').TotalSeconds&quot;) do set "DURATION=%%d"

echo Total duration: %DURATION% seconds

REM Calculate new duration
for /f "usebackq delims=" %%e in (powershell.exe -NoProfile -Command &quot;%DURATION% - %x%&quot;) do set "NEW_DURATION=%%e"

echo New duration: %NEW_DURATION% seconds

REM Run ffmpeg to trim the video
ffmpeg -i "%input%" -t %NEW_DURATION% -c copy "%output%"

echo The output file "%output%" has been created without the last %x% seconds.

Example of use:

script.bat input.mp4 7

will remove the last 7 seconds in input.mp4: it'll create a new file input_trimmed.mp4

If one uses this script on videos that have telemetry information (e.g., GoPro GPMF), replace ffmpeg -i "%input%" -t %NEW_DURATION% -c copy "%output%" with:

REM Run ffmpeg to trim the video  
ffmpeg -i "%input%" -t %NEW_DURATION% -map 0:v -map 0:a -map 0:3 -copy_unknown -tag:2 gpmd -c copy "%output%"  

(the extra attributes -map 0:v -map 0:a -map 0:3 -copy_unknown -tag:2 gpmd keeps the telemetry information)

Franck Dernoncourt
  • 24,246
  • 64
  • 231
  • 400