You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust中将视频帧(&[u8])编码为MP4视频求技术指导

解决FFmpeg相关Rust crate编译问题 + ffav-rs转MP4实操

先搞定编译失败的问题

绝大多数Rust的FFmpeg绑定 crate(包括ffav-rs)都依赖系统已安装的FFmpeg开发库,编译失败大概率是没装或者cargo找不到。按你的系统来:

  • Ubuntu/Debian:
    sudo apt-get install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
    
  • macOS:
    brew install ffmpeg
    
  • Windows:
    用vcpkg安装ffmpeg:x64-windows-static,然后设置环境变量:
    set VCPKG_ROOT=C:\path\to\vcpkg
    set PATH=%VCPKG_ROOT%\installed\x64-windows-static\bin;%PATH%
    
    也可以直接在Cargo.toml里指定库路径:
    [dependencies.ffav-rs]
    version = "0.10"
    features = ["buildtime-bindgen"]
    

ffav-rs 转MP4的实操代码

假设你的输入帧是RGB24格式(其他格式只需调整对应像素格式),以下是完整示例流程:

1. 依赖配置

Cargo.toml中添加:

[dependencies]
ffav-rs = "0.10"
image = "0.24" # 可选,仅用于生成测试RGB帧

2. 核心代码

use ffav_rs::{
    format::{io::IoContext, muxer::Muxer, OutputFormat},
    codec::{
        encoder::Encoder,
        pixel_format::PixelFormat,
        video::{VideoFrame, VideoParameters},
    },
    util::frame::Frame,
};
use std::fs::File;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 初始化输出文件与复用器
    let file = File::create("output.mp4")?;
    let io_ctx = IoContext::from_writer(file);
    let output_format = OutputFormat::guess("output.mp4", None, None)?;
    let mut muxer = Muxer::new(io_ctx, output_format)?;

    // 2. 设置视频流参数(根据实际帧尺寸、帧率调整)
    let width = 1920;
    let height = 1080;
    let fps = 30;
    let mut video_params = VideoParameters::new(width, height, PixelFormat::YUV420P)?;
    video_params.set_time_base((1, fps))?;
    video_params.set_frame_rate((fps, 1))?;

    // 3. 查找并打开H.264编码器
    let encoder = Encoder::find_by_name("libx264")?;
    let mut video_encoder = encoder.open_as_video(video_params)?;
    let mut stream = muxer.add_stream(Some(&video_encoder))?;

    // 4. 写入文件头
    muxer.write_header()?;

    // 5. 处理帧(替换成你的&[u8]帧数据)
    // 这里用模拟的RGB帧示例,实际中替换为你的帧数据
    let rgb_frame_data = vec![255u8; width * height * 3]; // 纯红测试帧
    let mut rgb_frame = VideoFrame::new(PixelFormat::RGB24, width, height)?;
    rgb_frame.copy_from_slice(&rgb_frame_data)?;

    // 6. RGB转YUV(编码器普遍要求YUV格式)
    let mut yuv_frame = VideoFrame::new(PixelFormat::YUV420P, width, height)?;
    let sws_ctx = ffav_rs::util::swscale::Context::new(
        width, height, PixelFormat::RGB24,
        width, height, PixelFormat::YUV420P,
        ffav_rs::util::swscale::Flags::BILINEAR,
    )?;
    sws_ctx.scale(&rgb_frame, &mut yuv_frame)?;

    // 7. 编码并写入帧
    yuv_frame.set_pts(0); // 按帧率递增设置显示时间戳
    if let Some(mut pkt) = video_encoder.encode(&yuv_frame)? {
        pkt.stream_index = stream.index();
        pkt.rescale_ts(video_encoder.time_base(), stream.time_base())?;
        muxer.write_packet(&pkt)?;
    }

    // 8. 刷新编码器,写入剩余数据包
    while let Some(mut pkt) = video_encoder.encode(None)? {
        pkt.stream_index = stream.index();
        pkt.rescale_ts(video_encoder.time_base(), stream.time_base())?;
        muxer.write_packet(&pkt)?;
    }

    // 9. 写入文件尾
    muxer.write_trailer()?;

    Ok(())
}

关键注意点

  • 若输入帧已是YUV格式,跳过RGB转YUV步骤,直接指定对应PixelFormat
  • 帧的时间戳(pts)必须按帧率正确递增,否则视频播放会出现卡顿/跳帧
  • 可调整编码器参数优化输出,比如给libx264设置码率或质量:
    video_encoder.set_bit_rate(5_000_000)?; // 5Mbps码率
    video_encoder.set_option("crf", "23")?; // CRF值越小,视频质量越高
    

内容的提问来源于stack exchange,提问作者radstevee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 20:44:51