在关键帧之间剪切视频而不使用 ffpmeg 重新编码完整视频?

bgu*_*uiz 7 audio video ffmpeg

我想在任何特定时间戳的开头剪切视频,并且需要精确,因此最近的关键帧不够好。

此外,这些视频相当长——一个小时或更长时间——所以如果可能的话,我想避免完全重新编码,或者只重新编码总持续时间的一小部分。因此,想最大限度地利用-vcodec copy.

我怎样才能做到这一点ffmpeg

注意:请参阅方案以及我自己对以下可能解决方案的粗略想法。


设想:

  • 原始视频
    • 1:00:00 时长
    • 每 10 秒有一个关键帧
  • 想要的剪裁:
    • 从 0:01:35 到结束
  • 尝试#1:
    • 使用-ss 0:01:35 -i blah.mp4 -vcodec copy,结果是一个文件,其中:
    • 音频从 0:01:30 开始
    • 视频也从 0:01:30 开始
    • 这太早开始了音频和视频
  • using -i blah.mp4 -ss 0:01:35 -vcodec copy,结果是一个文件,其中:
    • 音频从 0:01:35 开始,
    • 但视频在前 5 秒是空白/黑色,
      • 直到 0:01:40,当视频开始时
    • 这会按时启动音频,但视频启动太晚了

粗略的想法

  • (1) 切 0:01:30 到 0:01:40
    • 重新编码它以获得新的关键帧,包括目标时间 0:01:35 的关键帧
    • 然后剪下这个以获得从 0:01:35 到 0:01:40 的 5 秒
  • (2) 从 0:01:40 切到最后
    • 无需重新编码,使用 -vcodec copy
  • (3)ffmpeg concat第一个短夹(第5秒)与第二个长夹

我知道/可以计算出 (2) 和 (3) 的命令,但不确定 (1) 需要哪些命令。

llo*_*gan 8

列出关键帧的时间戳:

ffprobe -v error -select_streams v:0 -skip_frame nokey -show_entries frame=pkt_pts_time -of csv=p=0 input.mp4
Run Code Online (Sandbox Code Playgroud)

它会输出如下内容:

0.000000
2.502000
3.795000
6.131000
10.344000
12.554000
16.266000
...
Run Code Online (Sandbox Code Playgroud)

假设您要删除时间戳 0 到 5,然后流式复制剩余部分。最接近的跟随关键帧是 6.131。

将 5 重新编码为 6.131。确保输入和输出匹配属性和格式。对于 MP4,默认设置应该完成大部分工作,假设为 H.264/AAC,但您可能必须手动匹配配置文件

ffmpeg -i input.mp4 -ss 5 -to 6.131 trimmed.mp4
Run Code Online (Sandbox Code Playgroud)

input.txtCONCAT分路

file 'trimmed.mp4'
file 'input.mp4'
inpoint 6.131
Run Code Online (Sandbox Code Playgroud)

连接:

ffmpeg -f concat -i input.mp4 -c copy output.mp4
Run Code Online (Sandbox Code Playgroud)

  • 我知道问题只是关于视频,我也想要音频,但我在遵循说明时遇到了麻烦,因为在第一个重新编码部分之后我总是得到损坏的音频。原因是我也重新编码了音频,将其格式更改为与原始格式不兼容的格式。在重新编码第一部分时添加“-c:a copy”解决了该问题。 (3认同)
  • 最终命令行中的“input.mp4”应该是“input.txt”吗? (2认同)