deepinsight/insightface · error · ValueError
NV21 data size is not enough: expected {expected_size} bytes
Error message
NV21 data size is not enough: expected {expected_size} bytes, actual {len(yuv)} bytes What it means
read_nv21 validates that the raw file holds at least width*height*3/2 bytes (Y plane + interleaved VU plane) before reshape and cv2.cvtColor(COLOR_YUV2BGR_NV21). If the buffer is smaller, conversion is impossible, so it raises this ValueError instead of producing garbage.
Source
Thrown at cpp-package/inspireface/python/read_nv21.py:15
import cv2
import numpy as np
from inspireface import ImageStream
import inspireface as isf
def read_nv21(file_path, width, height, rotate=0):
with open(file_path, 'rb') as f:
nv21_data = f.read()
yuv = np.frombuffer(nv21_data, dtype=np.uint8)
expected_size = width * height * 3 // 2
if len(yuv) < expected_size:
raise ValueError(f"NV21 data size is not enough: expected {expected_size} bytes, actual {len(yuv)} bytes")
yuv_mat = np.zeros((height * 3 // 2, width), dtype=np.uint8)
yuv_mat[:] = yuv[:height * width * 3 // 2].reshape(height * 3 // 2, width)
bgr_mat = cv2.cvtColor(yuv_mat, cv2.COLOR_YUV2BGR_NV21)
# add reverse rotate
if rotate != 0:
# calculate reverse rotate angle
reverse_angle = (360 - rotate) % 360
# select rotate method by angle
if reverse_angle == 90:
bgr_mat = cv2.rotate(bgr_mat, cv2.ROTATE_90_CLOCKWISE)
elif reverse_angle == 180:
bgr_mat = cv2.rotate(bgr_mat, cv2.ROTATE_180)
elif reverse_angle == 270:
bgr_mat = cv2.rotate(bgr_mat, cv2.ROTATE_90_COUNTERCLOCKWISE)View on GitHub (pinned to 7fadd420c2)
Solutions
- Check the file size equals width*height*3//2 and fix width/height to match the actual capture resolution.
- Confirm the data really is NV21 (Y plane then interleaved V/U), not NV12, RGB, or compressed.
- If the file is truncated, re-capture the frame — do not pad, fix the producer side.
Example fix
# before
bgr = read_nv21('frame.nv21', 1080, 1920) # ValueError: expected 3110400 bytes, actual 2073600
# after
import os
w, h = 1080, 1920
assert os.path.getsize('frame.nv21') >= w * h * 3 // 2, 'truncated NV21 file'
bgr = read_nv21('frame.nv21', w, h) Defensive patterns
Strategy: validation
Validate before calling
import os w, h = 1080, 1920 assert os.path.getsize(path) >= w * h * 3 // 2, 'NV21 file too small for given width/height'
Type guard
def is_valid_nv21(buf: bytes, w: int, h: int) -> bool:
return isinstance(buf, (bytes, bytearray)) and len(buf) >= w * h * 3 // 2 Try / catch
try:
bgr = read_nv21(p, w, h)
except ValueError as e:
if 'NV21 data size' in str(e):
raise RuntimeError(f'bad frame {p}: {e}') from e
raise Prevention
- Size-check buffers against w*h*3//2 before conversion.
- Source capture resolution and reader args from one config constant.
When it happens
Trigger: Calling read_nv21(path, width, height) where the file has fewer bytes than width*height*3//2 — wrong width/height passed for the file, a truncated capture, or a file that is actually NV12/RGB/JPEG rather than NV21.
Common situations: Mismatch between camera capture resolution and the reader arguments, feeding an RGB or grayscale dump into the NV21 reader, truncated camera-HAL dumps, or buffers that lost the chroma planes during copy.
Related errors
- OpenCV is required for video face swap: {exc}
- Video could not be opened.
- Video dimensions could not be read.
- Video writer could not be opened.
AI-assisted analysis of deepinsight/insightface@7fadd420c2 (2026-08-28).
Data as JSON: /api/errors/b98d1bed37802b2c.
Report an issue: GitHub.