OpenCV VideoCapture 关闭来自 GoPro 的视频

Mic*_*ael 4 python opencv ffmpeg

我有一个来自 GoPro 设备的视频文件,我只是通过这样的方式使用它VideoCapture

cap = cv2.VideoCapture(path)
        index = 0
        start = time.time()

        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break
            # do something here
        end = time.time()
Run Code Online (Sandbox Code Playgroud)

这很奇怪,但我可以处理除 GoPro 捕获的任何文件之外的任何文件。Stream 只是在某个时候关闭,因为retvalue 变成False并且frame变成None。没有例外或其他任何事情。

谷歌搜索帮助我找到了这个问题。我已经使用ffmpeg工具从文件中删除了音频流,然后一切正常。那么为什么会这样呢?请帮忙!

我正在使用 Python 3.6.4 x64、Windows 10(但在 Linux 上相同)和来自该资源的OpenCV 的预编译二进制文件。

小智 5

我也遇到了这个问题,并且能够在不修剪音频的情况下解决它。事实上,我不相信音轨是问题所在。

我在这个问题上看到的所有 ffmpeg 转换命令都有意想不到的副作用,即从视频文件中剥离所有元数据轨道。GoPro 实际上将大量原始传感器数据直接打包到 MP4 数据中。我认为这更有可能是罪魁祸首,因为它是文件中存在的最不“标准”的数据类型。

我通过剥离测试这个理论只是音轨使用下面的命令:

ffmpeg -i GH010001.MP4 -map 0 -map -0:a -c copy GH010001_MUTED.MP4
Run Code Online (Sandbox Code Playgroud)

这个新的静音文件表现出相同的问题行为,因此简单地删除音轨是行不通的。

现在,如果您不关心元数据轨道,用其他 ffmpeg 调用将它们剥离出来就完全​​没问题了!我实际上想使用那个传感器,所以我不得不找到另一种方法来解决它。

解决方法

下面的代码在概念层面上非常粗糙,但它有效。我们不像通常使用 OpenCV 那样检查空帧,而是简单地计算我们知道应该在那里的帧数,跳过空帧。

auto expectedFrameCount = videoCapture.get(cv::CAP_PROP_FRAME_COUNT);
for(auto frameIndex = 0; frameIndex < expectedFrameCount; frameIndex++) {
  videoCapture >> frame;
  if(frame.empty()) {
    frameIndex--;
    continue;
  }
  // Do useful things with the frame here...
}
Run Code Online (Sandbox Code Playgroud)

忽略文件末尾的通常标志绝对感觉不对,但它起作用了,我能够播放原始视频文件的所有帧,而无需先进行任何 ffmpeg 转换。