roboflow/supervision · error · ValueError
Video frames must use uint8 dtype
Error message
Video frames must use uint8 dtype
What it means
The PyAV writer wraps frames with av.VideoFrame.from_ndarray(..., format='bgr24'), which requires uint8 data. Frames in float32/float64 (normalized 0-1 images, model outputs) or uint16 are rejected before encoding.
Source
Thrown at src/supervision/_cv2/_video.py:239
except Exception as exc:
self._error = exc
self.release()
def isOpened(self) -> bool:
"""Return whether the writer initialized successfully."""
return self._opened
def write(self, frame: npt.NDArray[np.uint8]) -> None:
"""Encode one BGR frame and mux all packets produced by the encoder."""
if not self._opened or self._container is None or self._stream is None:
raise RuntimeError("Video writer is not open") from self._error
if frame.shape != (self._height, self._width, 3):
raise ValueError(
"Video frame must have shape "
f"({self._height}, {self._width}, 3), got {frame.shape}"
)
if frame.dtype != np.uint8:
raise ValueError("Video frames must use uint8 dtype")
video_frame = av.VideoFrame.from_ndarray(
np.ascontiguousarray(frame), format="bgr24"
)
for packet in self._stream.encode(video_frame):
self._container.mux(packet)
def release(self) -> None:
"""Flush delayed encoder packets and close the output container."""
container = self._container
stream = self._stream
self._container = None
self._stream = None
self._opened = False
if container is None:
return
try:
if stream is not None:View on GitHub (pinned to 7f254d9784)
Solutions
- Convert before writing: frame_u8 = np.clip(frame * 255, 0, 255).astype(np.uint8).
- If already in 0-255 floats: frame_u8 = frame.astype(np.uint8).
- Keep a single uint8 annotation canvas instead of converting model tensors directly.
Example fix
# before writer.write(heatmap_float) # float64 in [0, 1] # after frame_u8 = (np.clip(heatmap_float, 0, 1) * 255).astype(np.uint8) writer.write(np.stack([frame_u8]*3, axis=-1))
Defensive patterns
Strategy: validation
Validate before calling
if frame.dtype != np.uint8:
frame = np.clip(frame, 0, 255).astype(np.uint8) if frame.max() > 1 else (np.clip(frame, 0, 1) * 255).astype(np.uint8)
writer.write(frame) Type guard
def is_writable_frame(frame: np.ndarray) -> bool:
return frame.dtype == np.uint8 and frame.ndim == 3 and frame.shape[2] == 3 Prevention
- Convert float frames to uint8 before write
- De-normalize [0,1] model outputs with *255
- Keep annotation canvases uint8 end-to-end
When it happens
Trigger: Writing float arrays such as normalized model outputs, occupancy heat maps, or images processed in float precision without converting back to uint8.
Common situations: Pipelines that normalize frames for inference and forget to de-normalize; heat-map visualizations computed in float; mixing annotated float arrays from matplotlib-like operations. Real OpenCV also misbehaves with non-uint8, but the fallback fails loudly.
Related errors
- PyAV video fallback only supports color (3-channel BGR) fram
- Video writer is not open
- Video frame must have shape ({self._height}, {self._width},
- VideoWriter_fourcc requires exactly four characters
- Unsupported video codec: {code}
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/9bc60a895e54684a.
Report an issue: GitHub.