video-rs 开源项目教程
项目介绍
video-rs
是一个基于 ffmpeg
的 Rust 视频处理库。它旨在提供一个稳定且符合 Rust 风格的接口,用于处理常见的视频任务,如读取、写入、编码和解码。该项目目前仍在开发中,部分 API 可能尚未完全稳定,使用时需谨慎。
项目快速启动
安装依赖
首先,确保你已经安装了 ffmpeg
库。video-rs
依赖于 ffmpeg-next
crate,你可以参考其提供的安装指南。
添加依赖
在你的 Cargo.toml
文件中添加以下依赖:
[dependencies]
video-rs = "0.8"
如果你需要使用 ndarray
crate 处理原始帧,可以启用 ndarray
特性:
[dependencies]
video-rs = { version = "0.8", features = ["ndarray"] }
示例代码
以下是一个简单的示例,展示如何解码一个视频并打印左上角像素的 RGB 值:
use video_rs::decode::Decoder;
use video_rs::Url;
fn main() {
video_rs::init().unwrap();
let source = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4".parse::<Url>().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;
}
}
}
应用案例和最佳实践
视频解码
使用 video-rs
可以轻松解码视频文件并处理每一帧。以下是一个完整的示例,展示如何解码视频并保存每一帧为图像文件:
use video_rs::decode::Decoder;
use video_rs::Url;
use image::{DynamicImage, ImageBuffer, Rgb};
use std::path::Path;
fn main() {
video_rs::init().unwrap();
let source = "path/to/your/video.mp4".parse::<Url>().unwrap();
let mut decoder = Decoder::new(source).expect("failed to create decoder");
let mut frame_count = 0;
for frame in decoder.decode_iter() {
if let Ok((_frame)) = frame {
let rgb = _frame.to_owned();
let img = DynamicImage::ImageRgb8(ImageBuffer::from_raw(rgb.width() as u32, rgb.height() as u32, rgb.into_raw()).unwrap());
img.save(Path::new(&format!("frame_{}.png", frame_count))).unwrap();
frame_count += 1;
} else {
break;
}
}
}
视频编码
使用 video-rs
编码视频同样简单。以下是一个示例,展示如何使用 ndarray
创建每一帧并编码为视频:
use std::path::Path;
use ndarray::Array3;
use video_rs::encode::{Encoder, Settings};
use video_rs::time::Time;
fn main() {
video_rs::init().unwrap();
let settings = Settings::preset_h264_yuv420p(1280, 720, false);
let mut encoder = Encoder::new(Path::new("output.mp4"), settings).expect("failed to create encoder");
for i in 0..100 {
let mut frame = Array3::<u8>::zeros((720, 1280, 3));
// 填充帧数据
encoder.encode(&frame, Time::from_secs(i)).unwrap();
}
encoder.finish().unwrap();
}