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