从命令行准确剪切视频文件


22

我在查找可以获取视频文件(最好是avi,mkv和mp4)的cli应用程序时遇到麻烦,并且可以精确地切出很短的剪辑(2-6秒)。我尝试了ffmpegmencoderavidemuxmp4box,但它们都在关键帧上剪切,这会创建6个以上的第二个剪辑。有没有一种工具可以对输入文件进行重新编码并削减准确的时间,或者不正确地剪切,重新编码然后进行准确的削减?


您可能需要重新编码才能剪切正确。您可能可以通过首先剪切周围的关键帧并仅重新编码片段来加快处理速度。
Nifle 2012年

4
您到底尝试了哪个FFmpeg命令?我相信,如果您之前解码视频(即,将-ss参数放置在之后 -i),它应该会更加准确。
slhck 2012年

1
FFmpeg技巧成功了!我没有意识到订单如此重要。其他任何工具都一样吗?
curmil 2012年

Answers:


23

用剪切视频 ffmpeg

可以使用FFmpeg准确剪切视频。从2.5版开始,这非常容易。例如,从0分钟,3秒和123毫秒开始,这将减少10秒。

ffmpeg -ss 00:00:03.123 -i input.mp4 -t 10 -c:v libx264 -c:a copy out.mp4

位置和时间可以是秒,也可以是hh:mm:ss[.xxx]形式。

请注意,在这些示例中,将使用x264编码器对视频进行重新编码。音频被复制。

您也可以使用-to而不是-t指定终点而不是持续时间。但是,在这种情况下,-to等效于-t,因为ffmpeg 通过将放在的-ss前面-i,将首先搜索到该点,然后开始输出。

另请参阅寻求 Wiki条目。


精确切割旧ffmpeg版本

如果您使用的是ffmpeg的旧版本,则为了进行精确查找,您需要放置-ssafter -i,这会使编码过程稍慢一些,因为必须首先对整个视频进行解码:

ffmpeg -i input.mp4 -ss 00:00:03.123 -t 10 -c:v libx264 -c:a copy out.mp4

在这里,-to-t不同的表现。-t 10将创建一个十秒钟长的剪辑,而-to 10将创建一个七秒钟长的剪辑。


-c:v libx264 -c:a libfaac我认为我们可以使用-acodec copy -vcodec copyffmpeg来检测和使用与原始文件相同的编解码器,而不是我想。谁能确认?
Baodad 2015年

2
@Baodad可以,但是不会准确切出。复制视频/音频比特流时,ffmpeg需要从关键帧开始,该关键帧可能只是每秒放置一次,甚至间隔更远。
slhck

如何克服“未知编码器'libfaac'”错误?
2015年

@Doug例如,选择其他编码器-c:a aac -strict experimental。那是最简单的解决方案。
slhck

1

到目前为止,我发现的唯一可以精确切割帧(或精确到帧)的Linux命令行工具是meltsudo apt-get install melt)。

假设您有一个inputvid.mp4-首先使用说说检查其编码设置ffmpeg(在这里,我只是说我想再次将其编码为-f mp4,但是作为文件,/dev/null因此输出被丢弃;我重定向了stderr以便可以grep通过它-注意中间,该命令会提示,并且您应该y使用ENTER进行回答,因此该过程将继续进行并转储有用的信息;这是在Ubuntu 14上的ffmpeg 3.3.3):

ffmpeg -i inputvid.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 640x360 [SAR 1:1 DAR 16:9], 389 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 95 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p(progressive), 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
      encoder         : Lavc57.89.100 libx264
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 128 kb/s (default)
      encoder         : Lavc57.89.100 aac

好的,这样我们就可以看到该视频的ffmpeg选择libx264aac编码器;然后我们可以输入melt

melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac vcodec=libx264

....,melt并将第7235和7349帧之间的片段剪切为一个新文件cut.mp4。然后要检查cut.mp4循环是否正确,请melt再次使用它播放两次-并将其播放到SDL窗口中:

melt cut.mp4 cut.mp4 -consumer sdl

...这是ffmpeg该文件的内容:

ffmpeg -i cut.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'    encoder         : Lavf54.20.4
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 526 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 182 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
      encoder         : Lavc57.89.100 libx264
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 48000 Hz, stereo, fltp, 128 kb/s (default)
      encoder         : Lavc57.89.100 aac

的视频编码设置cut.mp4似乎与以下相同,inputvid.mp4除了视频比特率从389 kb / s更改为526 kb / s,音频编码设置几乎相同,不同之处在于采样率从44100 Hz更改为48000 Hz。尽管可以通过以下方式进行调节:

melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac ar=44100 ab=95k vcodec=libx264 vb=389k

...但是,即使这样,对我来说最终的视频比特率最终还是337 kb / s。仍然,当循环播放时,cuts循环很好(并且包括音频),所以我想这确实是帧准确的...


1
melt重新编码视频,并使用下面的FFmpeg库。如果允许重新编码,则ffmpeg可以产生相同的输出。
Gyan

谢谢@Gyan-不知道这一点(尤其是melt使用FFmpeg库的情况),很高兴知道!
sdaau

与ffmpeg相比,melt看起来更易于使用,我们需要的是一种指定时间的方法,特别是以hr,min,sec形式或hr,min,sec,ms形式的时间,它们可以将它们转换为正确的帧。
barlop

0

就像鲍达德在评论中说的那样(我发帖是因为要快速阅读并不容易),更好的方法是通过ffmpeg自动检测音频/视频编码器,因此:

ffmpeg -ss 00:05:17.18 -i in.mp4 -t 00:06:29.10 -acodec copy -vcodec copy out.mp4 
  • 开始@ 00:05:17.18
  • 输入= in.mp4
  • 停止@ 00:06:29.10
  • 输出= out.mp4

2
这不会重新编码,也不提供帧精度。
Andrea Lazzarotto
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.