我的要求是尽可能快地使用手机上的 ffmpeg 精确地(上下移动几帧)动态剪切 mp4(h264 + aac)https 视频流 - 这意味着如果有必要,我会牺牲较差的压缩率(更大的输出文件)来换取更快的剪切速度。目前正在使用以下命令剪切视频:
ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 00:00:10.000 -c:a copy -c:v copy out.mp4
这种方法(比特流复制)非常快(在良好的网络上,10 秒的视频剪辑只需不到一秒的时间),但不能准确地剪辑视频。视频是在关键帧上剪辑的,不够精确。
因此,我的想法是在播放视频之前先搜索视频,以补偿这种不精确(与关键帧的距离):
delta = start_time - first_key_frame_timestamp_before_start_time
为了计算增量,我需要一种非常快速的方法来获取开始时间之前第一个关键帧的时间戳。我见过邮政这解释了如何在 start_time 之前获取第一个关键帧的时间戳,但这种方法不适用于较长(2 小时以上)的视频,因为此操作需要很长时间才能到达视频的中间部分。我需要这样的东西:
ffmpeg -ss 01:30:06.000 -i https://domain/in.mp4 -t 2 -show_frames > frame_meta.txt
我还尝试通过使用以下命令重新编码视频(2 小时长的视频,视频中间剪切 10 秒长的视频)进行精确剪切:
ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 10 out.mp4
但在移动设备上,它需要很长时间(约 16 秒)才能完成,而比特流复制命令则不到一秒。谢谢任何有用的提示或解决方案。
编辑1:
我设法使用 ExoPlayer(Android 多媒体播放器)内部类计算了 delta 并获取了 start_time 之前第一个 keyFrame 的时间戳,这种方法非常快,500ms(非常短的视频)到 1500ms(非常长的视频)。本质上,这种方法基于解析远程 mp4 流的 meta_headers(moov atom),以在剪切 start_time 之前找到 keyFrame 的适当时间戳。现在,当视频被剪切时,出现了新的问题:
ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 00:00:10.000 -c:a copy -c:v copy out.mp4
编辑列表原子被添加到元标头中,如从这和这帖子告诉播放器开始播放时使用增量时间偏移来补偿不精确的视频剪切,这是通过 ffmpeg bitStream copy 命令完成的。但我在 Android 上使用的播放器不支持编辑列表播放,因为它们只是从视频开头开始正常播放,或者在播放音频时在某个帧上冻结片刻,然后继续正常播放。
当我尝试寻找先前计算的增量,然后开始播放剪切的视频时,我没有定位在正确的帧上(例如,计算的增量=1 381ms,但实际/工作增量=444ms),并且我补偿不精确剪切的计划不起作用 :(。如果你问自己我是否正确计算了增量,我已经用等离子观察器(mp4 容器原子解析器)并通过使用 Avidemux 逐步浏览帧并查看 time_stamp/frame_type 值对来手动...