Skip to main content

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};