Download YouTube videos with no automatic subtitles
- ID
0ba233b- date
2025-12-24 16:49:40+00:00- author
Alex Chan <alex@alexwlchan.net>- parent
6ef2935- message
Download YouTube videos with no automatic subtitles YouTube has started returning an automatic HTTP 429 when downloading automatic subtitles on videos with no spoken audio, presumably because it looks suspicious. Download automatic subtitles in a separate step, only if we didn't get subtitles uploaded by the creator, and ignore an HTTP 429 error.- changed files
2 files, 44 additions, 1 deletion
Changed files
test_yt-dlp_alexwlchan.py (2310) → test_yt-dlp_alexwlchan.py (2814)
diff --git a/test_yt-dlp_alexwlchan.py b/test_yt-dlp_alexwlchan.py
index 99e4ffa..d1d1f7c 100644
--- a/test_yt-dlp_alexwlchan.py
+++ b/test_yt-dlp_alexwlchan.py
@@ -47,6 +47,22 @@ def test_youtube_path_is_cleaned_up() -> None:
)
+def test_youtube_video_does_not_http429() -> None:
+ """
+ Download a YouTube video without any subtitles or spoken audio.
+ """
+ video = download_video("https://www.youtube.com/watch?v=0N1_0SUGlDQ")
+ assert video["subtitle_path"] is None
+
+
+def test_youtube_video_with_automatic_subtitles() -> None:
+ """
+ Download a YouTube video with automatic subtitles.
+ """
+ video = download_video("https://www.youtube.com/shorts/hyGluE562oA")
+ assert video["subtitle_path"] is not None
+
+
def test_instagram_video() -> None:
"""
Download an Instagram video and check we get the expected output.
yt-dlp_alexwlchan.py (6777) → yt-dlp_alexwlchan.py (7803)
diff --git a/yt-dlp_alexwlchan.py b/yt-dlp_alexwlchan.py
index fc76ef8..00c26aa 100755
--- a/yt-dlp_alexwlchan.py
+++ b/yt-dlp_alexwlchan.py
@@ -12,6 +12,8 @@ from typing import Any, TypedDict
import httpx
import hyperlink
from yt_dlp import YoutubeDL
+from yt_dlp.networking.exceptions import HTTPError as YouTubeDLHTTPError
+from yt_dlp.utils import DownloadError
ydl_opts: Any = {
@@ -24,7 +26,6 @@ ydl_opts: Any = {
# Download subtitles, or YouTube's automatic subtitles if there
# aren't any.
"writesubtitles": True,
- "writeautomaticsub": True,
#
# Download video files as MP4 and thumbnails as JPEG, or convert
# to those formats if they aren't the best available.
@@ -169,6 +170,32 @@ def download_video(url: str) -> VideoInfo:
with YoutubeDL(ydl_opts) as ydl:
video_info: Any = ydl.extract_info(url)
+ # Try to download automatic subtitles for a YouTube video.
+ #
+ # If you try to download autosubs for a video which doesn't have any,
+ # YouTube rturns an HTTP 429 "Too Many Requests" error. Ignore this
+ # error, but raise all others.
+ if video_info["extractor"] == "youtube" and not any(
+ p.suffix == ".vtt" for p in tmp_dir.iterdir()
+ ):
+ ydl_auto_subtitle_opts = {
+ "logtostderr": True,
+ "writeautomaticsub": True,
+ "skip_download": True,
+ "outtmpl": ydl_opts["outtmpl"],
+ }
+ with YoutubeDL(ydl_auto_subtitle_opts) as ydl:
+ try:
+ ydl.extract_info(url)
+ except DownloadError as e:
+ if (
+ isinstance(e.exc_info[1], YouTubeDLHTTPError)
+ and e.exc_info[1].status == 429
+ ):
+ pass
+ else:
+ raise
+
cleanup_paths(tmp_dir)
video_path = next(p for p in tmp_dir.iterdir() if p.suffix == ".mp4")