Rust FFmpeg绑定库ffmpeg-sys-next的使用,提供跨平台音视频处理与多媒体编解码功能
这是一个被废弃的ffmpeg-sys crate的分支。您可以在crates.io上找到这个crate作为ffmpeg-sys-next。
这个crate包含FFmpeg的低级绑定。您可能对高级绑定感兴趣:ffmpeg-next。
关于版本控制:主要和次要版本跟踪FFmpeg的主要和次要版本,例如,此crate的4.2.x版本已更新以支持FFmpeg的4.2.x系列。补丁级别保留用于此crate的错误修复,不跟踪FFmpeg的补丁版本。
功能标志
除了在Cargo.toml中声明的功能标志外,此crate执行各种编译时版本和功能检测,并在其他标志中公开结果。这些标志简要记录如下;运行cargo build -vv以查看更多详细信息。
-
ffmpeg_<x>_<y>标志(v4.3.2新增),例如ffmpeg_4_4,表示正在编译的FFmpeg安装至少为版本<x>.<y>。当前可用:
- ffmpeg_3_0
- ffmpeg_3_1
- ffmpeg_3_2
- ffmpeg_3_3
- ffmpeg_3_1
- ffmpeg_4_0
- ffmpeg_4_1
- ffmpeg_4_2
- ffmpeg_4_3
- ffmpeg_4_4
-
avcodec_version_greater_than_<x>_<y>(v4.3.2新增),例如,avcodec_version_greater_than_58_90。名称应自解释。
-
ff_api_<feature>,例如ff_api_vaapi,对应于它们各自的大写弃用保护是否评估为真。
-
ff_api_<feature>_is_defined,例如ff_api_vappi_is_defined,类似于上述,但仅在相应的弃用保护已定义时启用。
以下是一个使用ffmpeg-sys-next的基本示例:
use ffmpeg_sys_next::*;
fn main() {
// 初始化FFmpeg库
unsafe {
av_register_all();
}
// 打开输入文件
let mut format_context: *mut AVFormatContext = std::ptr::null_mut();
let filename = std::ffi::CString::new("input.mp4").unwrap();
unsafe {
if avformat_open_input(&mut format_context, filename.as_ptr(), std::ptr::null_mut(), std::ptr::null_mut()) != 0 {
eprintln!("无法打开输入文件");
return;
}
// 获取流信息
if avformat_find_stream_info(format_context, std::ptr::null_mut()) < 0 {
eprintln!("无法获取流信息");
return;
}
// 查找视频流
let mut video_stream_index = -1;
for i in 0..(*format_context).nb_streams {
if (*(*format_context).streams.offset(i as isize)).codecpar().codec_type == AVMEDIA_TYPE_VIDEO {
video_stream_index = i as i32;
break;
}
}
if video_stream_index == -1 {
eprintln!("未找到视频流");
return;
}
println!("成功打开文件并找到视频流");
// 清理资源
avformat_close_input(&mut format_context);
}
}
完整示例代码:
// Cargo.toml
// [dependencies]
// ffmpeg-sys-next = "8.0.0"
use ffmpeg_sys_next::*;
use std::ffi::CString;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化FFmpeg
unsafe {
av_register_all();
}
let filename = "input.mp4";
let c_filename = CString::new(filename)?;
// 打开媒体文件
let mut format_ctx: *mut AVFormatContext = std::ptr::null_mut();
unsafe {
if avformat_open_input(&mut format_ctx, c_filename.as_ptr(), std::ptr::null_mut(), std::ptr::null_mut()) != 0 {
return Err("无法打开输入文件".into());
}
// 获取流信息
if avformat_find_stream_info(format_ctx, std::ptr::null_mut()) < 0 {
avformat_close_input(&mut format_ctx);
return Err("无法获取流信息".into());
}
// 打印媒体信息
av_dump_format(format_ctx, 0, c_filename.as_ptr(), 0);
// 查找视频流
let video_stream_index = find_video_stream(format_ctx);
if video_stream_index == -1 {
avformat_close_input(&mut format_ctx);
return Err("未找到视频流".into());
}
println!("视频流索引: {}", video_stream_index);
// 清理资源
avformat_close_input(&mut format_ctx);
}
Ok(())
}
// 查找视频流
fn find_video_stream(format_ctx: *mut AVFormatContext) -> i32 {
unsafe {
for i in 0..(*format_ctx).nb_streams {
let stream = *(*format_ctx).streams.offset(i as isize);
if (*stream).codecpar.codec_type == AVMEDIA_TYPE_VIDEO {
return i as i32;
}
}
}
-1
}
这个示例演示了如何使用ffmpeg-sys-next打开媒体文件、获取流信息并查找视频流。请注意,使用FFmpeg需要正确处理内存管理和错误处理。
Rust FFmpeg绑定库ffmpeg-sys-next使用指南
概述
ffmpeg-sys-next是Rust语言的FFmpeg绑定库,提供跨平台的音视频处理和多媒体编解码功能。该库为Rust开发者提供了直接访问FFmpeg底层C API的能力,支持音视频解码、编码、转码、过滤等多媒体操作。
安装配置
添加依赖
在Cargo.toml中添加:
[dependencies]
ffmpeg-sys-next = "0.5"
系统依赖
需要先安装FFmpeg开发库:
- Ubuntu/Debian:
sudo apt-get install libavcodec-dev libavformat-dev libavutil-dev
- macOS:
brew install ffmpeg
- Windows: 下载预编译的FFmpeg开发包
基本使用方法
初始化FFmpeg
use ffmpeg_sys_next::*;
fn main() {
unsafe {
avformat_network_init();
}
println!("FFmpeg初始化成功");
}
打开媒体文件
use std::ptr;
use ffmpeg_sys_next::*;
fn open_media_file(path: &str) -> Result<(), String> {
unsafe {
let mut format_context: *mut AVFormatContext = ptr::null_mut();
if avformat_open_input(&mut format_context,
path.as_ptr() as *const i8,
ptr::null_mut(),
ptr::null_mut()) != 0 {
return Err("无法打开媒体文件".to_string());
}
if avformat_find_stream_info(format_context, ptr::null_mut()) < 0 {
return Err("无法获取流信息".to_string());
}
// 处理媒体文件...
avformat_close_input(&mut format_context);
}
Ok(())
}
解码视频帧示例
use ffmpeg_sys_next::*;
use std::ptr;
fn decode_video_frame() {
unsafe {
let codec = avcodec_find_decoder(AVCodecID::AV_CODEC_ID_H264);
if codec.is_null() {
panic!("找不到H264解码器");
}
let codec_context = avcodec_alloc_context3(codec);
if codec_context.is_null() {
panic!("无法分配编解码器上下文");
}
let packet = av_packet_alloc();
let frame = av_frame_alloc();
// 解码逻辑...
av_packet_free(&mut packet);
av_frame_free(&mut frame);
avcodec_free_context(&mut codec_context);
}
}
高级功能
音频重采样
use ffmpeg_sys_next::*;
fn resample_audio() {
unsafe {
let swr_context = swr_alloc();
// 配置重采样参数...
swr_init(swr_context);
// 执行重采样操作...
swr_free(&mut swr_context);
}
}
视频缩放
use ffmpeg_sys_next::*;
fn scale_video() {
unsafe {
let sws_context = sws_getContext(
1920, 1080, AV_PIX_FMT_YUV420P,
1280, 720, AV_PIX_FMT_YUV420P,
SWS_BILINEAR, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()
);
// 执行缩放操作...
sws_freeContext(sws_context);
}
}
完整示例demo
以下是一个完整的媒体文件信息读取示例:
use ffmpeg_sys_next::*;
use std::ffi::CStr;
use std::ptr;
fn main() -> Result<(), String> {
// 初始化FFmpeg网络模块
unsafe {
avformat_network_init();
}
// 打开媒体文件
let file_path = "test.mp4";
let mut format_ctx: *mut AVFormatContext = ptr::null_mut();
unsafe {
// 打开输入文件
if avformat_open_input(
&mut format_ctx,
file_path.as_ptr() as *const i8,
ptr::null_mut(),
ptr::null_mut(),
) != 0
{
return Err("无法打开媒体文件".to_string());
}
// 获取流信息
if avformat_find_stream_info(format_ctx, ptr::null_mut()) < 0 {
avformat_close_input(&mut format_ctx);
return Err("无法获取流信息".to_string());
}
// 打印媒体文件信息
println!("媒体文件信息:");
println!("持续时间: {} 微秒", (*format_ctx).duration);
println!("比特率: {} bps", (*format_ctx).bit_rate);
println!("流数量: {}", (*format_ctx).nb_streams);
// 遍历所有流
for i in 0..(*format_ctx).nb_streams {
let stream = *(*format_ctx).streams.offset(i as isize);
let codec_type = (*stream).codecpar.as_ref().unwrap().codec_type;
match codec_type {
AVMediaType::AVMEDIA_TYPE_VIDEO => {
println!("流 {}: 视频流", i);
let codecpar = (*stream).codecpar.as_ref().unwrap();
println!(" 编码格式: {:?}", codecpar.codec_id);
println!(" 分辨率: {}x{}", codecpar.width, codecpar.height);
}
AVMediaType::AVMEDIA_TYPE_AUDIO => {
println!("流 {}: 音频流", i);
let codecpar = (*stream).codecpar.as_ref().unwrap();
println!(" 编码格式: {:?}", codecpar.codec_id);
println!(" 采样率: {}", codecpar.sample_rate);
println!(" 声道数: {}", codecpar.channels);
}
_ => println!("流 {}: 其他类型流", i),
}
}
// 清理资源
avformat_close_input(&mut format_ctx);
}
println!("媒体文件处理完成");
Ok(())
}
注意事项
- 内存安全: 由于直接调用C库,需要特别注意内存管理和空指针检查
- 错误处理: 所有FFmpeg函数都应检查返回值
- 线程安全: FFmpeg某些函数不是线程安全的,需要注意同步
- 资源释放: 确保正确释放所有分配的资源
跨平台支持
ffmpeg-sys-next支持Windows、Linux、macOS等主流平台,但需要确保目标系统已安装相应版本的FFmpeg开发库。
这个绑定库为Rust开发者提供了强大的多媒体处理能力,适合开发音视频处理工具、媒体服务器、转码工具等应用。