Skip to content

Instantly share code, notes, and snippets.

@larsenv
Last active May 10, 2026 02:47
Show Gist options
  • Select an option

  • Save larsenv/432ffbd58978df07dd2e43089a12f8db to your computer and use it in GitHub Desktop.

Select an option

Save larsenv/432ffbd58978df07dd2e43089a12f8db to your computer and use it in GitHub Desktop.
PBS Kids Video Downloader
import json
import requests
import subprocess
import re
home = requests.get("https://content.services.pbskids.org/v2/kidspbsorg/home/").text
home = json.loads(home)
shows = {}
episodes = {}
print("==========PBS Kids Show Downloader by Larsenv==========\n")
def title(j, k, data):
i = 0
for f in data:
i += 1
number = str(j) + str(i).zfill(2)
number = number.zfill(3)
if k == 0:
shows[number] = f
elif k == 1:
episodes[number] = f
print(number + ". " + f["title"])
print("Show List:")
print("\nWeekly Promo:\n")
promo = home["collections"]["kids-promo"]
shows["000"] = promo
print("000. " + promo["title"])
print("\nSpotlight:\n")
spotlight = home["collections"]["kids-show-spotlight"]["content"]
shows["001"] = spotlight[0]
print("001. " + spotlight[0]["title"])
for i in range(1, 4):
print("\nTier {}:\n".format(i))
title(i, 0, home["collections"]["kids-programs-tier-{}".format(i)]["content"])
selection = input("\nPlease enter the number of the show you want to download: ")
url = shows[selection]["URI"].replace("pbs.org", "pbskids.org")
showhome = json.loads(requests.get(url).text)
print("\nEpisode and Clips List:")
print("\nClips:\n")
title("", 1, showhome["collections"]["clips"]["content"])
print("\nEpisodes:\n")
title(2, 1, showhome["collections"]["episodes"]["content"])
print("\nPromoted Content:\n")
title(3, 1, showhome["collections"]["promoted_content"]["content"])
print("\nWould you like to download a single episode/clip or all episodes/clips?\n")
print("1. Single episode/clip")
print("2. All clips")
print("3. All episodes")
print("4. All promoted content")
choice = input("\nPlease enter your choice: ")
if choice == "1":
selection2 = input("\nPlease enter the number of the episode or clip you want to download: ")
selections_to_download = [selection2]
elif choice == "2":
selections_to_download = [key for key in episodes.keys() if key.startswith('1')]
elif choice == "3":
selections_to_download = [key for key in episodes.keys() if key.startswith('2')]
elif choice == "4":
selections_to_download = [key for key in episodes.keys() if key.startswith('3')]
else:
print("Invalid choice. Exiting.")
exit()
for selection2 in selections_to_download:
print(f"\nDownloading {episodes[selection2]['title']}...")
# Follow the redirect to get the final episode URI
redirected_uri = requests.get(episodes[selection2]["URI"], allow_redirects=True).url
# Modify the episode URI to remove the resolution part
episode_uri = re.sub(r'-\d+p_', '_', redirected_uri)
# Fetch subtitles from 'closedCaptionsMultiLanguage' and pick the most compatible type
preferred_formats = ["WebVTT", "SRT", "DFXP", "Caption-SAMI"]
subtitle_languages = {}
for cc in episodes[selection2]["closedCaptionsMultiLanguage"]:
lang = cc["language"]
if lang not in subtitle_languages:
subtitle_languages[lang] = cc
else:
current_format = cc["format"]
existing_format = subtitle_languages[lang]["format"]
if preferred_formats.index(current_format) < preferred_formats.index(existing_format):
subtitle_languages[lang] = cc
# Collect the chosen subtitle URIs
all_subtitles = [subtitle_languages[lang]["URI"] for lang in subtitle_languages]
filename = (shows[selection]["title"] + " - " + episodes[selection2]["title"] + ".mkv").replace("/", " - ")
# Prepare FFmpeg command
ffmpeg_command = ["ffmpeg", "-i", episode_uri]
# Add each subtitle stream to the command as input
for vtt in all_subtitles:
ffmpeg_command.extend(["-i", vtt])
# Map video, audio, and all subtitles
ffmpeg_command.extend(["-map", "p:0"])
for i in range(len(all_subtitles)):
ffmpeg_command.extend(["-map", str(i + 1)])
# Set codec options
ffmpeg_command.extend(["-c", "copy"])
# Add metadata for language and title after all inputs
for i, (lang, cc) in enumerate(subtitle_languages.items()):
ffmpeg_command.extend([f"-metadata:s:s:{i}", f"language={lang}"])
subtitle_name = cc.get("name", lang)
ffmpeg_command.extend([f"-metadata:s:s:{i}", f"title={subtitle_name}"])
# Add output filename
ffmpeg_command.append(filename)
# Execute FFmpeg command
subprocess.call(ffmpeg_command)
print(f"\n{episodes[selection2]['title']} downloaded successfully!")
@susssanoo
Copy link
Copy Markdown

Sorry to bother, but what browser extension is needed to run this script?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment