{"record":{"id":"530d3e268ff521d9","repo":"Graphify-Labs/graphify","slug":"youtube-url-download-requires-yt-dlp-run-pip-ins","errorCode":null,"errorMessage":"YouTube/URL download requires yt-dlp. Run: pip install 'graphifyy[video]'","messagePattern":"YouTube/URL download requires yt-dlp\\. Run: pip install 'graphifyy\\[video\\]'","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"graphify/transcribe.py","lineNumber":39,"sourceCode":"\n\ndef _get_whisper():\n    try:\n        from faster_whisper import WhisperModel\n        return WhisperModel\n    except ImportError as exc:\n        raise ImportError(\n            \"Video transcription requires faster-whisper. \"\n            \"Run: pip install 'graphifyy[video]'\"\n        ) from exc\n\n\ndef _get_yt_dlp():\n    try:\n        import yt_dlp\n        return yt_dlp\n    except ImportError as exc:\n        raise ImportError(\n            \"YouTube/URL download requires yt-dlp. \"\n            \"Run: pip install 'graphifyy[video]'\"\n        ) from exc\n\n\ndef is_url(path: str) -> bool:\n    \"\"\"Return True if the string looks like a URL rather than a file path.\"\"\"\n    return any(path.startswith(p) for p in URL_PREFIXES)\n\n\ndef download_audio(url: str, output_dir: Path) -> Path:\n    \"\"\"Download audio-only stream from a URL using yt-dlp.\n\n    Returns the path to the downloaded audio file (.m4a or .opus).\n    Uses cached file if already downloaded.\n    \"\"\"\n    from graphify.security import validate_url\n    validate_url(url)  # blocks private IPs, bad schemes before yt-dlp runs","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/transcribe.py#L21-L57","documentation":"Raised by _get_yt_dlp (graphify/transcribe.py) when `import yt_dlp` fails. Downloading audio from a YouTube/URL source is optional functionality behind the [video] extra; the import is lazy, so the error appears only at the moment a URL download is attempted (is_url(path) returned True).","triggerScenarios":"Calling download_audio(url, ...) or transcription on a string starting with one of URL_PREFIXES in an environment without yt-dlp installed.","commonSituations":"Base graphifyy install used with URL input; environments that block yt-dlp installs (some corporate mirrors); yt-dlp removed by a cleanup step after it broke on a site change.","solutions":["pip install 'graphifyy[video]' to get yt-dlp (and faster-whisper).","Or download the media yourself beforehand and pass the local file path, which bypasses _get_yt_dlp entirely.","Keep yt-dlp current — site changes frequently break old versions (python -m pip install -U yt-dlp).","If installs are blocked, host the audio file internally and reference it by path."],"exampleFix":"# before\ntranscribe(\"https://youtu.be/xyz123\")  # ImportError: yt-dlp missing\n\n# after\npip install 'graphifyy[video]'\ntranscribe(\"https://youtu.be/xyz123\")\n# or: download manually, then\ntranscribe(\"talk.m4a\")","handlingStrategy":"validation","validationCode":"def yt_dlp_available() -> bool:\n    try:\n        import yt_dlp  # noqa: F401\n    except ImportError:\n        return False\n    return True\n\nfrom graphify.transcribe import is_url\nif is_url(target) and not yt_dlp_available():\n    raise SystemExit(\"URL download needs: pip install 'graphifyy[video]' (or pass a local file)\")","typeGuard":"def can_download_urls() -> bool:\n    return yt_dlp_available()","tryCatchPattern":"try:\n    audio = download_audio(url, out_dir)\nexcept ImportError as e:\n    if 'yt-dlp' in str(e):\n        # explicit alternative: user downloads media, we take a local path\n        audio = Path(ask_user_for_local_file())\n    else:\n        raise","preventionTips":["Install the [video] extra where URL ingestion is used.","Accept local file paths as a fallback input path in pipelines.","Keep yt-dlp updated; old versions fail on site changes."],"tags":["video","youtube","installation","optional-dependencies"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}