我有一个来自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()
这很奇怪,但我可以使用GoPro捕获的任何文件除外。流只是在某个时刻关闭,因为ret
值变为False
而frame
变为None
。没有例外或其他任何事情。
谷歌搜索让我找到了this question。我用 ffmpeg 工具从文件中删除了音频流,然后一切正常。那么为什么会这样呢?请帮忙!
我使用的是Python 3.6.4 x64,Windows 10(但在Linux上相同)和来自this resource的OpenCV的预编译二进制文件。
答案 0 :(得分:1)
我也遇到了这个问题,能够在不修剪音频的情况下解决它。实际上,我不相信音轨是问题所在。
我在这个问题上看到的所有ffmpeg转换命令都具有从视频文件中剥离所有元数据轨道的意外副作用。 GoPro实际上将许多原始传感器数据直接打包到MP4数据中。我认为这更可能是罪魁祸首,因为它是文件中存在的最少“标准”数据类型。
我通过使用以下命令剥离 just 音轨来测试了这一理论:
ffmpeg -i GH010001.MP4 -map 0 -map -0:a -c copy GH010001_MUTED.MP4
这个新的静音文件表现出相同的问题行为,因此简单地删除音轨是行不通的。
现在,如果您不关心元数据轨道,那么将其与其他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...
}
忽略文件末尾的通常标志肯定不正确,但是它可以正常工作,而且我能够播放原始视频文件的所有帧,而无需先进行任何ffmpeg转换。
答案 1 :(得分:0)
我和迈克尔有同样的问题,想要为人们添加ffmpeg输出。输出太长,无法添加到上面的编辑或评论。
MacBook-Pro:MacOS ben$ ffmpeg -i /Users/ben/Downloads/GP011399.MP4
ffmpeg version 3.3.4 Copyright (c) 2000-2017 the FFmpeg developers
built with Apple LLVM version 8.1.0 (clang-802.0.42)
configuration: --prefix=/usr/local/Cellar/ffmpeg/3.3.4 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libmp3lame --enable-libx264 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma --enable-vda
libavutil 55. 58.100 / 55. 58.100
libavcodec 57. 89.100 / 57. 89.100
libavformat 57. 71.100 / 57. 71.100
libavdevice 57. 6.100 / 57. 6.100
libavfilter 6. 82.100 / 6. 82.100
libavresample 3. 5. 0 / 3. 5. 0
libswscale 4. 6.100 / 4. 6.100
libswresample 2. 7.100 / 2. 7.100
libpostproc 54. 5.100 / 54. 5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/ben/Downloads/GP011399.MP4':
Metadata:
major_brand : mp41
minor_version : 538120216
compatible_brands: mp41
creation_time : 2015-02-11T13:46:48.000000Z
firmware : HD4.01.02.00.00
Duration: 00:26:30.59, start: 0.000000, bitrate: 20127 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 1280x720 [SAR 1:1 DAR 16:9], 19979 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc (default)
Metadata:
creation_time : 2015-02-11T13:46:48.000000Z
handler_name : GoPro AVC
encoder : GoPro AVC encoder
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
creation_time : 2015-02-11T13:46:48.000000Z
handler_name : GoPro AAC
Stream #0:2(eng): Data: none (tmcd / 0x64636D74) (default)
Metadata:
creation_time : 2015-02-11T13:46:48.000000Z
handler_name : GoPro TCD
timecode : 13:46:07:17
Stream #0:3(eng): Data: none (fdsc / 0x63736466), 9 kb/s (default)
Metadata:
creation_time : 2015-02-11T13:46:48.000000Z
handler_name : GoPro SOS
可能与此有关吗?
OpenCV and GoPro - empty frames in VideoCapture stream
视频在VLC中播放时没有错误或明显损坏。相同的代码会打开我遇到过的所有其他视频文件(我已经使用此代码至少一年了。)
Opencv和Python版
2.7.10 (default, Feb 7 2017, 00:08:15)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Python Type "help", "copyright", "credits" or "license" for more information.
import cv2
cv2.__version__
'3.3.0'
与提交的代码相同Q.我的流读取26帧,然后返回ret = False。
答案 2 :(得分:0)
您未列出相机型号。但是我对GoPro的x264文件有问题。但不是x265文件。尝试在相机中将压缩模式从兼容模式更改为HEVC。对于x264,我使用“ ffmpeg -i video.mp4 -sn -an -vcodec mpeg4 -q:v 0 output.mp4”解压缩该文件,但此后文件大了约4倍。
答案 3 :(得分:0)
使用 OpenCV 4.4.0 对此进行更新(参考 Matt Barulic 的回答): 使用 VideoCapture 抓取/接收方法,我们已经通过类似的变通方法解决了这个问题。这段代码是用 C++ 编写的,但假设这种方法在 Python 中同样适用:
frameOk = videoCapture.grab();
if (!frameOk) {
if (framei > 0 && framei < 100) {
frameOk = true;
}
}
if (frameOk)
videoCapture.retrieve(image);
...