python - MoviePy 较小的剪辑拆分在连接文件、音频不匹配、编码时导致故障
问题描述
我的代码如下。断路器文件:
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
splits = [[1, 2], [5, 6], [7, 10]]
for i, split in enumerate(splits):
start, end = split
ffmpeg_extract_subclip("video.m4v", start, end, targetname="clips/{0}.mp4".format(i))
此断路器代码有效并成功地将剪辑分成适当的长度。打开它们时,出现以下错误:
- 在 VLC 中打开子剪辑时出现故障撕裂(示例)
- 与实际观看长度相比,视频长度不正确
- 例如,在拉斯维加斯,每个子剪辑的音频都比视频短
- 当试图将这些视频连接成一个更大的视频(下面的代码)时,当剪辑加入时,“过渡”会在播放新剪辑之前重复前一个视频的最后几分钟几秒钟
串联代码:
from moviepy.editor import *
clips = []
for i in range(1, 3):
clips.append(VideoFileClip("{0}.mp4".format(i)))
concat = concatenate_videoclips(clips)
concat.write_videofile("output.mp4")
这也有效,尽管在打开时我得到上面第 (4) 点中写的错误。
额外的信息:
- 我使用了同一视频的两个原始版本,一个是原始视频 (2.42gb),另一个是我通过 Handbrake 的编码运行的版本,以确保这不是问题。
- 我也对输出进行了编码,以防这是问题(再次手刹)并且问题保持不变。
- 昨天在运行两段代码时这不是问题,从那时起我所做的唯一操作是尝试重新安装 MoviePy (
pip uninstall moviepy
->pip install moviepy==1.0.1
,我目前正在使用版本1.0.3
- 如果我在默认情况下缺少某些东西安装Python,请告诉我) - 这个问题与语法错误无关,我已经解释了代码以使其更易于阅读
这是Vegas单独查看这些文件的截图(我没有剪切,这只是我将它们直接粘贴到Vegas):
更新:我已经尝试下载 exeFFMPEG
并直接调用它来进行拆分(不使用 Python 下载的版本 //moviepy 链接到 FFMPEG),但问题仍然存在。我从这个 Stack 帖子中得到了这个想法。
更新:我已经尝试了很多方法来排除原始文件被拆分为问题的可能性,但我开始相信这个问题在连接文件上被严重强调。将尝试寻找此功能的旧版本。
更新:对于我更改 MoviePy 的每个版本,都会有一些令人反感的变化。在2.0.0
中,子剪辑的结尾被冻结,而没有音频播放。在1.0.0
剪辑的开头出现故障。在1.0.1-2
中,剪辑的结尾在移动到新剪辑时出现故障。极度困惑。
更新:我只是无法确定从什么角度来解决这个问题。例如:我尝试了一个不同的视频,并且在第一次运行时它是半可行的(扔进维加斯,移动它以获得正确的时间,将它渲染为一个可以通过的视频)但是一旦我做出改变(比如尝试剪辑时添加一两秒钟)就好像一切都只是不同步并放弃了。一旦我恢复到之前的正常剪辑(这是可行的),剪辑就完全不可预测,并且完全不同步。我现在正在寻找的只是卸载和重新安装的东西,或者替代方案。
解决方案
故障是因为您可能没有指定时间戳的关键帧。因为非关键帧编码与最近关键帧的差异,所以它们只显示与前一个关键帧的差异,这就是为什么它们非常节省内存,但不一致。类似的理论也适用于音频,并且取决于编解码器/格式 ofc!
在核心moviePY也使用ffmpeg工具,这里是API参考的官方页面,以及底层细节, https: //zulko.github.io/moviepy/_modules/moviepy/video/io/ffmpeg_tools.html
使用 mp4 容器,可以在不使用编辑列表重新编码的情况下在非关键帧处进行剪切(关于编辑列表的问题)。换句话说,如果 3 秒之前最近的关键帧是 0 秒,那么它将从 0 秒开始复制视频并使用编辑列表告诉播放器开始播放不是在 3 秒,而是在 0 秒,因为它最近的关键帧休息帧被丢弃. 这就是为什么有时音频播放和视频图像挂起,但时间线继续运行的原因。
你做了什么,它不会重新编码原始的东西!它只是在最近的关键帧处拆分为您指定的开始/结束时间,并且它们的间距不相等,因此最终结果的长度不相等。
不要这样做: 即使它是我已经弄清楚的最快和最好的 ffmpeg 方式,这就是我假设你的方法正在做的事情:
ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4
但下面的东西会剪切并重新编码:
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4
重新编码时,您可能还希望包含其他编解码器选项,然后使用:
ffmpeg -ss 00:03:00 -t 00:00:05 -i test.wmv -acodec libmp3lame -vcodec libx264 1.mp4
但是 swami 有什么不同呢?
我们没有使用 -c 复制参数。因此不仅仅是转储原始 I/O 流。但重新编码,需要更多的 cpu 工作!
此外,-t 选项指定持续时间,而不是结束时间。上面的命令(第二个代码片段)将从 3 秒开始编码 8 秒的视频。要从 3 秒开始并在 8 秒结束,请使用 -t 5(第三个代码片段)。
注意:如果您使用的是当前版本的 ffmpeg(我猜是 2015 年以上),您还可以在上述命令中将 -t 替换为 -to 以在指定时间结束。
推荐阅读
- python - 如何在 Django 中的多对多字段上创建相对最大长度约束?
- javascript - Randomizing slides only works if more than two slides
- c# - 如何将 linq 用于 foreach
- html - 如何通过 NodeJS 在 Input 中正确显示值
- apache-spark - 持久化 Spark DataFrame 以点燃
- javascript - 如果存在,JS 按类查找一个元素,否则使用 or 运算符使用其他元素
- .net - 通过代码检查 Mac OS 上的 Internet 连接
- c++ - 数组到指针转换期间的临时实现
- go - 在 GO 中使用常见错误消息将字符串解析为不同类型
- r - 2 个多重响应集之间的频率