Skip to main content

ez_ffmpeg/
lib.rs

1// In test builds, libtest-generated code references test items through the
2// deprecated `opengl` module path, which a file-level allow cannot cover.
3#![cfg_attr(test, allow(deprecated))]
4// Safety-hygiene lint (clippy-only; does not affect normal builds). Every
5// public `unsafe fn` must document its contract with a `# Safety` section.
6// Broader gates (`clippy::undocumented_unsafe_blocks`, `unsafe_op_in_unsafe_fn`)
7// are deferred until the pre-existing unsafe-doc/import backlog is paid down.
8#![warn(clippy::missing_safety_doc)]
9
10//! # ez-ffmpeg
11//!
12//! **ez-ffmpeg** provides a safe and ergonomic Rust interface for [FFmpeg](https://ffmpeg.org)
13//! integration. By abstracting away much of the raw C API complexity,
14//! It abstracts the complexity of the raw C API, allowing you to configure media pipelines,
15//! perform transcoding and filtering, and inspect streams with ease.
16//!
17//! ## Crate Layout
18//!
19//! - **`core`**: The foundational module that contains the main building blocks for configuring
20//!   and running FFmpeg pipelines. This includes:
21//!   - `Input` / `Output`: Descriptors for where media data comes from and goes to (files, URLs,
22//!     custom I/O callbacks, etc.).
23//!   - `FilterComplex` and [`FrameFilter`](filter::frame_filter::FrameFilter): Mechanisms for applying FFmpeg filter graphs or
24//!     custom transformations.
25//!   - `container_info`: Utilities to extract information about the container, such as duration and format details.
26//!   - `stream_info`: Utilities to query media metadata (duration, codecs, etc.).
27//!   - `hwaccel`: Helpers for enumerating and configuring hardware-accelerated video codecs
28//!     (CUDA, VAAPI, VideoToolbox, etc.).
29//!   - `codec`: Tools to list and inspect available encoders/decoders.
30//!   - `packet_sink`: Encoded-packet export — consume encoder output
31//!     (WebCodecs-style H.264 access units, AAC frames) directly through
32//!     callbacks, without writing a container.
33//!   - `device`: Utilities to discover system cameras, microphones, and other input devices.
34//!   - `filter`: Query FFmpeg's built-in filters and infrastructure for building custom frame-processing filters.
35//!   - `context`: Houses [`FfmpegContext`] for assembling an FFmpeg job.
36//!   - `scheduler`: Provides [`FfmpegScheduler`] which manages the lifecycle of that job.
37//!
38//! - **`wgpu_filter`** (feature `"wgpu"`): GPU-accelerated frame filters via wgpu
39//!   (Vulkan/Metal/DX12/GL). Provide a WGSL fragment shader and apply effects with
40//!   correct color handling, headless operation, and GPU/CPU overlap.
41//!
42//! - **`opengl`** (feature `"opengl"`, deprecated): The former OpenGL filter path,
43//!   superseded by `wgpu_filter`. Kept for backward compatibility; it requires a
44//!   display connection and will be removed in a future major release.
45//!
46//! - **`rtmp`** (feature `"rtmp"`): Embedded RTMP server `EmbedRtmpServer` built for production streaming,
47//!   using native epoll/kqueue/WSAPoll via libc FFI (edge-triggered on Linux/macOS, level-triggered on Windows),
48//!   zero-copy GOP fanout with `Arc<[FrameData]>`, and tiered backpressure (1/2/4MB) on a 2-thread model;
49//!   10,000+ conns on Linux/macOS (8,000 on Windows) with in-process ingest (no TCP between FFmpeg and server).
50//!
51//! - **`flv`** (feature `"flv"`): Provides data structures and helpers for handling FLV
52//!   containers, useful if you’re working with RTMP or other FLV-based workflows.
53//!
54//! - **`subtitle`** (feature `"subtitle"`): Burns ASS/SRT subtitles onto video frames inside
55//!   the frame pipeline with a pure-Rust renderer — independent of whether the linked FFmpeg
56//!   was built with `--enable-libass`. Accepts subtitle files or in-memory scripts and
57//!   explicit font files.
58//!
59//! ## Basic Usage
60//!
61//! For a simple pipeline, you typically do the following:
62//!
63//! 1. Build a [`FfmpegContext`] by specifying at least one [input](Input)
64//!    and one [output](Output). Optionally, add filter descriptions
65//!    (`filter_desc`) or attach [`FrameFilter`](filter::frame_filter::FrameFilter) pipelines at either the input (post-decode)
66//!    or the output (pre-encode) stage.
67//! 2. Create an [`FfmpegScheduler`] from that context, then call `start()` and `wait()` (or `.await`
68//!    if you enable the `"async"` feature) to run the job.
69//!
70//! ```rust,ignore
71//! use ez_ffmpeg::FfmpegContext;
72//! use ez_ffmpeg::FfmpegScheduler;
73//!
74//! fn main() -> Result<(), Box<dyn std::error::Error>> {
75//!     // 1. Build the FFmpeg context
76//!     let context = FfmpegContext::builder()
77//!         .input("input.mp4")
78//!         .filter_desc("hue=s=0") // Example filter: desaturate
79//!         .output("output.mov")
80//!         .build()?;
81//!
82//!     // 2. Run it via FfmpegScheduler (sync mode)
83//!     let result = FfmpegScheduler::new(context)
84//!         .start()?
85//!         .wait();
86//!     result?; // If any error occurred, propagate it
87//!     Ok(())
88//! }
89//! ```
90//!
91//! ## Feature Flags
92//!
93//! **`ez-ffmpeg`** uses Cargo features to provide optional functionality. By default, no optional
94//! features are enabled, allowing you to keep dependencies minimal. You can enable features as needed
95//! in your `Cargo.toml`:
96//!
97//! ```toml
98//! [dependencies.ez-ffmpeg]
99//! version = "*"
100//! features = ["wgpu", "rtmp", "flv", "async"]
101//! ```
102//!
103//! ### Core Features
104//!
105//! - **`wgpu`**: Enables wgpu-based GPU filters (WGSL shaders, headless-capable).
106//! - **`opengl`** (deprecated): Enables the former OpenGL-based filters; superseded by `wgpu`.
107//! - **`rtmp`**: Embedded RTMP server tuned for scale (10,000+ conns on Linux/macOS, 8,000 on Windows),
108//!   native epoll/kqueue/WSAPoll IO (edge-triggered on Linux/macOS), zero-copy GOP, and in-process ingest
109//!   that avoids TCP between FFmpeg and server.
110//! - **`flv`**: Adds FLV container parsing and handling.
111//! - **`subtitle`**: Native ASS/SRT subtitle burn-in rendered in pure Rust — no system
112//!   libraries beyond FFmpeg itself (see the `subtitle` module docs).
113//! - **`async`**: Adds asynchronous functionality: [`FfmpegScheduler`] additionally implements
114//!   `Future`, so a running scheduler can be `.await`ed as a non-blocking alternative to the
115//!   always-available synchronous `wait()`.
116//! - **`cli`**: Strict ffmpeg command-line subset: run a supported command in-process with
117//!   `ez_ffmpeg::cli::from_cli_args`, or translate it into equivalent builder code with
118//!   `ez_ffmpeg::cli::emit_rust_code`. Every token must classify against a versioned
119//!   compatibility manifest; execution is additionally gated on verified (golden-tested)
120//!   command shapes and a verified linked-FFmpeg runtime profile — see the `cli` module docs.
121//! - **`static`**: Uses static linking for FFmpeg libraries (via `ffmpeg-next/static`).
122//!
123//! ## Relationship to the FFmpeg CLI
124//!
125//! The transcoding pipeline (demux -> decode -> filter -> encode -> mux) is
126//! ported from the FFmpeg CLI sources, `fftools/ffmpeg` of **FFmpeg 7.x**:
127//! function names, timestamp handling and scheduling semantics follow that
128//! release, and code comments cite the corresponding fftools file and line
129//! (line numbers refer to the FFmpeg `n7.1` tag).
130//! If you know `ffmpeg_demux.c` or `ffmpeg_filter.c`, grepping this crate
131//! for the same function names (`ts_fixup`, `video_sync_process`,
132//! `enc_open`, `mux_fixup_ts`, ...) lands in the equivalent Rust.
133//!
134//! Bitstream filters (`-bsf:v/-bsf:a/-bsf:s`) are supported through
135//! [`Output::set_video_bsf`](crate::core::context::output::Output::set_video_bsf)
136//! and its audio/subtitle siblings (single filter or comma-separated chain).
137//!
138//! Not every CLI feature is implemented. Notable gaps: progress/stats
139//! reporting (`-progress`), sub2video (rendering bitmap subtitles into
140//! video), `-fix_sub_duration`, and two-pass encoding. Unsupported paths
141//! fail with explicit errors rather than approximations.
142//!
143#![doc = include_str!("../docs/cli_mapping.md")]
144//!
145//! ## Logging
146//!
147//! FFmpeg's own diagnostics (av_log) are redirected into the Rust `log`
148//! facade under the [`FFMPEG_LOG_TARGET`] target. Without a logger installed
149//! (env_logger, tracing-log, ...) all FFmpeg messages are silently dropped —
150//! including decoder errors that explain a failing job. Use
151//! [`set_ffmpeg_log_level`] to bound the forwarded verbosity and
152//! `Input::set_log_level_offset` to shift it per input.
153//!
154//! ## License Notice
155//!
156//! ez-ffmpeg is licensed under your choice of MIT, Apache-2.0, or MPL-2.0
157//! (matching the `license` field in Cargo.toml).
158//!
159//! **Note:** FFmpeg itself is subject to its own licensing terms. When enabling features that incorporate FFmpeg components,
160//! please ensure that your usage complies with FFmpeg's license.
161
162pub mod core;
163pub mod error;
164pub mod util;
165
166/// Internal RAII wrappers concentrating raw FFmpeg FFI pointers (Rung-2 boundary).
167pub(crate) mod raw;
168
169pub use self::core::analysis;
170pub use self::core::capabilities;
171#[cfg(feature = "cli")]
172pub use self::core::cli;
173pub use self::core::codec;
174pub use self::core::container_info;
175pub use self::core::context::ffmpeg_context::FfmpegContext;
176pub use self::core::context::input::Input;
177pub use self::core::context::output::Output;
178pub use self::core::device;
179pub use self::core::filter;
180pub use self::core::frame_export;
181pub use self::core::hwaccel;
182pub use self::core::packet_scanner;
183pub use self::core::packet_sink;
184pub use self::core::recipes;
185pub use self::core::scheduler::ffmpeg_scheduler::FfmpegScheduler;
186pub use self::core::stream_info;
187pub use self::core::writer::{PushError, VideoWriter, VideoWriterBuilder};
188pub use self::core::{set_ffmpeg_log_level, FfmpegLogLevel, FFMPEG_LOG_TARGET};
189
190// ez-ffmpeg is a thin FFmpeg wrapper, so FFmpeg's core types appear in the public
191// API by design (e.g. `StreamInfo` carries an `AVCodecID`, an audio stream an
192// `AVChannelOrder`, and a filter's info carries `filter::Flags`). They are
193// re-exported here so downstream code can name them via `ez_ffmpeg::` without a
194// direct `ffmpeg-next` / `ffmpeg-sys-next` dependency (`AVSampleFormat` no longer
195// appears in builder signatures but custom FrameFilters still probe frame formats
196// with it). Feature-specific ecosystem types (`bytes` for `flv`, `bytemuck`/`glow`
197// for the GPU features) are intentionally left exposed to callers already working
198// in those ecosystems.
199pub use ffmpeg_next::filter::Flags as FilterFlags;
200pub use ffmpeg_next::Frame;
201pub use ffmpeg_sys_next::AVChannelOrder;
202pub use ffmpeg_sys_next::AVCodecID;
203pub use ffmpeg_sys_next::AVHWDeviceType;
204pub use ffmpeg_sys_next::AVMediaType;
205pub use ffmpeg_sys_next::AVRational;
206pub use ffmpeg_sys_next::AVSampleFormat;
207
208#[cfg(feature = "opengl")]
209#[deprecated(
210    since = "0.11.0",
211    note = "the OpenGL filter path is superseded by `wgpu_filter` (feature \"wgpu\"): it needs a \
212            display connection and converts colors on the CPU; see the module docs for migration"
213)]
214pub mod opengl;
215#[cfg(feature = "opengl")]
216use surfman::declare_surfman;
217#[cfg(feature = "opengl")]
218declare_surfman!();
219
220#[cfg(feature = "wgpu")]
221pub mod wgpu_filter;
222
223#[cfg(feature = "rtmp")]
224pub mod rtmp;
225
226#[cfg(feature = "flv")]
227pub mod flv;
228
229#[cfg(feature = "subtitle")]
230pub mod subtitle;