{"record":{"id":"0b3e5e1316bc4443","repo":"roboflow/supervision","slug":"pyav-video-fallback-only-supports-color-3-channel","errorCode":null,"errorMessage":"PyAV video fallback only supports color (3-channel BGR) frames; is_color=False is not implemented.","messagePattern":"PyAV video fallback only supports color \\(3-channel BGR\\) frames; is_color=False is not implemented\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"src/supervision/_cv2/_video.py","lineNumber":202,"sourceCode":"        filename: str | os.PathLike[str],\n        fourcc: int,\n        fps: float,\n        frame_size: tuple[int, int],\n        is_color: bool = True,\n    ) -> None:\n        \"\"\"Open a PyAV writer for the requested codec and frame dimensions.\n\n        The PyAV fallback always encodes 3-channel BGR frames, so grayscale\n        output is unsupported. ``is_color=False`` is rejected up front rather\n        than silently ignored, keeping the OpenCV-shaped contract honest for\n        callers that would otherwise expect single-channel writes.\n\n        Raises:\n            NotImplementedError: If ``is_color`` is ``False``; grayscale\n                writing is not supported by the PyAV fallback.\n        \"\"\"\n        if not is_color:\n            raise NotImplementedError(\n                \"PyAV video fallback only supports color (3-channel BGR) frames; \"\n                \"is_color=False is not implemented.\"\n            )\n        self._container: Any = None\n        self._stream: Any = None\n        self._width, self._height = frame_size\n        self._opened = False\n        self._error: Exception | None = None\n\n        try:\n            codec, pixel_format = _codec_details(fourcc)\n            self._container = av.open(str(filename), mode=\"w\")\n            rate = Fraction(str(fps)).limit_denominator(100_000)\n            self._stream = self._container.add_stream(codec, rate=rate)\n            self._stream.width = self._width\n            self._stream.height = self._height\n            self._stream.pix_fmt = pixel_format\n            self._opened = True","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/_cv2/_video.py#L184-L220","documentation":"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.","triggerScenarios":"Constructing cv2.VideoWriter(path, fourcc, fps, frame_size, is_color=False) in an environment without opencv-python, where Supervision substitutes the PyAV writer.","commonSituations":"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.","solutions":["Convert frames to BGR before writing and use is_color=True (default): frame_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR).","Install opencv-python / opencv-python-headless to regain grayscale writer support.","Persist grayscale frames as PNG sequences or a NumPy file if codec support is unavailable."],"exampleFix":"# before\nwriter = cv2.VideoWriter('out.mp4', fourcc, fps, (w, h), is_color=False)\n\n# after\nwriter = cv2.VideoWriter('out.mp4', fourcc, fps, (w, h))\nframe_bgr = cv2.cvtColor(gray_frame, cv2.COLOR_GRAY2BGR)","handlingStrategy":"validation","validationCode":"writer = cv2.VideoWriter(path, fourcc, fps, (w, h))  # is_color omitted\nif gray.ndim == 2:\n    frame = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass is_color=False in cv2-free environments","Convert grayscale frames to BGR before writing"],"tags":["opencv-fallback","pyav","video-writer","grayscale","not-implemented"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}