Skip to main content

Download subtitles or media from video and podcast URLs, then transcribe them to text.

Project description

CastScribe

CastScribe downloads subtitles or media from YouTube, Bilibili, Xiaoyuzhou, Apple Podcasts, playlists, feeds, and channel URLs, then writes transcript files.

It first tries subtitles. If subtitles are unavailable, it downloads audio. If audio-only download is unavailable, it downloads the lowest quality combined audio/video format and transcribes that.

Operating Systems

CastScribe can download media and convert existing subtitles on any system that supports Python and yt-dlp.

Local speech transcription depends on the operating system:

  • macOS 26 or later: local transcription uses Apple's yap command.
  • macOS before 26: use a cloud backend, or use faster-whisper by running on another supported Python environment.
  • Linux and Windows: local transcription uses faster-whisper.

Cloud transcription backends are available on macOS, Linux, and Windows when the matching cloud SDK and credentials are configured.

Requirements

  • Python 3.10+
  • yt-dlp Python package, installed automatically when installing this project
  • Or yt-dlp CLI available on PATH
  • optional cloud transcription SDKs: castscribe[azure], castscribe[aws], castscribe[google], or castscribe[cloud]

Local Transcription Setup

CastScribe first tries downloaded subtitles. These local transcription requirements apply only when no subtitle is available and CastScribe must transcribe audio.

macOS 26 or Later

CastScribe uses yap for the default local backend.

Install yap with Homebrew:

brew install yap

Or install it with Mint:

mint install finnvoor/yap

Enable Dictation and install the language assets before long runs:

  1. Open System Settings.
  2. Go to Keyboard.
  3. Enable Dictation.
  4. Add the language you plan to use, for example English -> United States.

yap does not provide speaker diarization. Use --backend google, --backend azure, or --backend aws when you need speaker labels.

Linux, Windows, or Non-yap Environments

CastScribe uses faster-whisper for the default local backend outside yap environments.

Install it through CastScribe's Whisper extra:

python3 -m pip install -e '.[whisper]'

Or install faster-whisper directly:

python3 -m pip install faster-whisper

The --model value is passed to faster-whisper; common choices are tiny, base, small, medium, and large-v3.

Install

Install from GitHub:

python3 -m pip install "castscribe @ git+https://github.com/longbai/CastScribe.git"

Or install from a local checkout:

python3 -m pip install -e .

Then run:

castscribe --help

You can also run without installing:

PYTHONPATH=src python3 -m castscribe --help

The old script entry remains available for compatibility:

PYTHONPATH=src python3 media_to_text.py --help

Usage

Single or multiple remote URLs:

castscribe "https://www.youtube.com/watch?v=..."
castscribe "https://space.bilibili.com/..." "https://www.xiaoyuzhoufm.com/episode/..."

URL file:

castscribe --input urls.txt

Channel or playlist URL:

castscribe --output transcripts "https://www.youtube.com/@channel/videos"
castscribe --output transcripts "https://www.youtube.com/playlist?list=..."
castscribe --locale en_US --output transcripts "https://podcasts.apple.com/cn/podcast/the-economics-of-everyday-things/id1666678354"

Local files, file:// URLs, and local directories:

castscribe ./audio.mp3
castscribe file:///Users/me/Downloads/captions.vtt
castscribe --output transcripts ./podcast-downloads

SRT output:

castscribe --format srt ./audio.mp3
castscribe --format srt --output transcripts "https://www.youtube.com/watch?v=..."

YouTube or Bilibili may require cookies when they show bot, sign-in, or HTTP 412 checks:

castscribe --cookies-from-browser chrome "https://www.youtube.com/shorts/JLV1YqS445I"
castscribe --cookies cookies.txt "https://www.youtube.com/watch?v=HjDsO0RHQHg&t=303s"
castscribe --cookies-from-browser chrome "https://space.bilibili.com/266765166/lists/2621160?type=season"

Limit a channel, playlist, or podcast feed while testing:

castscribe --playlist-items 1:2 --locale en_US --output transcripts "https://podcasts.apple.com/cn/podcast/the-economics-of-everyday-things/id1666678354"

Cloud Transcription

CastScribe only calls a transcription backend when it cannot use downloaded subtitles. The default backend is local.

Install optional cloud SDKs:

python3 -m pip install -e '.[azure]'
python3 -m pip install -e '.[aws]'
python3 -m pip install -e '.[google]'
python3 -m pip install -e '.[cloud]'

Azure Speech uses environment variables named SPEECH_KEY and ENDPOINT:

castscribe --backend azure --language en-US ./meeting.wav

AWS Transcribe uses the normal boto3 credential chain. The first version expects the media file to already be available in S3:

castscribe \
  --backend aws \
  --cloud-region us-west-2 \
  --cloud-uri s3://your-bucket/path/audio.mp3 \
  --language en-US \
  ./audio.mp3

Google Cloud Speech-to-Text uses Application Default Credentials:

castscribe --backend google --language en-US --min-speakers 2 --max-speakers 6 ./meeting.wav

Tencent Cloud and Alibaba Cloud are selectable but not implemented yet:

castscribe --backend tencent ./meeting.wav
castscribe --backend aliyun ./meeting.wav

Cloud credentials must not be committed to the repository. Do not pass access keys on the command line; use the provider's environment variables or default credential chain.

Behavior

The program first tries subtitles, preferring zh-Hans, zh-CN, zh, then en.

Apple Podcasts show pages are resolved through Apple's lookup API to their RSS feed before downloading episodes.

Local subtitle files are converted directly to .txt or .srt. Local media files are transcribed directly. Local directories are scanned recursively for supported subtitle and media files.

Output rules:

  • Without --output, each output is written next to the source or downloaded file with the same basename, ending in .txt or .srt.
  • With --output DIR, all transcript files are written directly into DIR.
  • Remote downloads use DIR/downloads when --output DIR is set. Without --output, downloads are written under the current directory using the yt-dlp filename template.
  • Existing .txt or .srt files are skipped, so channel and playlist downloads can be rerun after interruption.

Development

Run tests:

python3 -m unittest discover -s tests

Build a wheel and source distribution:

python3 -m pip install -e '.[build]'
python3 -m build
python3 -m twine check dist/*

Install the built wheel locally:

python3 -m pip install dist/castscribe-*.whl

Release

Packages are published by GitHub Actions when a GitHub Release is published.

Create a GitHub Release in the browser with tag v0.1.1.

Do not push a separate release tag when publishing from the GitHub Release UI; the release event triggers the publish workflow.

PyPI publishing uses Trusted Publishing. Configure the PyPI project with:

  • Owner: longbai
  • Repository: CastScribe
  • Workflow: publish.yml
  • Environment: pypi

No PyPI token is stored in the repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

castscribe-0.1.1.tar.gz (24.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

castscribe-0.1.1-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file castscribe-0.1.1.tar.gz.

File metadata

  • Download URL: castscribe-0.1.1.tar.gz
  • Upload date:
  • Size: 24.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for castscribe-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d2b694ba302fb4e2f3cec71dcff8fa19067144ffb433bc3857cb557eb4848f3c
MD5 52c771e8adc32bcd3fafd11ae4a56266
BLAKE2b-256 b10d077baf2c77ba80f48b80a589cb980a2ad35293aa5f7683a049476880b6a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for castscribe-0.1.1.tar.gz:

Publisher: publish.yml on longbai/CastScribe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file castscribe-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: castscribe-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 21.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for castscribe-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 17105c48df8bd18bde71b9ea89ff0a4a96577188810b4f394c0b267e1107c459
MD5 6a8160a2c1b8f894886bcbfda866dc9a
BLAKE2b-256 fb4c1bb1bad78e824a139907216fe798bf381ade52c6125ea300a554db525ea6

See more details on using hashes here.

Provenance

The following attestation bundles were made for castscribe-0.1.1-py3-none-any.whl:

Publisher: publish.yml on longbai/CastScribe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page