将numpy.ndarray转换为MP4视频时文件体积异常过小的问题排查求助
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




