What I've found to be trickier is dividing a video into multiple clips, where one clip can start at the end of another, but not necessarily.
What I've found to be trickier is dividing a video into multiple clips, where one clip can start at the end of another, but not necessarily.
I just think there are other closely related use cases where a separate program can add more value, especially in the terminal. I wouldn't suggest most people should use ffmpeg instead of a gui, those are too dissimilar. Another example is cutting out a part of a video, with ffmpeg you need to make two temporary videos and then concatenate them, that process would greatly benefit from a better ux.
It can be done in a single command, no temp files needed.
# make a 6 second long video that alternates from green to red every second.
ffmpeg -f lavfi -i "color=red[a];color=green[b];[a][b]overlay='mod(floor(t)\,2)*w'" -t 6 master.mp4; # creates 150 frames @ 25fps.
# try make a 1 second clip starting at 0sec. it should be all green.
ffmpeg -ss 0 -i "master.mp4" -t 1 -c copy "clip1.mp4"; # exports 27 frames. you see some red.
ffmpeg -ss 0 -t 1 -i "master.mp4" -c copy "clip2.mp4"; # exports 27 frames. you see some red.
ffmpeg -ss 0 -to 1 -i "master.mp4" -c copy "clip3.mp4"; # exports 27 frames. you see some red.
# -t and -to stop after the limit, so subtract a frame. but that leaves 26...
# so perhaps offset the start time so that frame#0 is at 0.04 (ie, list starts at 1)?
ffmpeg -itsoffset 0.04 -ss 0 -i "master.mp4" -t 0.96 -c copy "clip4.mp4"; # exports 25 frames, all green, time = 1.00. success.
# try make another 1 second clip starting at 2sec. it should be all green.
ffmpeg -itsoffset 0.04 -ss 2 -i "master.mp4" -t 0.96 -c copy "clip5.mp4"; # exports 75 frames, time = 1.08, and you see red-green-red.
# maybe don't offset the start, and drop 2 at the end?
ffmpeg -ss 2 -i "master.mp4" -t 0.92 -c copy "clip6.mp4"; # exports 75 frames, time = 1.08, and you see green-red.
ffmpeg -ss 2 -t 0.92 -i "master.mp4" -c copy "clip7.mp4"; # exports 75 frames, time = 0.92, and you see green-red.
# try something different...
ffmpeg -ss 2 -i "master.mp4" -c copy -frames 25 "clip8.mp4"; # video is broken.
ffmpeg -ss 2 -i "master.mp4" -c copy -frames 25 -avoid_negative_ts make_zero "clip9.mp4"; # exports 25 frames, all green, time = 1.00. success?
# try export a red video the same way.
ffmpeg -ss 3 -i "master.mp4" -c copy -frames 25 -avoid_negative_ts make_zero "clip10.mp4"; # oh no, it's all green! func BuildFFmpegCommand(opts ExportOptions) string {
output := opts.Output
if output == "" {
output = generateOutputName(opts.Input)
}
duration := opts.OutPoint - opts.InPoint
args := []string{"ffmpeg", "-y",
"-ss", fmt.Sprintf("%.3f", opts.InPoint.Seconds()),
"-i", filepath.Base(opts.Input),
"-t", fmt.Sprintf("%.3f", duration.Seconds()),
}
I think the best way of getting frame accurate clips like that is putting the starting time after the input (or rather before the output), which decodes the video up to that time, and reencode it instead of copying. Both of these commands gives the expected output: ffmpeg -i master.mp4 -ss 0 -t 1 -c:v libx264 green.mp4
ffmpeg -i master.mp4 -ss 1 -t 1 -c:v libx264 red.mp4There are incantations that can dump for you metadata about the individual packets a given video stream is made up of, ordered by timecode. That way you can sanity check things.
This is terribly frustrating. The paths of least resistance either lead to improper cuts or wasteful re-encoding. Re-encoding just until the nearest keyframe I'm sure is also possible, but yeah, this does suck, and the tool above doesn't seem to make this any more accessible either according to the sibling comment.
I wonder if there is a solution which would just copy the pieces in between the starting and ending points while only re-encoding the first and last piece as required.
https://github.com/stax76/awesome-mpv?tab=readme-ov-file#vid...
Appreciate you mentioning the MPV route for making clips, I might actually go through and process all the game recordings I saved for clips over the years.