Cutting the videos based on start and end time using ffmpeg
Solution 1
You probably do not have a keyframe at the 3 second mark. Because non-keyframes encode differences from other frames, they require all of the data starting with the previous keyframe.
With the mp4 container it is possible to cut at a non-keyframe without re-encoding using an edit list. In other words, if the closest keyframe before 3s is at 0s then it will copy the video starting at 0s and use an edit list to tell the player to start playing 3 seconds in.
If you are using the latest ffmpeg from git master it will do this using an edit list when invoked using the command that you provided. If this is not working for you then you are probably either using an older version of ffmpeg, or your player does not support edit lists. Some players will ignore the edit list and always play all of the media in the file from beginning to end.
If you want to cut precisely starting at a non-keyframe and want it to play starting at the desired point on a player that does not support edit lists, or want to ensure that the cut portion is not actually in the output file (for example if it contains confidential information), then you can do that by re-encoding so that there will be a keyframe precisely at the desired start time. Re-encoding is the default if you do not specify copy
. For example:
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4
When re-encoding you may also wish to include additional quality-related options or a particular AAC encoder. For details, see ffmpeg's x264 Encoding Guide for video and AAC Encoding Guide for audio.
Also, the -t
option specifies a duration, not an end time. The above command will encode 8s of video starting at 3s. To start at 3s and end at 8s use -t 5
. If you are using a current version of ffmpeg you can also replace -t
with -to
in the above command to end at the specified time.
Solution 2
Try using this. It is the fastest and best ffmpeg-way I have figure it out:
ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -c copy output.mp4
This command trims your video in seconds!
Explanation of the command:
-i: This specifies the input file. In that case, it is (input.mp4).
-ss: Used with -i, this seeks in the input file (input.mp4) to position.
00:01:00: This is the time your trimmed video will start with.
-to: This specifies duration from start (00:01:40) to end (00:02:12).
00:02:00: This is the time your trimmed video will end with.
-c copy: This is an option to trim via stream copy. (NB: Very fast)
The timing format is: hh:mm:ss
Please note that the current highly upvoted answer is outdated and the trim would be extremely slow. For more information, look at this official ffmpeg article.
Solution 3
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -c copy cut.mp4
Use -c copy for make in instantly. In that case ffmpeg will not re-encode video, just will cut to according size.
Solution 4
Here's what I use and will only take a few seconds to run:
ffmpeg -i input.mp4 -ss 01:19:27 -to 02:18:51 -c:v copy -c:a copy output.mp4
Reference: Trim video files using FFmpeg by Alexander Refsum Jensenius.
Generated mp4
files could also be used in iMovie
. More info related to get the full duration using get_duration(input_video) model.
If you want to concatenate multiple cut scenes you can use following Python script:
#!/usr/bin/env python3
import subprocess
def get_duration(input_video):
cmd = ["ffprobe", "-i", input_video, "-show_entries", "format=duration",
"-v", "quiet", "-sexagesimal", "-of", "csv=p=0"]
return subprocess.check_output(cmd).decode("utf-8").strip()
def main():
name = "input.mkv"
times = []
times.append(["00:00:00", "00:00:10"])
times.append(["00:06:00", "00:07:00"])
# times = [["00:00:00", get_duration(name)]]
if len(times) == 1:
time = times[0]
cmd = ["ffmpeg", "-i", name, "-ss", time[0], "-to", time[1], "-c:v", "copy", "-c:a", "copy", "output.mp4"]
subprocess.check_output(cmd)
else:
open('concatenate.txt', 'w').close()
for idx, time in enumerate(times):
output_filename = f"output{idx}.mp4"
cmd = ["ffmpeg", "-i", name, "-ss", time[0], "-to", time[1], "-c:v", "copy", "-c:a", "copy", output_filename]
subprocess.check_output(cmd)
with open("concatenate.txt", "a") as myfile:
myfile.write(f"file {output_filename}\n")
cmd = ["ffmpeg", "-f", "concat", "-i", "concatenate.txt", "-c", "copy", "output.mp4"]
output = subprocess.check_output(cmd).decode("utf-8").strip()
print(output)
if __name__ == "__main__":
main()
Example script will cut and merge scenes in between 00:00:00 - 00:00:10
and 00:06:00 - 00:07:00
.
If you want to cut the complete video (in case if you want to convert mkv
format into mp4
) just uncomment the following line:
# times = [["00:00:00", get_duration(name)]]
Solution 5
ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4
Drop everything except from second 3 to second 8.
Kalaiyarasan
Web developer having experience in Angular Ionic Html css Javascript and Jquery Laravel PHP Mysql Wordpress Redis Codeigniter MVC framework Mediawiki Wowza media server Amazon EC2 Amazon S3 Smarty Media temple server Customising Flex video applications using AS3 Kaltura video editor installation and usage CS Cart with good problem-solving skills.
Updated on January 15, 2022Comments
-
Kalaiyarasan over 2 years
I tried to cut the video using the start and end time of the video by using the following command
ffmpeg -ss 00:00:03 -t 00:00:08 -i movie.mp4 -acodec copy -vcodec copy -async 1 cut.mp4
By using the above command i want to cut the video from
00:00:03
to00:00:08
. But it is not cutting the video between those times instead of that it is cutting the video with first 11 seconds. can anyone help me how resolve this?Edit 1:
I have tried to cut by using the following command which is suggested by mark4o
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4
But it was shown the following error.
the encoder 'aac' is experimental but experimental codecs are not enabled
so i added the
-strict -2
into the command i.e.,ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -strict -2 cut.mp4
Now it is working fine.
-
Jikku Jose over 9 yearsIs there a shortcut to specify till the end of the video?
-
mark4o over 9 years@JikkuJose: Omit the
-t
/-to
and its argument to continue to the end. -
Denilson Sá Maia almost 9 yearsNote: it is faster to supply
-ss
BEFORE the input file (before-i
), because that way ffmpeg will skip directly to the location. However, that will also set the time "zero" to that location, meaning that-to
will point to the wrong time. Source: trac.ffmpeg.org/wiki/Seeking -
user2002522 almost 9 yearsI get audio and video sync issue after using this
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4
, though the original file has no such issue. -
mark4o almost 9 years@user2002522: Try without the
-async 1
. -
jiggunjer over 8 yearsI get the first 8 seconds with this, with the first 3 seconds frozen on the first frame. Fixed by chaining
setpts=PTS-STARTPTS
filter after the trim filter. -
Ivan over 8 yearsThis says "The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it." Adding -strict -2 does not help. The result is a zero length file.
-
Jan Gondol over 8 years@Ivan, did you try adding
-strict -2
beforecut.mp4
(as opposed to the end of the command line)? -
Kevin about 7 yearsthis answer, stackoverflow.com/a/14013439/1170023 is what you want for finding the keyframe times with -c copy to avoid audio sync
-
dorien almost 7 yearsof -c copy works great, but only if I remove -async 1
-
pelson almost 7 yearsYou may still suffer from a lack of keyframes with this though. I took your approach to cutting, then re-encoded as per the accepted answer to make sure I minimised the amount of time I needed to spend re-encoding.
-
Assil Ksiksi over 6 yearsThis ends up failing on write due to invalid headers in the case of different input and output containers e.g. .mkv input and .mp4 output.
-
Vlad Hudnitsky over 6 yearsAlright, to convert .mkv to .mp4 you have to use another command:
ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4
and vise versa -
Raphael over 6 yearsAs @pelson says, this will cut off key frames and leave the first few seconds blank (if the cutting time is between key frames). Interestingly, changing the parameter order solves the problem:
ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4
. Now, however, skipping is broken and the end time is not correct (in my case). -
vxh.viet over 6 yearsAccording to FFmpeg, input seeking is now both fast and accurate, is there any specific reason you use output seeking instead of input seeking?
-
Ryan over 6 yearsNice! What worked for me was
ffmpeg -i origin.mp4 -ss 02:51:14 -c copy destination.mp4
(I guess-to
is optional and unnecessary if you want the end point to be the absolute end of the video.) -
duplex143 almost 6 yearsFor me also, the output was corrupted and with no sound. IINA player is crashing whenever I'm trying to open the video. I'm on macOS 10.13.5 and ffmpeg is 3.4
-
Yamaneko over 5 yearsYou should use this answer if you don't need to trim at an exact milisecond, thus it will select the closest keyframe available. That's why it's so fast, it selects the closest keyframes and takes the snippet out without the need of reencoding. However, if you do need a precise time, taking the nearest keyframe isn't enough, because it certainly won't match exactly. The only solution available is to reencode the video, and that's why it's so slow. That's the only solution, though, if you do need this. That's why the other answer should be the accepted one, as that's what was OP's issue about.
-
theferrit32 over 5 yearsYou probably want
-ss
and-to
before-i
, example:ffmpeg -ss aa:bb:cc -to xx:yy:zz -i input.mp4 -c copy output.mp4
. Otherwise the-to
value ends up being a duration instead of the end time from the original video. Omitting the-c copy
will make it slower and more accurate by re-encoding, but still faster than if the-ss
and-to
are specified after-i
, since that case means to trim after having to process the whole input file. -
Shayan about 5 yearsRemember to put both
-ss
and-t
before-i
to avoid black screen for few seconds at the beginning and don't use-to
because it will produce a file with incorrect duration. -
techkuz about 5 years@theferrit32 it gives
Option to (record or transcode stop time) cannot be applied to input url file.mp4 -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to.
-
techkuz about 5 yearsslow, but the only thing worked for me (without loosing frames from other answers)
-
Trect over 4 yearsTHis is super slow
-
Bugs Happen over 4 yearsNote that if you specify
-ss
before-i
only, the timestamps will be reset to zero, so-t
and-to
have not the same effect. If you want to keep the original timestamps, add the-copyts
option. Reference -
Harsha over 4 yearsWhat are the advantages of re-encoding? Is it of any use if we just want smaller video in the same format?
-
vdegenne over 4 years
-to
is not the duration,-t
is ! -
lacostenycoder over 4 yearsThis outputs only an mp3 audio file and NOT a video.
-
ceremcem about 4 years
-
nstenz about 4 yearsCouldn't this just use "-c" with "copy" instead of splitting out -c:v and -c:a?
-
Yaniv Levi about 4 yearsI also experienced sync issues. i tried the solution provided by George Chalhoub (below) and the sync issue was fixed
-
Piotr Majek almost 4 yearsExcelent. The only solution to not calculate duration but provide start and end to the ffmpeg
-
Pablo Díaz almost 4 yearsI don't know why but I'm getting error with this code
-
Hoppeduppeanut almost 4 yearsGoing by the GitHub account profile, it looks like this might be a tool that you've created yourself. If this is the case, you must disclose this in your answer, otherwise this can be considered spam.
-
Muhammed Yalçın Kuru almost 4 yearsi am getting quality issue. Is there anyone getting same issue ?
-
mark4o almost 4 years@MuhammedYalçınKuru: To control the quality see trac.ffmpeg.org/wiki/Encode/H.264
-
Muhammed Yalçın Kuru almost 4 years@mark4o i have tried with my lack of info. Didn't find fit one. while cutting passed this one ` -c:v libx264 -preset ultrafast -crf 0 `
-
y o almost 4 yearsthis is slow. the input file isn't being seeked, it's being processed and discarded. -ss as an output option = slow. see my updated answer.
-
Pablo Díaz almost 4 yearsI'm getting the video cutted but for first seconds the frames just freeze
-
alper almost 4 years@PabloDíaz The video you are using might be faulty. Can you give it a try with a different video uncommenting
# times = [["00:00:00", get_duration(name)]]
and see if the generatedoutput.mp4
file is fine -
Franva over 3 yearsI can confirm that with the -c copy the speed is more than 300 times of normal playing speed whereas without the -c copy the speed is only 4 times of the normal playing speed. As typing the comment, the "with c " command has finished, and the "without c " is still running....
-
JasonXA over 3 yearsThis one is outdated, unless there are differences between the win and linux builds, or the answer was made with an old version of ffmpeg, but placing -to after the input file, for my recent win build, it creates an unwanted output, as in it resets timestamps with -ss to 0 and -to won't actually end with the desired timestamp from the input file. The -ss and -to options need to be placed before the input... for new versions of ffmpeg. Otherwise, -ss -i input should be followed by -t, i.e. total duration of the clip, to achieve the right duration for the cut.
-
Ale over 3 yearsIs there any way to re-encode only the part up to next keyframe, then copy everything else over?
-
Sudhir Singh Khanger over 3 yearsIn layman's terms what does now deprecated
async 1
does? -
Sudhir Singh Khanger over 3 yearsI have same question as @Harsha. What does -c copy in layman's terms?
-
Harsha over 3 years@SudhirSinghKhanger Just found a free GUI interface to Ffmpeg, check out the program LosslessCut
-
kiltek about 3 years-t is not picked up and the command ends up cutting from -ss to and of file
-
EmBeCoRau almost 3 yearsHi guys, I've implement it on my Android app, but it seem have a bit inaccuracy. I used this command
ffmpeg -y -i movie.mp4 -ss 00:00:00.400 -to 00:00:47 -preset ultrafast -c:v copy -c:a copy cut.mp4
the result always have the duration 46s, that mean it always cut 1s instead of 400ms as the params above. It can work well on my iOS app. Someone can help me in this case? -
mark4o almost 3 years@EmBeCoRau If you want to re-encode the video in order to create a new keyframe at a precise time, remove the -c:v copy option.
-
Sayyor Y almost 3 yearsI would advise to put the from time and to time together, otherwise they might not cut properly. So it should be: ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -c copy output.mp4
-
alper almost 3 years@yo It shouldn't be slow. What do you mean by
input file isn't being seeked? Instead of input.mp4
provide the path of the movie you want to convert. I have tried to convert 6.7 GB BlueRay movie by the script I provided, which only took 3.56 seconds. -
rolodex almost 3 yearsI suppose you can update the script to output video format instead of audio. If I remember correctly, about 3 years ago I did it just for audio.
-
greenoldman over 2 yearsIMHO you should fix your answer and put the start/to options on one side of the input -- either left or right. Splitting them gives very counter-intuitive behavior because as you put it "-to" behaves like "-t" (because it counts output time). I just learned about it from superuser.com/a/670574/43045
-
Nitin Ashutosh over 2 yearsif we use -t it will clip the video till the end of the video. Try -to instead of -t
-
Trung0246 over 2 yearsAdding
-c copy
apparently make the first few frames corrupted, so I removed that and it fixed the issue -
Sunwoo Yang about 2 yearsThis is so fast! I'm never gonna use the regular windows photo editor
-
Ax_ about 2 yearsin batches
for f in *.mp4; do ffmpeg -ss 00:00:00 -to 00:00:30 -i "$f" -c copy "$f".mp4 ; done
-
Ax_ about 2 yearsand optimize compression H265
for f in *.mp4 ; do ffmpeg -ss 00:00:00 -to 00:00:30 -i "$f" -c:v libx265 -preset fast -crf 28 -tag:v hvc1 -c:a eac3 -b:a 224k "$f".mp4 ; done