ff_encode/lib.rs
1//! # ff-encode
2//!
3//! Video and audio encoding - the Rust way.
4
5// FFmpeg binding requires unsafe code for C API calls
6#![allow(unsafe_code)]
7// Raw pointer operations are necessary for FFmpeg C API
8#![allow(clippy::borrow_as_ptr)]
9#![allow(clippy::ptr_as_ptr)]
10#![allow(clippy::ref_as_ptr)]
11#![allow(clippy::unnecessary_safety_doc)]
12// Casting between C and Rust types
13#![allow(clippy::cast_possible_wrap)]
14#![allow(clippy::cast_possible_truncation)]
15#![allow(clippy::cast_sign_loss)]
16// C string literals
17#![allow(clippy::manual_c_str_literals)]
18// Code structure warnings
19#![allow(clippy::too_many_arguments)]
20#![allow(clippy::single_match_else)]
21#![allow(clippy::inefficient_to_string)]
22#![allow(clippy::trivially_copy_pass_by_ref)]
23#![allow(clippy::doc_markdown)]
24#![allow(clippy::needless_pass_by_value)]
25#![allow(clippy::assigning_clones)]
26#![allow(clippy::unused_self)]
27#![allow(clippy::unnecessary_safety_comment)]
28//!
29//! This crate provides video and audio encoding functionality for timeline export.
30//! It supports automatic codec selection with LGPL compliance, hardware acceleration,
31//! and provides a clean Builder pattern API.
32//!
33//! ## Features
34//!
35//! - **Video Encoding**: H.264, H.265, VP9, AV1, `ProRes`, `DNxHD`
36//! - **Audio Encoding**: AAC, Opus, MP3, FLAC, PCM, Vorbis
37//! - **Hardware Acceleration**: NVENC, QSV, AMF, `VideoToolbox`, VA-API
38//! - **LGPL Compliance**: Automatic codec fallback when GPL features disabled
39//! - **Progress Callbacks**: Real-time encoding progress updates
40//! - **Builder Pattern**: Ergonomic encoder configuration
41//!
42//! ## Usage
43//!
44//! ### Basic Encoding
45//!
46//! ```ignore
47//! use ff_encode::{VideoEncoder, VideoCodec, AudioCodec, BitrateMode, Preset};
48//! use ff_format::VideoFrame;
49//!
50//! // Create encoder with Builder pattern
51//! let mut encoder = VideoEncoder::create("output.mp4")?
52//! .video(1920, 1080, 30.0) // resolution, FPS
53//! .video_codec(VideoCodec::H264) // codec
54//! .bitrate_mode(BitrateMode::Cbr(8_000_000)) // 8 Mbps
55//! .preset(Preset::Medium) // speed/quality balance
56//! .audio(48000, 2) // sample rate, channels
57//! .audio_codec(AudioCodec::Aac)
58//! .audio_bitrate(192_000) // 192 kbps
59//! .build()?;
60//!
61//! // Check actual codec used
62//! println!("Video codec: {}", encoder.actual_video_codec());
63//! println!("Audio codec: {}", encoder.actual_audio_codec());
64//!
65//! // Push frames
66//! for frame in frames {
67//! encoder.push_video(&frame)?;
68//! }
69//!
70//! // Push audio
71//! encoder.push_audio(&audio_samples)?;
72//!
73//! // Finish encoding
74//! encoder.finish()?;
75//! ```
76//!
77//! ### Progress Callbacks
78//!
79//! ```ignore
80//! use ff_encode::{VideoEncoder, Progress};
81//!
82//! // Simple closure-based callback
83//! let mut encoder = VideoEncoder::create("output.mp4")?
84//! .video(1920, 1080, 30.0)
85//! .on_progress(|progress| {
86//! println!("Encoded {} frames ({:.1}%) at {:.1} fps",
87//! progress.frames_encoded,
88//! progress.percent(),
89//! progress.current_fps
90//! );
91//! })
92//! .build()?;
93//! ```
94//!
95//! ### Progress Callbacks with Cancellation
96//!
97//! ```ignore
98//! use ff_encode::{VideoEncoder, ProgressCallback, Progress};
99//! use std::sync::Arc;
100//! use std::sync::atomic::{AtomicBool, Ordering};
101//!
102//! struct CancellableProgress {
103//! cancelled: Arc<AtomicBool>,
104//! }
105//!
106//! impl ProgressCallback for CancellableProgress {
107//! fn on_progress(&mut self, progress: &Progress) {
108//! println!("Progress: {:.1}%", progress.percent());
109//! }
110//!
111//! fn should_cancel(&self) -> bool {
112//! self.cancelled.load(Ordering::Relaxed)
113//! }
114//! }
115//!
116//! let cancelled = Arc::new(AtomicBool::new(false));
117//! let mut encoder = VideoEncoder::create("output.mp4")?
118//! .video(1920, 1080, 30.0)
119//! .progress_callback(CancellableProgress {
120//! cancelled: cancelled.clone()
121//! })
122//! .build()?;
123//!
124//! // Later, to cancel encoding:
125//! cancelled.store(true, Ordering::Relaxed);
126//! ```
127//!
128//! ### Hardware Encoding
129//!
130//! ```ignore
131//! use ff_encode::{VideoEncoder, HardwareEncoder};
132//!
133//! // Check available hardware encoders
134//! for hw in HardwareEncoder::available() {
135//! println!("Available: {:?}", hw);
136//! }
137//!
138//! // Create encoder with auto hardware detection
139//! let mut encoder = VideoEncoder::create("output.mp4")?
140//! .video(1920, 1080, 60.0)
141//! .hardware_encoder(HardwareEncoder::Auto) // auto-detect
142//! .build()?;
143//!
144//! // Check what encoder was actually used
145//! println!("Using: {}", encoder.actual_video_codec());
146//! println!("Hardware encoder: {:?}", encoder.hardware_encoder());
147//! println!("Is hardware encoding: {}", encoder.is_hardware_encoding());
148//! ```
149//!
150//! ## LGPL Compliance & Commercial Use
151//!
152//! **By default, this crate is LGPL-compliant and safe for commercial use without licensing fees.**
153//!
154//! ### Default Behavior (LGPL-Compatible)
155//!
156//! When H.264/H.265 encoding is requested, the encoder automatically selects codecs in this priority:
157//!
158//! 1. **Hardware encoders** (LGPL-compatible, no licensing fees):
159//! - NVIDIA NVENC (h264_nvenc, hevc_nvenc)
160//! - Intel Quick Sync Video (h264_qsv, hevc_qsv)
161//! - AMD AMF/VCE (h264_amf, hevc_amf)
162//! - Apple VideoToolbox (h264_videotoolbox, hevc_videotoolbox)
163//! - VA-API (h264_vaapi, hevc_vaapi) - Linux
164//!
165//! 2. **Fallback to royalty-free codecs**:
166//! - For H.264 request → VP9 (libvpx-vp9)
167//! - For H.265 request → AV1 (libaom-av1)
168//!
169//! ### GPL Feature (Commercial Licensing Required)
170//!
171//! Enable GPL codecs (libx264, libx265) only if:
172//! - You have appropriate licenses from MPEG LA, or
173//! - Your software is GPL-licensed (open source), or
174//! - For non-commercial/educational use only
175//!
176//! ```toml
177//! # WARNING: Requires GPL compliance and licensing fees for commercial use
178//! ff-encode = { version = "0.1", features = ["gpl"] }
179//! ```
180//!
181//! ### Checking Compliance at Runtime
182//!
183//! You can verify which encoder was selected:
184//!
185//! ```ignore
186//! let encoder = VideoEncoder::create("output.mp4")?
187//! .video(1920, 1080, 30.0)
188//! .video_codec(VideoCodec::H264)
189//! .build()?;
190//!
191//! println!("Using: {}", encoder.actual_video_codec());
192//! println!("LGPL compliant: {}", encoder.is_lgpl_compliant());
193//! ```
194
195mod audio;
196mod bitrate;
197mod codec;
198mod container;
199mod error;
200mod hardware;
201mod image;
202mod preset;
203mod progress;
204mod video;
205
206pub use audio::{AudioEncoder, AudioEncoderBuilder};
207pub use bitrate::{BitrateMode, CRF_MAX};
208pub use codec::{AudioCodec, VideoCodec};
209pub use container::Container;
210pub use error::EncodeError;
211pub use hardware::HardwareEncoder;
212pub use image::{ImageEncoder, ImageEncoderBuilder};
213pub use preset::Preset;
214pub use progress::{Progress, ProgressCallback};
215pub use video::{VideoEncoder, VideoEncoderBuilder};