video-rs
High-level video toolkit based on ffmpeg.
## 🎬 Introduction `video-rs` is a general-purpose video library for Rust that uses the `libav`-family libraries from `ffmpeg`. It aims to provide a stable and Rusty interface to many common video tasks such as reading, writing, muxing, encoding and decoding. ## 🛠 S️️tatus ⚠️ This project is still a work-in-progress, and will contain bugs. Some parts of the API have not been flushed out yet. Use with caution. Also check out our other video/audio project [`rave`](https://github.com/oddity-ai/rave). `rave` is still in development, but its eventual goal is to replace `video-rs` and provide a fully featured media library without depending on ffmpeg. ## 📦 Setup First, install the `ffmpeg` libraries. The `ffmpeg-next` project has [excellent instructions](https://github.com/zmwangx/rust-ffmpeg/wiki/Notes-on-building#dependencies) on this (`video-rs` depends on the `ffmpeg-next` crate). Then, add the following to your dependencies in `Cargo.toml`: ```toml video-rs = "0.4" ``` Use the `ndarray` feature to be able to use raw frames with the [`ndarray`](https://github.com/rust-ndarray/ndarray) crate: ```toml video-rs = { version = "0.4", features = ["ndarray"] } ``` ## 📖 Examples Decode a video and print the RGB value for the top left pixel: ```rust use video_rs::{self, Decoder, Locator}; fn main() { video_rs::init().unwrap(); let source = Locator::Url( "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" .parse() .unwrap(), ); let mut decoder = Decoder::new(&source) .expect("failed to create decoder"); for frame in decoder.decode_iter() { if let Ok((_, frame)) = frame { let rgb = frame .slice(ndarray::s![0, 0, ..]) .to_slice() .unwrap(); println!( "pixel at 0, 0: {}, {}, {}", rgb[0], rgb[1], rgb[2], ); } else { break; } } } ``` Encode a 🌈 video, using `ndarray` to create each frame: ```rust use std::path::PathBuf; use ndarray::Array3; use video_rs::{Encoder, EncoderSettings, Locator, Time}; fn main() { video_rs::init().unwrap(); let destination: Locator = PathBuf::from("rainbow.mp4").into(); let settings = EncoderSettings::for_h264_yuv420p(1280, 720, false); let mut encoder = Encoder::new(&destination, settings) .expect("failed to create encoder"); let duration: Time = Time::from_nth_of_a_second(24); let mut position = Time::zero(); for i in 0..256 { // This will create a smooth rainbow animation video! let frame = rainbow_frame(i as f32 / 256.0); encoder .encode(&frame, &position) .expect("failed to encode frame"); // Update the current position and add the inter-frame // duration to it. position = position.aligned_with(&duration).add(); } encoder.finish().expect("failed to finish encoder"); } fn rainbow_frame(p: f32) -> Array3