{"record":{"id":"dfbcb33d6a44763a","repo":"Panniantong/Agent-Reach","slug":"yt-dlp-produced-no-output-file-source-may-exceed","errorCode":null,"errorMessage":"yt-dlp produced no output file (source may exceed {limit_mib} MiB limit)","messagePattern":"yt-dlp produced no output file \\(source may exceed (.+?) MiB limit\\)","errorType":"exception","errorClass":"TranscribeError","httpStatus":null,"severity":"error","filePath":"agent_reach/transcribe.py","lineNumber":276,"sourceCode":"            \"-x\",\n            \"--audio-format\",\n            \"m4a\",\n            \"--audio-quality\",\n            \"0\",\n            \"--no-playlist\",\n            \"--max-filesize\",\n            str(MAX_SOURCE_BYTES),\n            \"-o\",\n            str(template),\n            \"--\",\n            url,\n        ],\n        timeout=1800,  # long podcasts over slow networks — generous but bounded\n    )\n    files = sorted(out_dir.glob(\"source.*\"))\n    if not files:\n        limit_mib = MAX_SOURCE_BYTES // (1024 * 1024)\n        raise TranscribeError(\n            f\"yt-dlp produced no output file (source may exceed {limit_mib} MiB limit)\"\n        )\n    audio = files[0]\n    _require_size_at_most(audio, MAX_SOURCE_BYTES, \"downloaded source\")\n    return audio\n\n\ndef compress_audio(src: Path, out_dir: Path) -> Path:\n    \"\"\"Re-encode to mono / 16kHz / 32kbps m4a — keeps most content under 25MB.\"\"\"\n    _require(\"ffmpeg\")\n    dst = out_dir / \"compressed.m4a\"\n    _run(\n        [\n            \"ffmpeg\",\n            \"-loglevel\",\n            \"error\",\n            \"-y\",\n            \"-i\",","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/Panniantong/Agent-Reach/blob/93ae1d18c37b707dec053c7c4f9d91cd8ef8943d/agent_reach/transcribe.py#L258-L294","documentation":"Raised by download_audio (transcribe.py:273-278) when yt-dlp exits successfully but no source.* file appears in out_dir. The most common cause is baked into the command: --max-filesize 512MiB makes yt-dlp silently skip downloads it estimates as over the limit, exiting 0 with no output. The hint in the message ('source may exceed 512 MiB limit') reflects that.","triggerScenarios":"A video/audio whose estimated filesize exceeds MAX_SOURCE_BYTES (512 MiB) — yt-dlp aborts before writing; also sites that extract to a format the -x --audio-format m4a post-processing chain yields nothing for, or a URL where yt-dlp downloads to a different filename pattern (template mismatch is prevented here by the fixed -o template, so size-skip dominates).","commonSituations":"Long lossless-audio uploads (FLAC/WAV concerts), high-bitrate 4-hour streams, or a reused out_dir where a previous failed run left stale state. Note a reused out_dir with an old source.* file would instead satisfy the glob with the stale file — always use a fresh dir.","solutions":["Check the actual size: yt-dlp --simulate -j -- <url> | jq '.filesize_approx' — if near/over 512 MiB, pick a lower-bitrate format or trim","Download out-of-band with yt-dlp choosing a smaller format (-f 'bestaudio[abr<=128]'), then pass the local file to transcribe()","Ensure out_dir is a fresh, empty directory per call","Run yt-dlp manually with the same flags minus --max-filesize to see the real failure mode"],"exampleFix":"# before\ndownload_audio(url, out_dir)  # yt-dlp produced no output file (source may exceed 512 MiB limit)\n\n# after: force a compact audio format out-of-band\nsubprocess.run([\"yt-dlp\", \"-x\", \"--audio-format\", \"m4a\", \"--audio-quality\", \"5\",\n                \"-f\", \"bestaudio[abr<=128]/bestaudio\", \"-o\", \"src.m4a\", \"--\", url], check=True)\ntext = transcribe(\"src.m4a\")","handlingStrategy":"validation","validationCode":"import subprocess, json\n\ndef within_source_budget(url: str, max_bytes: int = 512 * 1024 * 1024) -> bool:\n    out = subprocess.run([\"yt-dlp\", \"--simulate\", \"-j\", \"--\", url],\n                         capture_output=True, text=True)\n    if out.returncode != 0:\n        return False\n    info = json.loads(out.stdout)\n    size = info.get(\"filesize_approx\") or info.get(\"filesize\") or 0\n    return size <= max_bytes","typeGuard":null,"tryCatchPattern":"from agent_reach.transcribe import TranscribeError\ntry:\n    transcribe(url)\nexcept TranscribeError as e:\n    if \"produced no output file\" in str(e):\n        # download out-of-band with a size-capped format, then pass the local path\n        ...\n    raise","preventionTips":["Check filesize_approx with yt-dlp --simulate -j before calling","Prefer low-bitrate audio formats for long media","Always use a fresh empty out_dir per job to avoid stale-file confusion"],"tags":["yt-dlp","download","size-limit","transcription"],"backgroundTag":null,"analyzedSha":"93ae1d18c37b707dec053c7c4f9d91cd8ef8943d","analyzedAt":"2026-08-14T22:54:06.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}