You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

将numpy.ndarray转换为MP4视频时文件体积异常过小的问题排查求助

Troubleshooting the Tiny MP4 Output Issue in OpenCV

Let's break down why your output video is only 300KB instead of the expected ~50MB — this almost always boils down to a format mismatch between the frames you're writing and what cv2.VideoWriter expects, even though saving frames as PNG works perfectly. Here are the most likely fixes:

1. Check Frame Dimensions & Channel Count

cv2.VideoWriter is strict about matching the frame size and channel count you initialized it with. If your processed my_image has a different size or number of channels, the writer will silently fail to write valid frames (or write corrupted data), leading to a tiny file.

Add these print statements inside your loop to verify:

print(f"Expected size: ({frame_width}, {frame_height}) | My image size: ({my_image.shape[1]}, {my_image.shape[0]})")
print(f"Expected channels: 3 (BGR) | My image channels: {my_image.shape[2] if len(my_image.shape) ==3 else 1}")
  • If dimensions don't match: Resize your processed frame to match the original size before writing:
    my_image = cv2.resize(my_image, (frame_width, frame_height))
    
  • If channels are wrong (e.g., grayscale 1-channel): Convert it back to 3-channel BGR (MP4 typically expects color frames):
    if len(my_image.shape) == 2:
        my_image = cv2.cvtColor(my_image, cv2.COLOR_GRAY2BGR)
    

2. Fix Color Space Mismatch

OpenCV reads frames in BGR format, but your PIL code uses 'RGB' to save images — this means your processed my_image is likely in RGB format. cv2.VideoWriter expects BGR frames, so writing RGB frames will produce invalid data.

Convert the color space before writing:

# Convert RGB to BGR for OpenCV's VideoWriter
my_image = cv2.cvtColor(my_image, cv2.COLOR_RGB2BGR)

3. Ensure Proper Resource Release

Your current code only releases out when the stream ends, but if your loop exits early (e.g., an error or break condition), out might not flush all frames to disk. Use a try/finally block to guarantee release:

cap = cv2.VideoCapture(args.video)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (frame_width, frame_height))

try:
    while cap.isOpened():
        ret, img = cap.read()
        if not ret:
            print("Can't receive frame (stream end?). Exiting ...")
            break
        # Your frame processing code here...
        
        # Fix color space if needed
        my_image = cv2.cvtColor(my_image, cv2.COLOR_RGB2BGR)
        # Fix dimensions if needed
        if my_image.shape[:2] != (frame_height, frame_width):
            my_image = cv2.resize(my_image, (frame_width, frame_height))
        
        out.write(my_image)
finally:
    cap.release()
    out.release()
    cv2.destroyAllWindows()

4. Try a Different FourCC Codec

The mp4v codec (MPEG-4) might be compressing frames more aggressively than expected, or have compatibility issues with your system. Try using the H.264 codec (avc1) which is more widely supported and produces reasonable file sizes:

fourcc = cv2.VideoWriter_fourcc(*'avc1')

Note: If avc1 doesn't work, check if your OpenCV build supports it — some distributions require additional codecs.

Quick Sanity Check

To rule out corrupted frames, add a line to display your processed frame during the loop. If it looks normal, the issue is definitely with how you're feeding it to VideoWriter:

cv2.imshow('Processed Frame', my_image)
if cv2.waitKey(1) == ord('q'):
    break

内容的提问来源于stack exchange,提问作者Yagel

火山引擎 最新活动