Skip to content

stupside/castor

Repository files navigation

Castor

stupside%2Fcastor | Trendshift

Latest Release Go Reference Homebrew License Build Status

Castor

Smart TVs won't cast arbitrary web video, and screen mirroring is laggy and drops resolution. Castor casts the real stream instead, at full quality, from your terminal.

Point Castor at a web page you are watching, or at a direct stream URL, and it finds the video, extracts the stream, transcodes it for your TV, and casts in real time. It can also resolve an IMDB/TMDB id against sources you configure yourself, and burn in auto-generated subtitles.

To extract, it launches headless Chrome and watches network traffic over the Chrome DevTools Protocol, then runs a short action pipeline to start playback: click the page, navigate into the largest iframe, and click again as a fallback. This works on pages that allow automated playback, and won't work everywhere.

A general-purpose casting tool: it casts only what you point it at. See Purpose and disclaimer.

Browsing titles in the castor TUI
Run castor cast to browse titles and cast, without leaving the terminal.

Installation

Run Castor as a native binary (recommended): it runs on your machine, so it shares your TV's network, which device discovery needs. The binary shells out to three tools that must be on your PATH:

Tool Version Used for
Chrome / Chromium Any recent Headless stream extraction
ffmpeg 7.1+ Transcoding (and stream copy)
ffprobe 7.1+ Source format detection

ffmpeg and ffprobe must be 7.1 or newer: Castor uses flags (-readrate_initial_burst, stricter HLS extension handling) that older builds reject. The Docker image bundles a suitable build (Linux only).

Homebrew (macOS)

brew install --cask stupside/tap/castor
Build from source (needs Go 1.26+ and cmake)

The whisper.cpp bindings are cgo and link a locally built libwhisper.a, so clone with submodules and build with make:

git clone --recurse-submodules https://github.com/stupside/castor.git
cd castor
make          # builds libwhisper.a, then the castor binary

go install won't work: the vendored whisper.cpp bindings come in through a local replace and need that prebuilt static lib.

Quick start

Tell Castor which TV to use: find its name with castor scan and put it in config.yaml.

device:
  name: "Living Room TV"   # exact name from `castor scan`
  type: dlna

Now cast a page you are watching, or a stream URL you have:

castor cast player https://example.com/watch/some-video

For the interactive browser, which searches titles and casts them for you, add a TMDB key and a source (see Configuration), then run castor cast:

Selecting a cast target in the castor TUI

The commands you'll use most (run castor --help for all flags):

Command What it does
castor scan List cast targets on your network
castor cast Browse titles and cast, interactively (needs a TMDB key)
castor cast player <url> Cast a web page that has an embedded video player
castor cast url <url> Cast a direct stream or video URL
castor cast movie <id> Resolve a movie id against your sources and cast
castor cast episode <id> --season N --episode N Resolve a TV episode and cast

Configuration

Castor reads config.yaml from the working directory (or --config <path>). The only required key is the device shown in Quick start; everything else (timeouts, probing, capture, transcoding, network interface, Chrome discovery) has working defaults.

Tip

Keep secrets like your TMDB key out of the committed file: put them in a git-ignored config.local.yaml that overlays config.yaml, or in CASTOR_SECTION__FIELD environment variables. See SECURITY.md.

Everything below is optional.

Sources: resolve movie / episode ids against sites you configure

cast movie, cast episode, and the interactive browser resolve a title id against sources you configure. Castor bundles none, so add your own (sites you are authorized to use). There is no catalog and no lookup: Castor substitutes the id into the templates you write, prefixes each of your proxies, and opens the resulting page, then extracts the stream exactly like cast player. For example, castor cast movie tt12300742 opens https://your-source.example/embed/movie/tt12300742.

sources:
  - proxies: ["https://your-source.example"]   # base URLs, tried in order
    templates:
      movie: "/embed/movie/{itemID}"
      episode: "/embed/tv/{itemID}/{season}-{episode}"
Resolver: cap resolution with max_height

Source selection and stream probing. All options have sensible defaults; you normally only set max_height to your TV's vertical resolution, which caps both the selected stream and the encoder output.

resolver:
  # The tallest video to cast. Source selection prefers the largest stream no
  # taller than this, and the encoder scales its output down to it. Defaults to
  # 1080; raise it to your TV's native height (e.g. 2160 for a 4K panel) to pass
  # 4K through, or lower it to save bandwidth.
  max_height: 2160
  # hls_timeout: 30s
  # probe_timeout: 30s
  # probe_max_concurrency: 2
  # ffprobe_path: ffprobe
TMDB: API key for the interactive browser

The interactive browser (castor cast) uses a TMDB API key to search titles; direct commands like cast movie <id> do not need it. Get a free key from themoviedb.org and keep it in config.local.yaml:

tmdb:
  api_key: "<KEY>"
Subtitles: auto-transcribe with whisper and burn in (off by default)

Auto-generated subtitles, transcribed with whisper and burned into the video:

whisper:
  enable: true             # off by default
  # language: "fr"         # default: English
  # model_path: ""         # default: ggml-tiny.en (~75 MB, auto-downloaded)

Supported devices

Run castor scan to list what is on your network.

Protocol Works with Status
DLNA / UPnP (MediaRenderer:1) Virtually every smart TV from the last decade (Samsung, LG, Sony Bravia, Panasonic Viera, Philips, Hisense, TCL, VIZIO, Sharp), plus networked players like Kodi, VLC, and Plex Tested on Samsung
Chromecast Google Cast devices Experimental, untested (contributions welcome)

Docker (optional)

The prebuilt ghcr.io/stupside/castor image bundles Chrome, ffmpeg, and ffprobe, so you install nothing by hand. Run it on a Linux host on the same LAN as your TV.

Warning

--network host is required: device discovery (SSDP multicast) and the TV streaming back from Castor both need the container on your real LAN. On Docker Desktop (macOS/Windows) that flag is a no-op, so the container never reaches your TV and scan finds nothing. Use the native binary there instead.

# Discover devices (no config needed)
docker run --rm --network host ghcr.io/stupside/castor:latest scan

# Cast, passing the Intel GPU through for hardware transcoding
docker run --rm --network host --device /dev/dri \
  -v "$PWD/config.yaml:/config.yaml" \
  -v castor-cache:/root/.cache \
  ghcr.io/stupside/castor:latest \
  cast player https://example.com/watch/some-video

--device /dev/dri hands the container your Intel GPU for VA-API hardware H.264 encoding; without it (or on a non-Intel host) Castor falls back to software libx264. Either way, when your TV already accepts the source video Castor stream-copies it and skips encoding entirely.

Run commands from the directory holding your config.yaml (mounted at /config.yaml). The castor-cache volume persists the auto-downloaded whisper models.

Tag Build
:latest Latest stable release
:canary Latest preview build
:v1.7.0 A specific pinned version

Purpose and disclaimer

Castor is a general-purpose caster, not a service tied to any particular site.

  • It hosts nothing. No bundled video, catalog, or sources: Castor casts only a page, stream URL, or source you supply and are authorized to use, much like a Chromecast.
  • It does not touch DRM. Castor does not decrypt or circumvent DRM, and cannot cast DRM-protected services.
  • Using it lawfully is your responsibility. Whether a site's terms of use and your local law allow what you do with Castor is on you. Do not use it to infringe copyright.

Castor is provided as-is for lawful, personal, and educational use.

Contributing

See CONTRIBUTING.md.

About

Point it at any web page and it finds the video, extracts the stream, transcodes it and casts in real time to your TV. It even burns subtitles….

Topics

Resources

License

Contributing

Security policy

Stars

1.8k stars

Watchers

3 watching

Forks

Packages

 
 
 

Contributors

Languages