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.avibut it only skips the first 7 seconds of the video, and displays the video flipped.
33 Answers
You have to find out the total duration of the video (either with parsing ffmpeg output or using other libraries such as MediaInfo, etc.), d and then subtract the time manually from that.
Say your video is 40 seconds long and you want to cut 7 seconds, you need to encode only 33 seconds, so do:
ffmpeg -i input.avi -t 33 -c copy output.avi 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 I know this is an old post, but it comes up high on the search results and I found these answers more complicated than I'd like. It took me a lot of searching plus trial & error to figure this out, so I figured I'd share my answer here. I added the first two for clarification. Basically all the other answers i've found refer to these scenarios at the expense of the third. Confusion averted.
3 Completely Different Scenarios:
1 - Want to keep only the last N seconds of a video.
2 - Want to delete the last N seconds of a video and keep the rest. (Manually enter duration)
3 - Want to delete the last N seconds of a video and keep the rest. (Auto-detect duration of file. Great for multiple/batch files too.)
1 -
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 -
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 -
You'll need to use both ffmpeg and ffprobe, but it can all be done in console, with very little code, and no writing to a file.
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 = $duration - seconds;Example:
$duration = $ ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4;
$duration = $duration - 7;
$ ffmpeg -ss 00:00:00 -to $duration -i input.mp4 -c copy output.mp4;Removes the last 7 seconds of the video.
Bonuses:
I won't go into batch syntax here, but here are a few useful tidbits I also ran into.
code to prevent reencoding:
-c copyCMD vs POWERSHELL:
cmd uses
$ ffmpeg
$ ffprobepowershell doesn't use this ($) and it doesn't default to the folder you call the console from.
To do this, you use
.\ffmpeg
.\ffprobeHow to keep your video cover art:
add the code
map 0Some movie files have spaces in the filename:
use "" to reference these files
Here is the single video file code I use:
(I mod this for batch use)
$duration = .\ffprobe -v error -show_entries format=duration -of csv=p=0 "My Input Video.mp4";
$duration = $duration - 15;
.\ffmpeg -ss 00:00:36 -to $duration -i "My Input Video.mp4" -map 0 -c copy "My Output Video.mp4";This automatically removes the first 36 seconds and last 15 seconds of the video, replaces the cover art for the output file, and does NOT reencode the file, all without me even knowing the video duration. Very fast and easy.
Thanks to all those who actively develop FFmpeg.