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

时间:2013-08-26 12:34:19

标签: linux video ffmpeg video-editing

我尝试使用以下命令

使用视频的开始和结束时间剪切视频
ffmpeg -ss 00:00:03 -t 00:00:08 -i movie.mp4 -acodec copy -vcodec copy -async 1 cut.mp4

通过使用上述命令,我想将视频从00:00:03剪切为00:00:08。但它并没有在这些时间之间切断视频,而是在前11秒内切断视频。任何人都可以帮我解决这个问题吗?

修改1:

我尝试使用mark4o

建议的以下命令进行剪切
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

但是显示出以下错误。

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

所以我将-strict -2添加到命令中,即

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

现在工作正常。

9 个答案:

答案 0 :(得分:454)

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

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

如果您使用git master中的latest ffmpeg,则在使用您提供的命令调用时,将使用编辑列表执行此操作。如果这不适合您,那么您可能要么使用较旧版本的ffmpeg,要么您的播放器不支持编辑列表。有些玩家会忽略编辑列表,并始终从头到尾播放文件中的所有媒体。

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

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

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

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

答案 1 :(得分:255)

尝试使用此功能。这是我发现的最快最好的方式:

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

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

我已在我的博客here上解释过它:

  

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

时间格式为: hh:mm:ss

请注意,目前高度响应的答案已过时,修剪速度极慢。有关更多信息,请查看此官方ffmpeg article

答案 2 :(得分:74)

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

立即使用 -c copy 进行制作。在这种情况下,ffmpeg不会重新编码视频,只会根据大小进行切换。

答案 3 :(得分:26)

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

删除除第二个3到第二个8之外的所有内容。

答案 4 :(得分:8)

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

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

这将导致从0:45到1:00的15秒切换。

这是因为当将-ss用作输出选项时,丢弃的时间仍包含在从输入读取的总时间中,-t用来知道何时停止。而如果将-ss作为 input 选项给出,则会寻找开始时间,而不计算,这是造成混淆的地方。

这比查找要慢,因为省略的段在丢弃之前仍要进行处理,但是据我所知,这是唯一的方法。如果您要从一个大文件中深切,则最好进行数学运算并使用-ss作为输入。

答案 5 :(得分:2)

这就是我刚刚使用的内容:

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


生成的mp4文件也可以在iMovie中使用。

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

答案 6 :(得分:0)

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

URL | start_time | end_time | filename

例如

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

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

如果有任何问题请打我。

    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;

答案 7 :(得分:0)

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

答案 8 :(得分:0)

请随意使用此工具https://github.com/rooty0/ffmpeg_video_cutter 差不多是ffmpeg的cli前端...您只需要创建一个想要剪切的Yaml ...类似这样的

cut_method: delete  # we're going to delete following video fragments from a video
timeframe:
  - from: start   # waiting for people to join the conference
    to: 4m
  - from: 10m11s  # awkward silence
    to: 15m50s
  - from: 30m5s   # Off-Topic Discussion
    to: end

然后运行工具以获取结果