#ffmpeg #video #frame #binary #iterator #standalone #interface

bin+lib ffmpeg-sidecar

将独立的 FFmpeg 二进制文件包裹在直观的 Iterator 接口内

14 个版本 (3 个稳定版)

1.1.0 2024 年 4 月 14 日
1.0.1 2024 年 2 月 23 日
0.5.1 2023 年 10 月 13 日
0.4.1 2023 年 4 月 26 日
0.1.0 2023 年 2 月 15 日

#7多媒体 类别中

Download history 151/week @ 2024-04-29 229/week @ 2024-05-06 148/week @ 2024-05-13 212/week @ 2024-05-20 217/week @ 2024-05-27 273/week @ 2024-06-03 280/week @ 2024-06-10 250/week @ 2024-06-17 242/week @ 2024-06-24 240/week @ 2024-07-01 149/week @ 2024-07-08 246/week @ 2024-07-15 207/week @ 2024-07-22 264/week @ 2024-07-29 209/week @ 2024-08-05 190/week @ 2024-08-12

每月下载量 887
4 个 Crates 使用(其中 3 个直接使用)

MIT 许可证

110KB
2K SLoC

FFmpeg Sidecar 🏍

Github | Crates.io | Docs.rs

将独立的 FFmpeg 二进制文件包裹在直观的 Iterator 接口内。

特性

  • ✨ 最小化依赖
  • ⚡ 自动下载 FFmpeg CLI(如果需要)
  • 🤗 支持 Windows、MacOS 和 Linux
  • 🧪 详尽的单元测试

👉 跳转到 入门指南 👈

动机

本项目的核心目标是提供一种方法,可以将任何视频 视为一组原始 RGB 帧数组

当然,从本质上讲,视频就是这样,但在到达那里之前,接收和解析视频涉及到的复杂性就像潘多拉的盒子一样。

使用 FFmpeg 作为核心引擎提供了与大量格式、容器、扩展、协议、编码器、解码器、硬件加速等之间的互操作性。

为什么使用 CLI?

使用 FFmpeg 的方法之一是将其 CLI 内部的代码进行低级绑定 -- Rust 生态系统中有一些 优秀的 Crates 可以做到这一点。

低级绑定有一些缺点

  • 构建、工具链和依赖关系困难、耗时,尤其是在 Windows 上
  • 复杂性,特别是对于初学者来说
  • 您需要从头开始手动实现许多标准转换

通过封装 CLI,这个 Crates 避免了这些缺点,并解决了一些在使用 CLI 时可能会遇到的问题

  • 原始数据可以轻松地进出 FFmpeg 实例,或者在它们之间进行管道传输。在底层,它们通过 stdin 和 stdout 传输。
  • 从 FFmpeg 的 stderr 日志中恢复丰富的语义信息,包括
    • 进度更新(帧号、时间戳、速度、比特率等)
    • 输入/输出元数据和流映射
    • 警告和错误
  • 参数预设和可通过Intellisense/自动完成发现的别名

唯一的缺点是FFmpeg二进制文件的大小,但压缩后不到100MB。它可以通过crate自动下载,因此您可以选择不在自己的应用程序中包含它,而是在运行时下载。

入门

1. Cargo 安装

cargo add ffmpeg-sidecar

2. 下载FFmpeg

要在您的平台(Windows、MacOS和Linux)上自动下载和安装FFmpeg二进制文件,请在任何地方调用此函数

ffmpeg_sidecar::download::auto_download().unwrap();

您只需这样做一次来设置您的开发环境,或者将其作为客户端应用程序的一个功能。

要自定义或扩展下载,请参阅 /examples/download_ffmpeg.rs

示例

你好世界 👋

读取原始视频帧。

use ffmpeg_sidecar::{command::FfmpegCommand, event::FfmpegEvent};

fn main() -> anyhow::Result<()> { 
  FfmpegCommand::new() // <- Builder API like `std::process::Command`
    .testsrc()  // <- Discoverable aliases for FFmpeg args
    .rawvideo() // <- Convenient argument presets
    .spawn()?   // <- Uses an ordinary `std::process::Child`
    .iter()?    // <- Iterator over all log messages and video output
    .for_each(|event: FfmpegEvent| {
      match event {
        FfmpegEvent::OutputFrame(frame) => {
          println!("frame: {}x{}", frame.width, frame.height);
          let _pixels: Vec<u8> = frame.data; // <- raw RGB pixels! 🎨
        }
        FfmpegEvent::Progress(progress) => {
          eprintln!("Current speed: {}x", progress.speed); // <- parsed progress updates
        }
        FfmpegEvent::Log(_level, msg) => {
          eprintln!("[ffmpeg] {}", msg); // <- granular log message from stderr
        }
        _ => {}
      }
    });
  Ok(())
}

来源: /examples/hello_world.rs

cargo run --example hello-world

H265转码

解码H265,修改解码的帧,然后写回H265。

来源: /examples/h265_transcode.rs

cargo run --example h265_transcode

FFplay

将FFmpeg实例通过FFplay进行调试。

来源: /examples/ffplay_preview.rs

cargo run --example ffplay_preview

其他

有关其他大量示例,请查看本存储库中 /src/test.rs 中的任何单元测试。

待办事项

  • 添加 /examples
  • 从stdin接收输入,并在迭代器之间进行管道传输
  • 直接将数据传输到 ffplay 以进行调试
  • 使用惯用错误类型而不是 Result<_, String>
  • 处理不确定的输出格式,如H264/H265
    • 由于这些格式需要直接消耗 stdout,因此在使用 iter() 时相互排斥

另请参阅

受Node.js fluent-ffmpeg 的启发,它在JavaScript中执行类似操作。

使用 setup-ffmpeg 进行Github Actions,并作为自动下载行为的参考。

📣 欢迎拉取请求 📣

依赖关系

~130KB