28个版本 (7个重大变更)
0.8.1 | 2024年5月14日 |
---|---|
0.7.4 | 2024年4月29日 |
0.7.2 | 2024年3月27日 |
0.5.0 | 2023年11月10日 |
0.1.6 | 2022年11月29日 |
#17 in 视频
2,108次每月下载
在 4 crate中使用
135KB
2.5K SLoC
video-rs
基于ffmpeg的高级别视频工具包。
🎬 简介
video-rs
是一个通用的Rust视频库,它使用来自ffmpeg
的libav
家族库。它旨在提供稳定且Rust风格的接口,用于许多常见的视频任务,如读取、写入、复用、编码和解码。
🛠 状态
⚠️ 此项目仍在开发中,可能包含错误。API的一些部分尚未完全实现。请谨慎使用。
还可以查看我们的其他视频/音频项目rave
。 rave
仍在开发中,但最终目标是取代video-rs
并提供一个无需依赖ffmpeg的完整功能媒体库。
📦 设置
首先,安装ffmpeg
库。ffmpeg-next
项目在这方面有优秀的说明(video-rs
依赖于ffmpeg-next
crate)。
然后,将以下内容添加到您的Cargo.toml
依赖项中
video-rs = "0.8"
使用ndarray
功能来使用原始帧,并使用ndarray
crate
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;
}
}
}
使用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("rainbow.mp4"), 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<u8> {
// This is what generated the rainbow effect! We loop through the HSV color spectrum and convert
// to RGB.
let rgb = hsv_to_rgb(p * 360.0, 100.0, 100.0);
// This creates a frame with height 720, width 1280 and three channels. The RGB values for each
// pixel are equal, and determined by the `rgb` we chose above.
Array3::from_shape_fn((720, 1280, 3), |(_y, _x, c)| rgb[c])
}
fn hsv_to_rgb(h: f32, s: f32, v: f32) -> [u8; 3] {
let s = s / 100.0;
let v = v / 100.0;
let c = s * v;
let x = c * (1.0 - (((h / 60.0) % 2.0) - 1.0).abs());
let m = v - c;
let (r, g, b) = if (0.0..60.0).contains(&h) {
(c, x, 0.0)
} else if (60.0..120.0).contains(&h) {
(x, c, 0.0)
} else if (120.0..180.0).contains(&h) {
(0.0, c, x)
} else if (180.0..240.0).contains(&h) {
(0.0, x, c)
} else if (240.0..300.0).contains(&h) {
(x, 0.0, c)
} else if (300.0..360.0).contains(&h) {
(c, 0.0, x)
} else {
(0.0, 0.0, 0.0)
};
[
((r + m) * 255.0) as u8,
((g + m) * 255.0) as u8,
((b + m) * 255.0) as u8,
]
}
🪲 调试
Ffmpeg并不总是直接产生有用的错误消息。如果您遇到问题,建议开启跟踪以查看日志消息中是否包含额外信息。
将以下包添加到 Cargo.toml
[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"
并在你的主函数中添加以下内容
fn main() {
tracing_subscriber::fmt::init();
// ...
}
设置环境变量 RUST_LOG
以显示跟踪消息
RUST_LOG=video=debug cargo run
✨ 致谢
video-rs
的存在归功于以下组织和人员
- 所有 贡献者 为他们的工作!
- Provincie Utrecht 作为“情境感知软件”项目的一部分支持本项目。
- zmwangx 维护 rust-ffmpeg。
- FFmpeg 项目 为
ffmpeg
和ffmpeg
库。
⚖️ 许可证
在以下许可证中选择一项
- Apache License,版本 2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
贡献
除非你明确声明,否则根据 Apache-2.0 许可证定义的,任何有意提交给工作以包含在你所做的工作中的贡献,都将如上双重许可,不附加任何额外条款或条件。
依赖
~2–5MB
~118K SLoC