{"record":{"id":"b05c0bc2cd0a7580","repo":"roboflow/supervision","slug":"video-source-has-no-video-stream-source","errorCode":null,"errorMessage":"Video source has no video stream: {source}","messagePattern":"Video source has no video stream: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/_cv2/_video.py","lineNumber":80,"sourceCode":"    def __init__(self, source: str | os.PathLike[str] | int) -> None:\n        \"\"\"Open a file source and retain a lazy PyAV frame iterator.\"\"\"\n        self._container: Any = None\n        self._stream: Any = None\n        self._frames: Iterator[Any] | None = None\n        self._source = source\n        self._position = 0\n        self._frame_count_cache: int | None = None\n        self._opened = False\n        self._error: Exception | None = None\n\n        try:\n            if isinstance(source, int):\n                raise BackendUnavailableError(\n                    \"PyAV fallback supports file paths, not webcam device indexes.\"\n                )\n            self._container = av.open(str(source), mode=\"r\")\n            if not self._container.streams.video:\n                raise ValueError(f\"Video source has no video stream: {source}\")\n            self._stream = self._container.streams.video[0]\n            self._frames = iter(self._container.decode(video=self._stream.index))\n            self._opened = True\n        except Exception as exc:\n            self._error = exc\n            logger.warning(\"Failed to open video source %r: %s\", source, exc)\n            self.release()\n\n    def isOpened(self) -> bool:\n        \"\"\"Return whether the underlying video file is open for reading.\"\"\"\n        return self._opened\n\n    def _frame_count(self) -> int:\n        \"\"\"Return the stream count, decoding a second handle if metadata lacks it.\"\"\"\n        if self._frame_count_cache is not None:\n            return self._frame_count_cache\n\n        count = int(getattr(self._stream, \"frames\", 0) or 0)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/_cv2/_video.py#L62-L98","documentation":"Raised when the PyAV capture opens a file successfully but the container contains no video stream (self._container.streams.video is empty). This happens with audio-only media, some corrupt files, or text files passed as video; the fallback refuses to continue with an empty stream.","triggerScenarios":"cv2.VideoCapture('audio.mp3'), a truncated/corrupt video, an image or arbitrary binary renamed to .mp4, or a stream URL that resolves to audio-only content.","commonSituations":"Globbing a directory and opening every file without extension checks, user-uploaded media of unknown type, or partially downloaded videos where the moov/index is missing.","solutions":["Verify the file is a video before opening: check extension and/or probe with av.open in a try block, inspecting container.streams.video.","Re-download or re-mux corrupt files (ffmpeg -i in.mp4 -c copy out.mp4 often repairs truncation).","Handle open failure via cap.isOpened() == False and skip/log the source instead of crashing a batch job."],"exampleFix":"# before\ncap = cv2.VideoCapture(user_supplied_path)  # may be audio-only\n\n# after\nimport av\ncap = cv2.VideoCapture(user_supplied_path)\nif not cap.isOpened():\n    logger.warning('not a readable video: %s', user_supplied_path)\n    continue","handlingStrategy":"validation","validationCode":"import av\n\ndef has_video_stream(path: str) -> bool:\n    try:\n        with av.open(path):\n            return True\n    except av.AVError:\n        return False\n\nif has_video_stream(path):\n    cap = cv2.VideoCapture(path)","typeGuard":null,"tryCatchPattern":"cap = cv2.VideoCapture(path)\nif not cap.isOpened():\n    logger.warning('skipping unreadable/non-video source: %s', path)\n    return None","preventionTips":["Filter by extension before opening directory globs","Probe media with PyAV/ffprobe before processing user uploads","Always check cap.isOpened() and skip-and-log in batch jobs"],"tags":["opencv-fallback","pyav","video-capture","invalid-input","media-validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}