roboflow/supervision · error · NotImplementedError

PyAV video fallback only supports color (3-channel BGR) fram

Error message

PyAV video fallback only supports color (3-channel BGR) frames; is_color=False is not implemented.

What it means

The PyAV fallback writer always encodes 3-channel BGR frames, so the OpenCV is_color=False option (grayscale output) cannot be honored. It raises NotImplementedError up front so callers do not discover the limitation after writing a corrupt file.

Source

Thrown at src/supervision/_cv2/_video.py:202

        filename: str | os.PathLike[str],
        fourcc: int,
        fps: float,
        frame_size: tuple[int, int],
        is_color: bool = True,
    ) -> None:
        """Open a PyAV writer for the requested codec and frame dimensions.

        The PyAV fallback always encodes 3-channel BGR frames, so grayscale
        output is unsupported. ``is_color=False`` is rejected up front rather
        than silently ignored, keeping the OpenCV-shaped contract honest for
        callers that would otherwise expect single-channel writes.

        Raises:
            NotImplementedError: If ``is_color`` is ``False``; grayscale
                writing is not supported by the PyAV fallback.
        """
        if not is_color:
            raise NotImplementedError(
                "PyAV video fallback only supports color (3-channel BGR) frames; "
                "is_color=False is not implemented."
            )
        self._container: Any = None
        self._stream: Any = None
        self._width, self._height = frame_size
        self._opened = False
        self._error: Exception | None = None

        try:
            codec, pixel_format = _codec_details(fourcc)
            self._container = av.open(str(filename), mode="w")
            rate = Fraction(str(fps)).limit_denominator(100_000)
            self._stream = self._container.add_stream(codec, rate=rate)
            self._stream.width = self._width
            self._stream.height = self._height
            self._stream.pix_fmt = pixel_format
            self._opened = True

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Convert frames to BGR before writing and use is_color=True (default): frame_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR).
  2. Install opencv-python / opencv-python-headless to regain grayscale writer support.
  3. Persist grayscale frames as PNG sequences or a NumPy file if codec support is unavailable.

Example fix

# before
writer = cv2.VideoWriter('out.mp4', fourcc, fps, (w, h), is_color=False)

# after
writer = cv2.VideoWriter('out.mp4', fourcc, fps, (w, h))
frame_bgr = cv2.cvtColor(gray_frame, cv2.COLOR_GRAY2BGR)
Defensive patterns

Strategy: validation

Validate before calling

writer = cv2.VideoWriter(path, fourcc, fps, (w, h))  # is_color omitted
if gray.ndim == 2:
    frame = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

Prevention

When it happens

Trigger: Constructing cv2.VideoWriter(path, fourcc, fps, frame_size, is_color=False) in an environment without opencv-python, where Supervision substitutes the PyAV writer.

Common situations: Writing grayscale/threshold/heat-map videos from processing pipelines that pass is_color=False as an optimization; works under real OpenCV, breaks when the dependency is dropped from a slim image.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/0b3e5e1316bc4443. Report an issue: GitHub.