Linux 使用 ffmpeg 根据开始和结束时间剪切视频

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18444194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:39:56  来源:igfitidea点击:

Cutting the videos based on start and end time using ffmpeg

linuxvideoffmpegvideo-editing

提问by Kalai

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:03to 00: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?

通过使用上面的命令我想从剪切视频00:00:0300:00:08。但它不会在这些时间之间剪切视频,而是在前 11 秒内剪切视频。谁能帮我解决这个问题?

Edit 1:

编辑1:

I have tried to cut by using the following command which is suggested by mark4o

我尝试使用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

编码器“aac”是实验性的,但未启用实验性编解码器

so i added the -strict -2into the command i.e.,

所以我-strict -2在命令中添加了

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -strict -2 cut.mp4

Now it is working fine.

现在它工作正常。

采纳答案by mark4o

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.

您可能在 3 秒标记处没有关键帧。由于非关键帧对与其他帧的差异进行编码,因此它们需要从前一个关键帧开始的所有数据。

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.

使用 mp4 容器,可以在非关键帧处进行剪切,而无需使用编辑列表重新编码。换句话说,如果 3s 之前最近的关键帧是 0s,那么它会从 0s 开始复制视频并使用编辑列表告诉播放器开始播放 3 秒。

If you are using the latest ffmpegfrom 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.

如果您使用来自 git master的最新 ffmpeg,它将在使用您提供的命令调用时使用编辑列表执行此操作。如果这对您不起作用,那么您可能使用的是旧版本的 ffmpeg,或者您的播放器不支持编辑列表。有些播放器会忽略编辑列表,始终从头到尾播放文件中的所有媒体。

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:

如果您想从非关键帧开始精确剪切并希望它从不支持编辑列表的播放器上的所需点开始播放,或者想要确保剪切部分实际上不在输出文件中(例如如果它包含机密信息),那么您可以通过重新编码来做到这一点,以便在所需的开始时间精确地有一个关键帧。如果您未指定,则重新编码是默认设置copy。例如:

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 Guidefor video and AAC Encoding Guidefor audio.

重新编码时,您可能还希望包含其他与质量相关的选项或特定的 AAC 编码器。有关详细信息,请参阅 ffmpeg 的x264视频编码指南和音频的AAC 编码指南

Also, the -toption 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 -twith -toin the above command to end at the specified time.

此外,该-t选项指定持续时间,而不是结束时间。上面的命令将从 3s 开始编码 8s 的视频。要从 3s 开始到 8s 结束,请使用-t 5. 如果您使用的是当前版本的 ffmpeg,您还可以替换上面命令中的-twith-to以在指定时间结束。

回答by JFMD

    ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4

Drop everything except from second 3 to second 8.

除了从秒 3 到秒 8 之外的所有内容。

回答by Vlad Hudnitsky

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -c copy cut.mp4 

Use -c copyfor make in instantly. In that case ffmpeg will not re-encode video, just will cut to according size.

使用-c copy立即制作。在这种情况下,ffmpeg 不会重新编码视频,只会切割到相应的大小。

回答by George Chalhoub

Try using this. It is the fastest and best ffmpeg-way I have figure it out:

尝试使用这个。这是我发现的最快和最好的 ffmpeg 方式:

 ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4

This command trims your video in seconds!

此命令可在几秒钟内修剪您的视频!

I have explained it on my blog here:

我已经在我的博客上解释

-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)

-i:指定输入文件。在这种情况下,它是 (input.mp4)。
-ss:与 -i 一起使用,在输入文件 (input.mp4) 中寻找位置。
00:01:00:这是您修剪后的视频开始的时间。
-to:指定从开始 (00:01:40) 到结束 (00:02:12) 的持续时间。
00:02:00:这是您修剪后的视频结束的时间。
-c copy:这是通过流复制进行修剪的选项。(注意:非常快)

The timing format is: hh:mm:ss

计时格式为: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.

请注意,当前高度赞成的答案已过时,修剪速度会非常慢。有关更多信息,请查看这篇 ffmpeg 官方文章

回答by R Y

To cut based on start and end time from the source video and avoid having to do math, specify the end time as the input option and the start time as the output option.

要根据源视频的开始和结束时间进行剪切并避免进行数学运算,请将结束时间指定为输入选项,将开始时间指定为输出选项。

ffmpeg -t 1:00 -i input.mpg -ss 45 output.mpg

This will produce a 15 second cut from 0:45 to 1:00.

这将产生从 0:45 到 1:00 的 15 秒剪辑。

This is because when -ssis given as an output option, the discarded time is still included in the total time read from the input, which -tuses to know when to stop. Whereas if -ssis given as an inputoption, the start time is seeked and not counted, which is where the confusion comes from.

这是因为当-ss作为输出选项给出时,丢弃的时间仍然包含在从输入读取的总时间中,-t用于知道何时停止。而 if-ss作为输入选项给出,开始时间被搜索而不是计算,这就是混淆的来源。

It's slower than seeking since the omitted segment is still processed before being discarded, but this is the only way to do it as far as I know. If you're clipping from deep within a large file, it's more prudent to just do the math and use -ssfor the input.

它比查找慢,因为省略的段在被丢弃之前仍然被处理,但据我所知,这是唯一的方法。如果您从大文件的深处进行剪辑,则只进行数学运算并-ss用于输入更为谨慎。

回答by alper

Here's what I use:

这是我使用的:

ffmpeg -i input.mkv -ss 00:01:00 -to 00:02:00 -c:v copy -c:a copy output.mp4


Generated mp4files could also be used in iMovie.

生成的mp4文件也可以在iMovie.

Reference: https://www.arj.no/2018/05/18/trimvideo

参考:https: //www.arj.no/2018/05/18/trimvideo



If you want to concatenate multiple cut scenes you can use following script:

如果要连接多个过场动画,可以使用以下脚本:

#!/usr/bin/env python3

import subprocess

name = "batman.mp4"

times = []
times.append(["01:06:00", "01:07:00"])
times.append(["01:08:00", "01:09:00"])

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", "final.mp4"]
output = subprocess.check_output(cmd).decode("utf-8").strip()

回答by rolodex

Even though I'm 6 years late, but I think all the answers above didn't properly address the question @kalaiis asking. The bash script below will process a text file in the following format:

尽管我迟到了 6 年,但我认为上面的所有答案都没有正确解决@kalai提出的问题。下面的 bash 脚本将处理以下格式的文本文件:

URL | start_time | end_time | filename

for example

例如

https://www.youtube.com/watch?v=iUDURCrvrMI|00:02:02|00:03:41|1

and loop through the file, downloads the file that youtube-dlsupports, calculating duration between start_timeand end_timeand passing it to ffmpeg, since -tis actually the duration, not the real end_time

并循环遍历文件,下载youtube-dl支持的文件,计算start_time和之间的持续时间end_time并将其传递给ffmpeg,因为-t实际上是持续时间,而不是真实的end_time

Hit me up if you have any question.

如果您有任何问题,请联系我。

    for i in $(<video.txt);
    do
        URL=`echo $i | cut -d "|" -f 1`;
        START=`echo $i | cut -d "|" -f 2`;
        END=`echo $i | cut -d "|" -f 3`;
        FILE=`echo $i | cut -d "|" -f 4`;

        SEC1=`echo $START | sed 's/^/((/; s/:/)*60+/g' | bc`
        SEC2=`echo $END | sed 's/^/((/; s/:/)*60+/g' | bc`

        DIFFSEC=`expr ${SEC2} - ${SEC1}`

        ffmpeg $(youtube-dl -g $URL | sed "s/.*/-ss $START -i &/") -t $DIFFSEC -c copy $FILE".mkv";
        ffmpeg -i $FILE".mkv" -f mp3 -ab 192000 -vn $FILE".mp3";
        rm $FILE".mkv";
    done;

回答by dynamichael

Use -to instead of -t: -to specifies the end time, -t specifies the duration

使用-to代替-t:-to指定结束时间,-t指定持续时间