在Python中,OpenCV无法读取未压缩的AVI视频文件,尽管它可以打开并读取元数据

编程语言 2026-07-10

我无法在.avi文件上使用opencv cap.read(),因为它在那里崩溃了。似乎有关于fourcc的问题,因为它返回0.0,而cap.IsOpened返回true。fps、宽度、高度也正确返回。我可以使用IINA无问题地播放这些.avi文件,但无法将其转换成其他任何视频格式。

import cv2
video_path = '/Users/aravind/Downloads/test.avi'  
cap = cv2.VideoCapture(video_path)

print(cap.get(cv2.CAP_PROP_FOURCC))
print("FPS:", cap.get(cv2.CAP_PROP_FPS))
print("Frame count:", cap.get(cv2.CAP_PROP_FRAME_COUNT))
print("Width:", cap.get(cv2.CAP_PROP_FRAME_WIDTH)) 
print("Height:", cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

while cap.isOpened():
     print("Working here")
     ret, frame = cap.read() # crashes here

我在Python中得到的错误是“zsh: segmentation fault python3 t.py”(t.py是上述文件的名称)

运行
ffprobe -v quiet -print_format json -show_streams /Users/aravind/Downloads/test.avi 给出:

{
    "streams": [
        {
            "index": 0,
            "codec_name": "rawvideo",
            "codec_long_name": "raw video",
            "codec_type": "video",
            "codec_tag_string": "[0][0][0][0]",
            "codec_tag": "0x0000",
            "width": 192,
            "height": 192,
            "coded_width": 192,
            "coded_height": 192,
            "has_b_frames": 0,
            "pix_fmt": "bgr24",
            "level": -99,
            "r_frame_rate": "30/1",
            "avg_frame_rate": "30/1",
            "time_base": "1/30",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 60,
            "duration": "2.000000",
            "bit_rate": "26991946",
            "nb_frames": "60",
            "extradata_size": 9,
            "disposition": {
                "default": 0,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0,
                "non_diegetic": 0,
                "captions": 0,
                "descriptions": 0,
                "metadata": 0,
                "dependent": 0,
                "still_image": 0,
                "multilayer": 0
            }
        }
    ]
}

运行
ffmpeg -i /Users/aravind/Downloads/test.avi -vframes 1 /tmp/test_frame.png 2>&1
给出如下输出,以及 /tmp/test_frame.png中期望的第一帧:

ffmpeg version 8.1 Copyright (c) 2000-2026 the FFmpeg developers
  built with Apple clang version 21.0.0 (clang-2100.0.123.102)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/8.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gpl --enable-libsvtav1 --enable-libopus --enable-libx264 --enable-libmp3lame --enable-libdav1d --enable-libvmaf --enable-libvpx --enable-libx265 --enable-openssl --enable-videotoolbox --enable-audiotoolbox --enable-neon
  libavutil      60. 26.100 / 60. 26.100
  libavcodec     62. 28.100 / 62. 28.100
  libavformat    62. 12.100 / 62. 12.100
  libavdevice    62.  3.100 / 62.  3.100
  libavfilter    11. 14.100 / 11. 14.100
  libswscale      9.  5.100 /  9.  5.100
  libswresample   6.  3.100 /  6.  3.100
Input #0, avi, from '/Users/aravind/Downloads/test.avi':
  Duration: 00:00:02.00, start: 0.000000, bitrate: 26813 kb/s
  Stream #0:0: Video: rawvideo, bgr24, 192x192, 26991 kb/s, 30 fps, 30 tbr, 30 tbn
File '/tmp/test_frame.png' already exists. Overwrite? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> png (native))
Press [q] to stop, [?] for help
Output #0, image2, to '/tmp/test_frame.png':
  Metadata:
    encoder         : Lavf62.12.100
  Stream #0:0: Video: png, rgb24(pc, gbr/unknown/unknown, progressive), 192x192, q=2-31, 200 kb/s, 30 fps, 30 tbn
    Metadata:
      encoder         : Lavc62.28.100 png
[image2 @ 0xbe7018280] The specified filename '/tmp/test_frame.png' does not contain an image sequence pattern or a pattern is invalid.
[image2 @ 0xbe7018280] Use a pattern such as %03d for an image sequence or use the -update option (with -frames:v 1 if needed) to write a single image.
[out#0/image2 @ 0xbe6c54180] video:2KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown
frame=    1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.03 bitrate=N/A speed=7.15x elapsed=0:00:00.00

刚刚发现问题可能出在我的视频上,因为它是用MATLAB的 videowriter创建的未压缩.avi文件。我用MATLAB创建了一个灰度AVI,工作正常。不太确定到底发生了什么

附上不起作用的视频链接:Jumpshare链接
和一个可用的视频链接:File examples

解决方案

首先我建议把你的代码改成类似下面这样的:

import sys
import cv2

video_path = '/Users/aravind/Downloads/test.avi'  
cap = cv2.VideoCapture(video_path)

print(cap.get(cv2.CAP_PROP_FOURCC))
frame_count = cap.get(cv2.CAP_PROP_FPS)
print("FPS:", frame_count)
print(f"Frame count: {frame_count}")
print("Width:", cap.get(cv2.CAP_PROP_FRAME_WIDTH)) 
print("Height:", cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

if not cap.isOpened():
    sys.exit(f"Capture not initialised possible unsupported codac! {video_path}")

work_to_do = (frame_count > 0)
current_frame = 0
while work_to_do:
    current_frame += 1
    print(f"Reading from {current_frame} of {frame_count}", end=" ")
    ok, frame = cap.read()
    if ok:
        print(f" - Read {frame.nbytes=}")
    work_to_do = ok and (current_frame < frame_count)
print(f"Ended after {current_frame} frames!")

这样你就能看清楚何时“崩溃”——是第一帧、最后一帧,还是尝试读取超过最后一帧。

之所以重要,是因为你当前的测试 cap.isOpened() 在初始化成功时会返回 True——你已经可以从元数据中感受到这一点。我怀疑你的崩溃可能是因为你试图读取视频文件末尾之外的内容。

如果是在第一帧就崩溃,这意味着未检测到编解码器( hence the 0.0 )且默认值不起作用,你可以尝试将Codec设置为一个合适的值。

在你提供的 test.avi 文件上运行我上面的代码时,我能够读取全部30帧,每帧为110,592字节。

然而,运行你自己的代码,带有 while cap.isOpened(): 的循环上限,循环不会终止,但在30帧之后,frameNone,因此对它调用任何方法/访问变量都会失败并抛出相应的错误。

输出:

0.0
FPS: 30.0
Frame count: 30.0
Width: 192.0
Height: 192.0
Reading from 1 of 30.0  - Read frame.nbytes=110592
Reading from 2 of 30.0  - Read frame.nbytes=110592
Reading from 3 of 30.0  - Read frame.nbytes=110592
Reading from 4 of 30.0  - Read frame.nbytes=110592
Reading from 5 of 30.0  - Read frame.nbytes=110592
Reading from 6 of 30.0  - Read frame.nbytes=110592
Reading from 7 of 30.0  - Read frame.nbytes=110592
Reading from 8 of 30.0  - Read frame.nbytes=110592
Reading from 9 of 30.0  - Read frame.nbytes=110592
Reading from 10 of 30.0  - Read frame.nbytes=110592
Reading from 11 of 30.0  - Read frame.nbytes=110592
Reading from 12 of 30.0  - Read frame.nbytes=110592
Reading from 13 of 30.0  - Read frame.nbytes=110592
Reading from 14 of 30.0  - Read frame.nbytes=110592
Reading from 15 of 30.0  - Read frame.nbytes=110592
Reading from 16 of 30.0  - Read frame.nbytes=110592
Reading from 17 of 30.0  - Read frame.nbytes=110592
Reading from 18 of 30.0  - Read frame.nbytes=110592
Reading from 19 of 30.0  - Read frame.nbytes=110592
Reading from 20 of 30.0  - Read frame.nbytes=110592
Reading from 21 of 30.0  - Read frame.nbytes=110592
Reading from 22 of 30.0  - Read frame.nbytes=110592
Reading from 23 of 30.0  - Read frame.nbytes=110592
Reading from 24 of 30.0  - Read frame.nbytes=110592
Reading from 25 of 30.0  - Read frame.nbytes=110592
Reading from 26 of 30.0  - Read frame.nbytes=110592
Reading from 27 of 30.0  - Read frame.nbytes=110592
Reading from 28 of 30.0  - Read frame.nbytes=110592
Reading from 29 of 30.0  - Read frame.nbytes=110592
Reading from 30 of 30.0  - Read frame.nbytes=110592
Ended after 30 frames!

我正在Windows 11上使用Python 3.14.3、cv2 4.13.0.92进行测试,因此建议运行:

python3 -mpip install --upgrade opencv-python numpy

然后在测试时使用正确的结束条件重新运行。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章