1个不稳定版本
0.4.1 | 2023年11月29日 |
---|
#351 在 视频
33 每月下载量
在 3 个组件(2直接)中使用
125KB
2K SLoC
video-rs
基于ffmpeg的高级视频工具包。
🎬 简介
video-rs
是一个通用的Rust视频库,它使用了来自 ffmpeg
的 libav
家族库。它的目标是提供一个稳定且Rust风格的接口,用于许多常见的视频任务,如读取、写入、复用、编码和解码。
🛠 状态
⚠️ 此项目仍在进行中,可能包含错误。API的一些部分尚未完善。请谨慎使用。
还可以查看我们的其他视频/音频项目 rave
。 rave
仍在开发中,但其最终目标是取代 video-rs
并提供一个功能齐全的媒体库,而不依赖于ffmpeg。
📦 设置
首先,安装 ffmpeg
库。 ffmpeg-next
项目在这方面有出色的说明(video-rs
依赖于 ffmpeg-next
包)。
然后,将以下内容添加到您的 Cargo.toml
依赖项中
video-rs = "0.4"
使用 ndarray
功能来使用原始帧与 ndarray
包
video-rs = { version = "0.4", features = ["ndarray"] }
📖 示例
解码视频并打印左上角的RGB值
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;
}
}
}
使用 ndarray
创建每个帧来编码 🌈 视频
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<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许可证,版本2.0(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或http://opensource.org/licenses/MIT)
任选其一。
贡献
除非你明确表示,否则根据Apache-2.0许可证定义的,任何有意提交以包含在作品中的贡献,都应按照上述方式双许可,而不附加任何额外条款或条件。
依赖项
~2–5MB
~118K SLoC