unslothai/unsloth · warning · TranscriptUnavailable

This video has no captions.

Error message

This video has no captions.

What it means

TranscriptUnavailable raised when the player response contains a captions.playerCaptionsTracklistRenderer with no captionTracks entries that have a baseUrl. The video exists and plays, but YouTube exposes no caption tracks for it — no human subtitles and no auto-generated (ASR) track.

Source

Thrown at studio/backend/core/youtube_transcript.py:124

    Within a language a human-written track wins over an auto-generated one. With no
    match the track YouTube pairs with the video's default audio track is used.
    """
    if not _VIDEO_ID_RE.fullmatch(video_id):
        raise TranscriptUnavailable("That is not a YouTube video link.")

    async with httpx.AsyncClient(timeout = _TIMEOUT, follow_redirects = True) as client:
        player = await _fetch_player(client, video_id)
        status = (player.get("playabilityStatus") or {}).get("status")
        if status not in (None, "OK"):
            raise TranscriptUnavailable(
                (player.get("playabilityStatus") or {}).get("reason")
                or "YouTube will not play this video."
            )

        tracklist = (player.get("captions") or {}).get("playerCaptionsTracklistRenderer") or {}
        tracks = [t for t in (tracklist.get("captionTracks") or []) if t.get("baseUrl")]
        if not tracks:
            raise TranscriptUnavailable("This video has no captions.")

        track = _select_track(tracks, tracklist, languages)
        text = await _fetch_track_text(client, str(track["baseUrl"]))

    if not text:
        raise TranscriptUnavailable("This video's captions are empty.")
    text, truncated = _truncate_transcript(text)

    details = player.get("videoDetails") or {}
    return Transcript(
        video_id = video_id,
        title = str(details.get("title") or ""),
        author = str(details.get("author") or ""),
        length_seconds = _as_int(details.get("lengthSeconds")),
        language = _track_label(track),
        language_code = str(track.get("languageCode") or ""),
        is_generated = track.get("kind") == "asr",
        text = text,

View on GitHub (pinned to 203007d190)

Solutions

  1. Confirm the video shows a CC button on YouTube's watch page; if not, no transcript exists — skip it.
  2. If the video is new, retry later once auto-captions may have been generated.
  3. Use an alternative transcript source (whisper-based local transcription) when YouTube has none.

Example fix

# before
transcript = await fetch_transcript(video_id)

# after
try:
    transcript = await fetch_transcript(video_id)
except TranscriptUnavailable as exc:
    transcript = await transcribe_locally(video_id)  # fallback, e.g. whisper
Defensive patterns

Strategy: fallback

Try / catch

try:
    transcript = await fetch_transcript(video_id)
except TranscriptUnavailable as e:
    if "no captions" in str(e):
        transcript = await transcribe_audio_locally(video_id)  # e.g. whisper
    else:
        raise

Prevention

When it happens

Trigger: Videos where the uploader disabled subtitles and auto-captions have not been generated (or were turned off); music-heavy or non-speech videos where ASR produced nothing; tracks present but all missing baseUrl (filtered out).

Common situations: Auto-transcription features pointed at music videos, gameplay with no speech, or freshly uploaded videos where ASR is still processing; rare player-response shape changes dropping captionTracks.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/d1823d92edfbbcc0. Report an issue: GitHub.