docs.rs failed to build youtube-legend-cli-0.4.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
youtube-legend-cli
English | Português Brasileiro
What Is It
youtube-legend-cliis a single Rust binary that turns a YouTube URL into a clean subtitle file- It is non-interactive, ships no daemon, and never phones home
- It speaks plain HTTP to third-party subtitle providers, with no browser and no headless runtime
- The interface is pure Unix: the URL on argv or on
stdin, the subtitle body onstdout, logs and progress onstderr - The version in
Cargo.tomlis0.4.0
Why
- You want the subtitle text, and you do not want to run a browser to get it
- You want a command that behaves the same inside a script, a Makefile and an agent loop
- You want machine-readable failure, so
--jsongives you a stablekindinstead of prose you have to parse - You want the process to tell the truth through its exit code, so downstream tooling can branch without reading text
- You want configuration you can inspect, so
config list-keysprints the whole registry instead of a wiki page - You want zero surprises about state, so the binary reads NO environment variable at all
Superpowers
- One positional
[URL]accepts the watch, shorts, embed andyoutu.beforms - Three output formats behind
--format:txt,srtandvtt - Language negotiation through
--lang, in ISO 639-1 or BCP 47 form - Two real providers plus an
autochain that walks them in cost order - A local file cache with a TTL you control through
--cache-ttl - Batch mode that reads one URL per line from
stdin, with--jobsconcurrency and--resume - A structured JSON envelope on
stdoutunder--json, for success AND for failure - Agent-native output shaping with
--select,--filter,--limit,--sort,--dedupe-byand--count-only - Output budgets with
--truncate-contentand--max-output-bytes, so an agent never drowns in a transcript - A self-describing surface through
--print-schema,config list-keys,completionsandman - Unicode NFC normalisation on the emitted transcript text
- Cooperative signal handling:
SIGINTexits 130 andSIGTERMexits 143, both declared insrc/main.rs - Zero telemetry, zero analytics, zero call home
Quick Start
# Install from crates.io
# Subtitles for one video, plain text on stdout
# Keep the timestamps
# Brazilian Portuguese
# Structured JSON on stdout
# Batch mode, one URL per line on stdin
Installation
# From crates.io
# From a local checkout
# Verify
- The Minimum Supported Rust Version is 1.88.0, declared by
rust-versioninCargo.toml rust-toolchain.tomlpins the local development toolchain, which is a different and newer channel- This project has NO CI, so nothing enforces the MSRV for you: build and test on that version yourself
- The crate ships exactly one binary, named
youtube-legend-cli
Usage
Streams
stdoutcarries the subtitle body, or the--jsonenvelopestderrcarries logs, progress and human-readable error messages- MEASURED on 2026-09-04 with
--jsonagainstnot-a-url: the JSON error object leaves onstdoutand the exit code is 65 stdinaccepts one URL, or a batch of one URL per line under--batch--no-inputrefusesstdinand fails fast instead of blocking
Input And Output Flags
[URL]is the positional argument, in watch, shorts, embed oryoutu.beform--lang <LANG>sets the preferred subtitle language, ISO 639-1 or BCP 47, defaulten--ui-lang <LANG>sets the interface language for messages onstderr--format <FORMAT>pickstxt,srtorvtt, defaulttxt--jsonemits structured JSON onstdout--batchreads multiple URLs fromstdin, one per line--resumeskips URLs whose output a previous--batchrun already emitted--jobs <N>sets how many batch items run concurrently, default0, which derives the number from the host--no-inputrefusesstdinand fails fast--yesassumes yes for any confirmation prompt--print-schemaprints the JSON Schema of every output surface and exits
Network And Cache Flags
--timeout <SECONDS>caps the WHOLE operation, not one HTTP request, default300--provider <PROVIDER>acceptsauto,provider-decopyorprovider-noiz, defaultauto--user-agent <STRING>sets a custom User-Agent for HTTP requests--cache-ttl <HOURS>sets the local cache TTL, default24--no-cachedisables reads from the local cache--dry-runskips network I/O and serves reads from cache only--offlinerefuses every outbound request and serves reads from the local cache only
Logging And Presentation Flags
--verboseemits tracing events tostderr--quietsuppresses allstderroutput except errors--log-level <LEVEL>acceptserror,warn,info,debugortrace, defaultwarn--log-format <FORMAT>acceptstextorjson, defaulttext--color <WHEN>acceptsauto,alwaysornever, defaultauto--no-progresssuppresses progress bars onstderr--config <PATH>points at a TOML config file
Agent-Native Shaping Flags
--select <KEYS>keeps only these comma-separated dotted keys, and carries the alias--fields--filter <EXPR>filters elements bykey=value,key!=valueorkey~substring--limit <N>emits at most N elements--sort <KEY>sorts ascending by a dotted key--dedupe-by <KEY>drops later elements repeating that key's value--count-onlyreplaces the payload with a count--truncate-content <N>shortens strings above N characters, never bytes--max-output-bytes <N>caps the envelope at N bytes by dropping whole elements
Help Flags
-hand--helpprint help-Vand--versionprint the version
Providers
provider-decopypins the decopy.ai provider, which serves the native track only and offers no language choiceprovider-noizpins the noiz.io provider, which is subject to a five-per-day quotaautois the default and walks the whole chain in cost order- There are exactly TWO providers, and no browser is involved in either
# Default, auto walks the whole chain
# Pin one provider
Commands
- The binary exposes exactly THREE subcommands
configinspects and edits the configuration filecompletions <SHELL>prints the shell completion script onstdoutmanprints the section 1 manual page onstdout, in roff format
config
config pathprints the absolute path of the configuration fileconfig showprints every key that is set, in dotted formconfig get <KEY>prints the value of one keyconfig set <KEY> <VALUE>sets one key, validated against the registryconfig unset <KEY>removes one key, restoring the compiled defaultconfig list-keysprints the whole registry: key, type and description
completions
completionsaccepts exactly FIVE shells:bash,elvish,fish,powershellandzsh- The script is derived from the
clapcommand tree, so it never drifts from the flags above
man
manprints the section 1 page in roff format onstdout, derived from the same command tree
Configuration
- The binary reads ZERO environment variables to govern its behaviour
RUST_LOGwas the fallback for--log-leveluntil 2026-08-31 and is NOT read any more- Any document that teaches you an environment variable for this CLI is wrong
- Configuration happens in exactly two places: a CLI flag, and the TOML file that
configowns - Run
config pathto find that file,config list-keysto see every key it accepts, andconfig setto change one - A CLI flag always wins over the file
--config <PATH>points the run at a different TOML file
Exit Codes
- The CLI follows the BSD
sysexits.hconvention, mapped insrc/error.rs 0means success2means the command line was refused before the run started, withkindequal toinvalid_usage64isEX_USAGE, for an invalid usage or an emptystdin65isEX_DATAERR, for an invalid URL or invalid input66isEX_NOINPUT, forlanguage_unavailableand forno_captions69isEX_UNAVAILABLE, for a provider that is unavailable or rate limited70isEX_SOFTWARE, reserved for defects that are ours74isEX_IOERR, for a local I/O failure75isEX_TEMPFAIL, for the operation timeout76isEX_PROTOCOL, for a malformed upstream answer78isEX_CONFIG, for a configuration error130means the run was cut short bySIGINT141means the reader ofstdoutclosed the pipe143means the run was cut short bySIGTERM- Under
--batchthe process exit is the code of the WORST item, never of the first one
JSON Envelopes
Success Envelope
--jsonprints one JSON object onstdout- The measured keys are
byte_size,content,delivered_language,duration_ms,format,language,provider,source_url,target_resolved,target_sourceandvideo_id languageechoes what you ASKED for, by designdelivered_languageis the only field that reports the track actually deliveredtarget_sourcetellsargvapart frombatch-file
Error Envelope
- A failure also prints one JSON object on
stdout, never onstderr - The discriminant is
error, whose value is the booleantrue - There is NO nested
.errorobject and there is NOokfield, so a filter like.error.kindfails against a boolean - The top-level fields are
error,code,message,kind,retryable,provider,video_id,target_resolved,target_source,requested_language,available_languagesandattempts messageis localised by--ui-langand must NEVER be parsed- Branch on
kind, which is a stable English identifier for the failure class - Branch on
retryableto decide whether repeating the same call can help
|
Integration Patterns
- Pipe the plain body straight into a file, because
stdoutcarries nothing else - Branch on the exit code first, and only then parse
stdout - Shape the envelope in the CLI instead of post-processing it, so an agent pays for fewer tokens
- Cap the payload with
--truncate-contentand--max-output-byteswhen a transcript would blow your context - Use
--offlinein a sandbox that must never open a socket - Use
--no-inputin a non-interactive runner, so a missing URL fails fast instead of hanging onstdin - Use
--resumeto make a long batch restartable
# Only the fields an agent needs
# A batch of URLs, four at a time, restartable
# Branch on the exit code, then on kind
if ! out=; then
|
fi
# Never open a socket
Performance
- Three micro-benchmarks live in
benches/cache_bench.rs cache_pathmeasures composing the cache file pathsrt_to_textmeasures converting a SubRip body into plain textnoteey_to_textmeasures converting a provider transcript body into plain text- Run them with
cargo bench --bench cache_bench - No timing figure is published here, because this repository carries no reproducible baseline to cite
- The default URL length ceiling is 2048 characters, declared in
src/cli/mod.rs - The default whole-operation ceiling is 300 seconds, and it wraps the entire provider chain and every retry
Troubleshooting FAQ
The command exits 66 and prints nothing on stdout
- Exit 66 is
EX_NOINPUT, which coversno_captionsandlanguage_unavailable - Run again with
--jsonand readavailable_languagesto see what the video really offers - Ask for one of those languages with
--lang
The command exits 69
- Exit 69 is
EX_UNAVAILABLE, which covers a provider that is down or rate limited provider-noizcarries a five-per-day quota, so a quiet day is not the same as a broken install--offlinealso refuses the network by design, so check whether you passed it
The command exits 2 instead of 64
- Exit 2 means
claprefused the command line before the run started - Read the message on
stderr, fix the flag spelling, and try again
My JSON filter on .error.kind returns nothing
erroris a boolean, not an object, so you cannot index it- Read
.kindat the top level instead
Setting RUST_LOG changes nothing
- The binary reads NO environment variable
- Use
--log-levelon the command line, or setlog_levelthroughconfig set
The run hangs with no URL
- Without a URL the CLI waits on
stdinby design - Pass
--no-inputto fail fast instead
A batch run returned a failure exit even though most URLs worked
- Under
--batchthe process exit is the code of the worst item - Read the per-item envelopes on
stdoutto see which ones failed
Contributing
- Read CONTRIBUTING.md for the development workflow, the MSRV expectation, the style rules and the
no Co-authored-bypolicy - This project has NO CI, so you run the gates locally before you claim a change is green
Security
- Read SECURITY.md for the supported versions, the threat model and the private disclosure channel
- The
secret_endpointsmodule is declaredpub(crate), so upstream hostnames never enter the published rustdoc
Changelog
- Every release is recorded in CHANGELOG.md
- The Portuguese mirror is CHANGELOG.pt-BR.md
- No version history is inlined in this README, on purpose
License
- Dual-licensed under either MIT or Apache-2.0, at your option