MCPcopy Index your code
hub / github.com/boul2gom/yt-dlp

github.com/boul2gom/yt-dlp @v2.7.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.7.2 ↗ · + Follow
2,439 symbols 6,279 edges 222 files 918 documented · 38%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

🎬️ A Rust library (with auto dependencies installation) for video downloading

This library is a Rust asynchronous wrapper around the yt-dlp command line tool, a feature-rich audio/video downloader supporting YouTube, Vimeo, TikTok, Instagram, Twitter, and more.

The crate is designed to download audio and video from various websites. You don't need to care about dependencies, yt-dlp and ffmpeg will be downloaded automatically.

⚠️ The project is still in development, so if you encounter any bugs or have any feature requests, please open an issue or a discussion.

Report a Bug · Request a Feature · Ask a Question


Develop CI
Release Downloads Ask DeepWiki

Discussions Issues Pull%20requests

License Stars Forks

Statistics

Codecov Quality Scorecard


💭️ Why use an external Python app?

Originally, to download videos from YouTube, I used the rustube crate, written in pure Rust and without any external dependencies. However, I quickly realized that due to frequent breaking changes on the YouTube website, the crate was outdated and no longer functional.

After a few tests and research, I concluded that the python app yt-dlp was the best compromise, thanks to its regular updates and massive community. Its standalone binaries and its ability to output the fetched data in JSON format make it a perfect candidate for a Rust wrapper.

Using an external program is not ideal, but it is the most reliable and maintained solution for now.

📥 How to get it

Add the following to your Cargo.toml file:

[dependencies]
yt-dlp = "2.7.2"

A new release is automatically published every two weeks, to keep up to date with dependencies and features. Make sure to check the releases page to see the latest version of the crate.

🔌 Optional features

This library puts a lot of functionality behind optional features in order to optimize compile time for the most common use cases. The following features are available.

  • 🪝 hooks - Enables Rust hooks and callbacks for download events. Allows registering async functions that will be called when events occur.
  • 📡 webhooks - Enables HTTP webhooks delivery for download events. Allows sending events to external HTTP endpoints with retry logic.
  • 📊 statistics - Enables real-time statistics and analytics on downloads and fetches. Exposes aggregate counters, averages, success rates, and a bounded history window.
  • cache-memory (enabled by default) — In-memory Moka cache (pulls in moka). Fast TTL-based eviction; no persistence.
  • 🗃️ cache-json — JSON file-system backend. One .json file per entry.
  • 🗄️ cache-redb — Embedded redb backend. Single-file, pure-rust, ACID-compliant.
  • 🌐 cache-redis — Distributed Redis backend. Native TTL via SETEX.
  • 🔴 live-recording - Enables live stream recording via HLS segment fetching (reqwest) or FFmpeg fallback. Pulls in m3u8-rs for HLS manifest parsing.
  • 📡 live-streaming - Enables live fragment streaming via HLS segment fetching (reqwest). Pulls in m3u8-rs for HLS manifest parsing.
  • 🔒 rustls - Enables the rustls-tls feature in the reqwest crate. This enables building the application without openssl or other system sourced SSL libraries.
  • 🌍 hickory-dns - Enables async DNS resolution via Hickory DNS (passes reqwest/hickory-dns). Replaces the default blocking system resolver with a fully async, pure-Rust resolver.

🗄️ Cache backends

The library includes a tiered metadata cache that avoids redundant yt-dlp subprocess calls for video info, downloaded files, and playlists. The architecture uses an optional L1 in-memory layer (Moka) and an optional L2 persistent layer, selected exclusively via Cargo features:

Feature Backend Persistence Notes
cache-memory (default) In-memory Moka ❌ No TTL-based eviction, async-ready
cache-json JSON files on disk ✅ Yes One .json file per entry in the cache directory
cache-redb Embedded redb ✅ Yes Single-file, pure-Rust, ACID transactions
cache-redis Redis ✅ Yes Distributed, native TTL via SETEX

Multiple persistent backends can be compiled in simultaneously. When exactly one is enabled, it is selected automatically. When several are enabled, CacheConfig::persistent_backend must be set explicitly; otherwise CacheLayer::from_config returns an Error::AmbiguousCacheBackend at runtime. The cache-memory feature (Moka L1) can always be combined with any persistent backend for a tiered L1 + L2 setup.

Default (in-memory Moka) — no persistence, TTL-based eviction, useful for short-lived processes:

[dependencies]
yt-dlp = { version = "2.7.2", features = ["cache-memory"] }

JSON — persistent, file-system backed, no extra dependencies:

[dependencies]
yt-dlp = { version = "2.7.2", features = ["cache-json"] }

Redb — embedded, single-file, ACID-compliant, great for desktop/server apps:

[dependencies]
yt-dlp = { version = "2.7.2", features = ["cache-redb"] }

Redis — distributed, ideal for multi-node or cloud deployments:

[dependencies]
yt-dlp = { version = "2.7.2", features = ["cache-redis"] }

Tiered (Moka L1 + persistent L2) — best of both worlds:

[dependencies]
yt-dlp = { version = "2.7.2", features = ["cache-memory", "cache-redb"] }

Multiple backends compiled in — select one at runtime via CacheConfig::persistent_backend:

[dependencies]
yt-dlp = { version = "2.7.2", features = ["cache-memory", "cache-json", "cache-redb"] }

```rust,ignore use yt_dlp::prelude::*;

let config = CacheConfig::builder() .cache_dir("cache") .persistent_backend(PersistentBackendKind::Redb) // required when multiple compiled in .build();


#### CDN URL expiry and cache invalidation

When a `Video` is cached, its stream format URLs are valid for approximately **6 hours** (YouTube CDN lifetime). The library tracks this automatically via the `available_at` field on each `Format`.

On every `fetch_video_infos` call, the cache checks whether the format URLs are still fresh. If they have expired, the cached entry is **silently invalidated** and the video is re-fetched — so you never end up downloading with stale CDN URLs. The configured TTL (default 24 h) acts as an upper bound; the effective TTL is `min(configured_ttl, cdn_url_lifetime)`.

This behavior is transparent and requires no changes to your code. You can inspect the expiry yourself:
```rust,ignore
if !video.are_format_urls_fresh() {
    // URLs are stale — fetch_video_infos will re-fetch automatically
}
// Or get the earliest available_at timestamp across all downloadable formats:
if let Some(ts) = video.formats_available_at() {
    println!("Format URLs valid until approx. {} (unix)", ts + yt_dlp::model::FORMAT_URL_LIFETIME);
}

🔍 Observability & Tracing

This crate always includes the Tracing tracing crate. The library emits debug and trace span events throughout its internal operations (downloads, cache lookups, subprocess execution, etc.).

⚠️ Important: tracing macros are pure no-ops without a configured subscriber. If you don't add one, there is zero runtime overhead.

To capture logs, add a subscriber in your application:

[dependencies]
tracing-subscriber = "0.3"

```rust,ignore use tracing::Level; use tracing_subscriber::FmtSubscriber;

let subscriber = FmtSubscriber::builder() // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.) // will be written to stdout. .with_max_level(Level::TRACE) // completes the builder. .finish(); tracing::subscriber::set_global_default(subscriber) .expect("setting default subscriber failed");


Refer to the [`tracing-subscriber` documentation](https://docs.rs/tracing-subscriber) for more advanced configuration (JSON output, log levels, targets, etc.).

---

## 📖 Documentation

The documentation is available on [docs.rs](https://docs.rs/yt-dlp).

## 🏗️ Multi-Extractor Architecture

This library now supports downloading from **1,800+ websites** through a flexible extractor system:

- **`Downloader`** - Universal client supporting all sites via the extractors
- **`extractor::Youtube`** - Highly optimized YouTube extractor with platform-specific features:
  - Player client selection (Android, iOS, Web, TvEmbedded) for bypassing restrictions
  - Format presets (Best, Premium, High, Medium, Low, AudioOnly, ModernCodecs)
  - YouTube-specific methods: `search()`, `fetch_channel()`, `fetch_user()`, `fetch_playlist_paginated()`
- **`extractor::Generic`** - Universal extractor for all other sites with authentication support

### 🧩 Usage Patterns

- 🎬️ For YouTube with optimizations:
```rust,no_run
use yt_dlp::Downloader;
use yt_dlp::client::deps::Libraries;
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let libraries = Libraries::new(
        PathBuf::from("libs/yt-dlp"),
        PathBuf::from("libs/ffmpeg")
    );
    let downloader = Downloader::builder(libraries, "output")
        .build()
        .await?;

    // Access YouTube-specific features
    let youtube = downloader.youtube_extractor();
    let results = youtube.search("rust programming", 10).await?;
    let channel = youtube.fetch_channel("UCaYhcUwRBNscFNUKTjgPFiA").await?;

    Ok(())
}
  • 🌐 For any website (YouTube, Vimeo, TikTok, etc.): ```rust,no_run use yt_dlp::Downloader; use yt_dlp::client::deps::Libraries; use std::path::PathBuf;

[tokio::main]

async fn main() -> Result<(), Box> { let libraries = Libraries::new( PathBuf::from("libs/yt-dlp"), PathBuf::from("libs/ffmpeg") ); let downloader = Downloader::builder(libraries, "output") .build() .await?;

// Works with any supported site
let video = downloader.fetch_video_infos("https://vimeo.com/123456789").await?;
let video_path = downloader.download_video(
    &video,
    "output.mp4"
).await?;
Ok(())

} ```

📚 Examples

  • 📦 Installing the yt-dlp and ffmpeg binaries: ```rust,no_run use yt_dlp::Downloader; use std::path::PathBuf;

[tokio::main]

pub async fn main() -> Result<(), Box

Extension points exported contracts — how you extend this code

VideoBackend (Interface)
Trait for video cache backend implementations. [5 implementers]
src/cache/backend/mod.rs
RangeFetcher (Interface)
A source capable of fetching an arbitrary byte range from a remote stream. Implementors provide the HTTP (or other) tra [3 …
crates/media-seek/src/lib.rs
VideoSelection (Interface)
Trait for selecting video, audio, and storyboard formats from a Video. [1 implementers]
src/client/streams/selection.rs
CommonTraits (Interface)
Trait that combines the basic traits that any structure should implement. This trait combines: - `Debug` for debug disp [1 …
src/model/utils/mod.rs
BaseMetadata (Interface)
Common metadata operations shared across different file formats. This trait provides methods to extract and format meta [1 …
src/metadata/base.rs
VideoExtractor (Interface)
(no doc) [3 implementers]
src/extractor/mod.rs
EventHook (Interface)
(no doc) [1 implementers]
src/events/delivery/hooks.rs
PlaylistBackend (Interface)
Trait for playlist cache backend implementations. [5 implementers]
src/cache/backend/mod.rs

Core symbols most depended-on inside this repo

clone
called by 362
src/events/delivery/hooks.rs
len
called by 349
tests/common/media_seek.rs
clone
called by 142
src/lib.rs
parse
called by 84
crates/media-seek/src/lib.rs
build
called by 81
src/client/builder.rs
get
called by 77
src/cache/stores/video.rs
temp_test_dir
called by 70
tests/common/fixtures.rs
build_e2e_downloader
called by 70
tests/e2e/helpers.rs

Shape

Function 1,396
Method 814
Class 164
Enum 53
Interface 12

Languages

Rust99%
Python1%

Modules by API surface

tests/unit/model/types.rs81 symbols
tests/unit/extractor/extractor.rs58 symbols
tests/unit/selection.rs52 symbols
tests/unit/error.rs50 symbols
tests/unit/events.rs47 symbols
tests/unit/download/config.rs37 symbols
crates/media-seek/src/video/mp4.rs35 symbols
tests/unit/utils/validation.rs34 symbols
src/model/types/chapter.rs34 symbols
src/download/manager.rs34 symbols
src/lib.rs33 symbols
tests/unit/utils/fs_utils.rs32 symbols

For agents

$ claude mcp add yt-dlp \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact