Media Tools
The lab's media toolkit: 9 tools that compose end-to-end into a movie/series research → find → subtitle/dub → playback pipeline. Concrete commands, contracts, and composition patterns.
Purpose
The media toolkit is the lab's collection of 9 tools for entertainment automation. It is a concrete application of the Tooling Layer pattern to a specific domain: movie/series search, subtitle discovery, dubbed audio detection, technical metadata extraction, and multi-backend playback.
This page documents each tool's contract, the
end-to-end pipeline, and the composition patterns. The
per-tool TOOL.md format is in
Tool Spec. The standard tool structure
is in Tool Structure. The
tools.json schema is in
Tool Registry. The Media Lab Server
is in Media Lab Server.
Tool inventory
| # | Tool | Status | Layer | Function |
|---|---|---|---|---|
| 1 | torrent-finder | Implemented | search | Find BitTorrent sources for a title. |
| 2 | subtitle-finder | Implemented | search | Find subtitles in one or more languages. |
| 3 | dubbed-finder | Implemented | search | Detect releases with dubbed audio for a language. |
| 4 | media-info | Implemented | metadata | Extract technical video metadata via ffprobe. |
| 5 | media-organizer | Planned | library | Organize downloaded media into a library structure. |
| 6 | chromecast | Implemented | playback | Discover and control Cast devices on the LAN. |
| 7 | vlc | Implemented | playback | Spawn and control VLC locally or on a remote host. |
| 8 | media-playback | Implemented | dispatcher | High-level dispatcher that picks the right backend. |
| 9 | media-lab-server | Implemented | generation | Local HTTP server (:8765) for image and music generation. |
The tools are split into four layers: search, metadata, playback, dispatcher, and generation. The Media Agent composes the layers into an end-to-end pipeline.
Quick reference: end-to-end media pipeline
The Media Agent's typical request flow:
A full request runs in 3 to 7 seconds (search + selection + backend dispatch) without transcoding; with transcoding, 1-3 minutes.
torrent-finder
CLI tool. Searches public torrent sources for a movie or series by title, year, quality, or codec.
Activation
Activate when:
- The user asks for torrent sources for a specific title.
- A media request requires source identification.
- The Media Agent needs a candidate release.
Inputs
| Name | Type | Required | Constraints |
|---|---|---|---|
title | string | yes | non-empty |
year | integer | no | 1900 to current year |
quality | string | no | 480p, 720p, 1080p, 2160p |
codec | string | no | x264, x265, h264, h265, hevc, av1 |
limit | integer | no | default 20, max 100 |
Command shape
Outputs
Sources and their characteristics
The default configuration queries three sources; each has its own quirks.
| Source | Protocol | Filter support | Quality filters | Notes |
|---|---|---|---|---|
solidtorrents.net | HTML | strong | 4K, 1080p, HDR, DV, x265, x264 | Aggregator with rich filters. |
1377x.to | HTML | medium | 1080p, 720p | High seed counts; more 1080p releases. |
bt4g.com | HTML | weak | none built-in | High coverage; lower signal/noise. |
The tool normalizes the response across sources so the output JSON has a single shape.
Filters and quality detection
The tool runs each candidate through a multi-step filter:
- Title normalization. Strip the year, the resolution, the codec, the group, and any special characters.
- Quality match. Compare the release's quality tag
to the requested quality. A
1080prelease does not pass a4Kfilter. - Codec match. Compare the release's codec tag to
the requested codec.
h265andhevcare equivalent. - Size sanity check. A
4Krelease under 1 GB is rejected as probably CAM/TS. - Seeding threshold. A release with 0 seeders is rejected.
Failure modes
| Failure | Handling |
|---|---|
| All three sources timeout | Retry each once; return error. |
| One source returns 4xx | Skip; try the other two. |
| All sources return 4xx | Return error with the upstream status codes. |
| No results match the filter | Return empty sources array with count: 0. |
| Magnet URL is malformed | Skip the entry; log the issue. |
Result count exceeds limit | Sort by seeders, take top limit. |
Configuration
| Variable | Default | Purpose |
|---|---|---|
TORRENT_SOURCES | [solidtorrents.net, 1377x.to, bt4g.com] | Sources to query. |
TORRENT_TIMEOUT_S | 30 | Per-request timeout. |
TORRENT_USER_AGENT | (random per request) | User agent string. |
TORRENT_PROXY_URL | (none) | Optional HTTP/HTTPS proxy. |
TORRENT_MIN_SEEDERS | 0 | Minimum seeders to include a release. |
Dependencies
requests>=2.28: HTTP client.beautifulsoup4>=4.11: HTML parsing.lxml>=4.9: XML/HTML parser.pydantic>=2.0: output schema validation.
subtitle-finder
CLI tool. Searches public subtitle sites for a movie or series.
Activation
- The user asks for subtitles for a specific title.
- A media request requires subtitle discovery.
Inputs
| Name | Type | Required | Constraints |
|---|---|---|---|
title | string | yes | non-empty |
year | integer | no | 1900 to current year |
season | integer | no | 1 to 99 (series) |
episode | integer | no | 1 to 999 (series) |
language | string | yes | ISO 639-1 code (e.g., es, en) |
limit | integer | no | default 20, max 100 |
Command shape
Outputs
Failure modes
| Failure | Handling |
|---|---|
| All subtitle sites down | Return error with upstream status. |
| No results | Return empty subtitles array. |
| Release name not matching | Surface in the result metadata; user can pick. |
dubbed-finder
CLI tool. Detects releases that have audio dubbed in a given language.
Activation
- The user asks for a dubbed version of a title.
- A media request requires audio language information.
Inputs
| Name | Type | Required | Constraints |
|---|---|---|---|
title | string | yes | non-empty |
year | integer | no | 1900 to current year |
language | string | yes | ISO 639-1 code |
limit | integer | no | default 20, max 100 |
Outputs
How it detects dubbed audio
The tool uses two signals:
- Release name. Strings like
Spanish,Castellano,VOSE,Dual-Audio,Multiare strong signals. - Media-info cross-check. When the user has a local
file,
media-inforeturns the audio track languages; the tool uses that as ground truth.
The tool's media-info cross-check is the more reliable
signal; the release name is a hint.
media-info
CLI tool. Extracts technical video metadata through
ffprobe or mediainfo.
Activation
- The user asks for technical info on a video file.
- A media request needs resolution, codec, or duration.
- The Media Agent needs to verify the downloaded file matches the requested quality.
Inputs
| Name | Type | Required | Constraints |
|---|---|---|---|
path | string | yes | absolute path to a video file |
mode | string | no | full, quick (default full) |
Command shape
Outputs (full)
Failure modes
| Failure | Handling |
|---|---|
ffprobe not in PATH | Return error: backend unavailable. |
| File not found | Return error with the path. |
| File is not a media file | Return error with the format detection. |
| Permission denied | Return error with the permission needed. |
media-organizer (planned)
CLI tool. Organizes downloaded media into a library structure based on metadata. Status: planned; the implementation will follow the CLI Python tool template.
Planned inputs:
source: path to the source directory.library: path to the library root.strategy:movie-tmdb|series-tvdb|flat.
Planned outputs:
chromecast
CLI tool. Discovers Cast devices on the LAN and controls playback on a selected device.
Activation
- The user wants to play a cloud stream on a TV.
- The Media Agent's backend selector picks Chromecast for a request.
Protocol
The tool uses Google's Cast protocol. The discovery is
mDNS (_googlecast._tcp.local.). The control is HTTPS
on the port returned by the mDNS record (typically
8009).
Actions
| Action | Inputs | Outputs |
|---|---|---|
discover | none | list of devices |
play | device, url, content_type, title?, thumb? | playback status |
pause | device | ack |
resume | device | ack |
stop | device | ack |
status | device | current state |
volume | device, volume | new volume |
Command shape
Outputs
For discover:
For play:
Failure modes
| Failure | Handling |
|---|---|
| No devices on the LAN | Return empty list; user can retry. |
| Device unreachable | Retry once; then return error. |
play fails (e.g., bad URL) | Return the Cast error message. |
| Volume out of range | Clamp to 0.0-1.0. |
vlc
CLI tool. Spawns and controls VLC locally or on a remote host over the RC (TCP) or HTTP interface.
Activation
- The source is a local file and the user wants to play it on a remote device.
- The source is a network stream that needs transcoding or sending to a non-Cast device.
- The user explicitly requests VLC.
- The Media Agent's backend selector picks VLC for a request (e.g., when transcoding is required).
Protocol
VLC is controlled through its RC interface (TCP) or HTTP
interface. The default port for RC is 4212. The default
port for HTTP is 8080. The tool supports both.
Actions
| Action | Inputs | Outputs |
|---|---|---|
play | host, source | started / enqueued / failed |
enqueue | host, source | started / enqueued / failed |
pause | host | ack |
resume | host | ack |
stop | host | ack |
status | host | state and position |
transcode | host, source, profile | started / failed with sout URL |
duplicate | host, source, profile | started / failed with duplicate URL |
quit | host | ack |
Command shape
Outputs
For play:
For transcode:
Profiles
The profile argument is a named VLC sout profile.
Built-in profiles:
| Profile | Output | Use case |
|---|---|---|
hls-1080p | HLS 1080p @ 5 Mbps | Local network streaming to a TV |
hls-720p | HLS 720p @ 2.5 Mbps | Low-bandwidth or older devices |
dash-1080p | DASH 1080p @ 5 Mbps | Modern smart TVs |
raw-copy | Copy the source without re-encoding | Local playback |
audio-only | Strip video, keep audio | Casting to speakers |
Custom profiles can be added in the configuration.
Failure modes
| Failure | Result |
|---|---|
| Host unreachable (TCP connect refused) | Return a "host unreachable" result. |
| RC authentication fails | Return an "auth failed" result. |
add or play returns a VLC error | Return the error message in the result. |
sout URL port already in use | Increment and retry once. |
| VLC binary not found in PATH | Return a "backend unavailable" result. |
| Source file not found | Return a "source not found" result. |
Configuration
| Variable | Default | Purpose |
|---|---|---|
VLC_BINARY | vlc | Path to the VLC binary. |
VLC_RC_PORT | 4212 | Default RC port. |
VLC_RC_PASSWORD | (none) | Default RC password. |
VLC_HOSTS | (none) | Named hosts (e.g., kitchen:192.168.1.50). |
media-playback
High-level dispatcher. Selects the right playback
backend (Chromecast, VLC, or direct) for a given source
and target, then invokes the appropriate tool. The
Media Agent's request flow calls this tool instead of
calling chromecast, vlc, or the direct player
directly.
Backend selection algorithm
The dispatcher uses the following rules in order:
- Explicit backend. If the caller passed
backendexplicitly, use it. - Target device type. If the target is a Cast
device (name matches a discovered Cast), use
chromecast. - Source type and target. If the source is a local
file and the target is a named VLC host, use
vlc. - Source type and transcoding. If the source is a
local file and transcoding is required, use
vlc. - Source is a network stream. If the source is an
HLS/DASH stream and the target is a Cast device, use
chromecast. - Default. If none of the above match, use
direct(spawn the system default player).
Inputs
| Name | Type | Required | Constraints |
|---|---|---|---|
source | object | yes | the source to play (URL, file path, or stream descriptor) |
target | object | no | the target device (Cast name, VLC host, or localhost) |
backend | string | no | explicit backend choice: chromecast, vlc, or direct |
options | object | no | backend-specific options |
Outputs
Direct player
The direct player spawns the OS default media player:
- macOS:
open <path>oropen <url>. - Linux:
xdg-open <path>orxdg-open <url>.
The direct player is the simplest backend; it has no controls and no state tracking.
media-lab-server
A local HTTP server that generates images and music. Not a CLI tool but an HTTP service. Documented in detail at Media Lab Server.
Quick reference:
- Listens on
127.0.0.1:8765. - Exposes
/api/imageand/api/music. - Web UI at
http://127.0.0.1:8765/.
Tool coordination
The media tools compose into a pipeline. The Media Agent runs the pipeline.
Pipeline stages
- Discovery —
torrent-finderproduces a candidate list. - Selection — the user (or the agent, by default) picks one candidate.
- Subtitle discovery (optional) —
subtitle-finderproduces subtitle candidates. - Dubbed audio discovery (optional) —
dubbed-finderfinds releases with the requested language. - Metadata (optional) —
media-infoextracts technical info on the local file. - Backend selection —
media-playbackpicks a backend. - Dispatch —
media-playbackinvokes the chosen backend tool. - Playback — the user watches/listens.
The pipeline is the basis of the Media Agent workflow.
Sequential vs parallel
Stages 1, 3, and 4 can run in parallel when the search candidates are independent. Stages 5 and 7 must run sequentially because they depend on a single source. Stage 6 must run after stages 1-5 because it needs the selected source.
A typical parallel run:
torrent-finder(search sources) — 5-15 ssubtitle-finder(find subs) — 2-5 s — paralleldubbed-finder(find dubbed) — 2-5 s — parallelmedia-info(verify local file) — 1-2 s — only when the file is already downloaded
Caching
The tools cache their results:
torrent-findercaches the search results in a local file (~/.cache/torrent-finder/) for 1 hour.subtitle-findercaches for 1 hour.media-infocaches the per-file result indefinitely (the file's mtime is the cache key).
The cache reduces duplicate work when the user revisits the same title.
Error recovery
The pipeline is resilient: a stage that fails does not
abort the pipeline unless the user requires its output.
For example, if subtitle-finder fails, the user can
still play the release without subtitles.
The Media Agent surfaces the error to the user and continues with the next stage.
Registry entry examples
The media tools are registered in tools.json. Real
entries:
The tags are used by the skill loader to activate the right tool when a relevant topic appears in a request.