🍣
Rustでffmpegを使って動画の情報を得る
目的
動画の再生時間やら諸々の情報を知りたいです。Rustでffmpegを使って調べてみます。
ffmpegのインストール
Ubuntu24.04にffmpegをインストールします。現在最新の8.0をインストールしたいので以下のサイトを参考に入れてみます。
Install FFmpeg (8.0 Updated) via PPA in Ubuntu 22.04 | Ubuntu 24.04
sudo add-apt-repository ppa:ubuntuhandbook1/ffmpeg8
sudo apt update
sudo apt install libavutil-dev libavformat-dev libavfilter-dev libavcodec-dev ffmpeg
ffmpeg以外はビルドした時に要求されたので追加しています。
コード
Cargo.toml
[package]
name = "samples"
version = "0.1.0"
edition = "2024"
[dependencies]
ffmpeg-next = "8.0.0"
main.rs
use ffmpeg_next::format;
fn main() {
let format_context = format::input("samples/sample.mp4").unwrap();
println!("BitRate: {}", format_context.bit_rate());
println!("Number of chapters: {}", format_context.chapters().len());
println!("Number of streams: {}", format_context.streams().len());
let duration = format_context.duration();
println!("Duration: {} microseconds", duration);
let format = format_context.format();
println!("Format name: {}", format.name());
println!("Format description: {}", format.description());
println!("Format extentions: {:?}", format.extensions());
println!("Format mime types: {:?}", format.mime_types());
let metadata = format_context.metadata();
for (key, value) in metadata.iter() {
println!("Metadata: {}: {}", key, value);
}
for stream in format_context.streams() {
println!("Stream {}:", stream.index());
println!(" Time Base: {}/{}", stream.time_base().numerator(), stream.time_base().denominator());
println!(" Duration: {}", stream.duration());
println!(" Frames: {}", stream.frames());
println!(" Rate: {}", stream.rate());
println!(" Disposition: {:?}", stream.disposition());
println!(" Avg Frame Rate: {:?}", stream.avg_frame_rate());
println!(" Start Time: {}", stream.start_time());
println!(" Discard: {:?}", stream.discard());
for (key, value) in stream.metadata().iter() {
println!(" Metadata: {}: {}", key, value);
}
let parameters = stream.parameters();
println!(" Codec ID Name: {}", parameters.id().name());
println!(" Codec Type: {:?}", parameters.medium());
let width = unsafe { parameters.as_ptr().as_ref().and_then(|p| Some(p.width)).unwrap_or(0) };
println!(" Width: {}", width);
let height = unsafe { parameters.as_ptr().as_ref().and_then(|p| Some(p.height)).unwrap_or(0) };
println!(" Height: {}", height);
let bit_rate = unsafe { parameters.as_ptr().as_ref().and_then(|p| Some(p.bit_rate)).unwrap_or(0) };
println!(" Bit Rate: {}", bit_rate);
let pixel_format = unsafe { parameters.as_ptr().as_ref().and_then(|p| Some(p.format)).unwrap_or(-1) };
println!(" Pixel Format: {}", pixel_format);
let side_data_iter = stream.side_data();
for side_data in side_data_iter {
println!(" Side Data Type: {:?}", side_data.kind());
}
};
}
結果
BitRate: 20211358
Number of chapters: 0
Number of streams: 3
Duration: 5366833 microseconds
Format name: mov,mp4,m4a,3gp,3g2,mj2
Format description: QuickTime / MOV
Format extentions: ["mov", "mp4", "m4a", "3gp", "3g2", "mj2", "psp", "m4b", "ism", "ismv", "isma", "f4v", "avif", "heic", "heif"]
Format mime types: []
Metadata: major_brand: isom
Metadata: minor_version: 131072
Metadata: compatible_brands: isomiso2mp41
Metadata: creation_time: 2025-11-25T22:41:36.000000Z
Metadata: location: +35.6878+139.7033/
Metadata: location-eng: +35.6878+139.7033/
Metadata: com.android.capture.fps: 30.000000
Metadata: com.android.model: Pixel 8
Metadata: com.android.manufacturer: Google
Stream 0:
Time Base: 1/90000
Duration: 483015
Frames: 161
Rate: 30/1
Disposition: Disposition(DEFAULT)
Avg Frame Rate: Rational(966000/32201)
Start Time: 0
Discard: Default
Metadata: creation_time: 2025-11-25T22:41:36.000000Z
Metadata: language: eng
Metadata: handler_name: VideoHandle
Metadata: vendor_id: [0][0][0][0]
Codec ID Name: hevc
Codec Type: Video
Width: 1920
Height: 1080
Bit Rate: 19953549
Pixel Format: 12
Side Data Type: DisplayMatrix
Stream 1:
Time Base: 1/48000
Duration: 256084
Frames: 250
Rate: 0/0
Disposition: Disposition(DEFAULT)
Avg Frame Rate: Rational(0/0)
Start Time: 878
Discard: Default
Metadata: creation_time: 2025-11-25T22:41:36.000000Z
Metadata: language: eng
Metadata: handler_name: SoundHandle
Metadata: vendor_id: [0][0][0][0]
Codec ID Name: aac
Codec Type: Audio
Width: 0
Height: 0
Bit Rate: 192184
Pixel Format: 8
Stream 2:
Time Base: 1/90000
Duration: 483015
Frames: 161
Rate: 0/0
Disposition: Disposition(DEFAULT)
Avg Frame Rate: Rational(0/0)
Start Time: 0
Discard: Default
Metadata: creation_time: 2025-11-25T22:41:36.000000Z
Metadata: language: eng
Metadata: handler_name: MetaHandle
Codec ID Name: none
Codec Type: Data
Width: 0
Height: 0
Bit Rate: 50162
Pixel Format: -1
まとめ
正直データが生すぎて使いにくいですね。unsafeなんていちいち書かなくて済むようなstructを作って欲しいです。
ffmpeg-nextをラップしたライブラリはいくつかあるんですが、8.0に対応してくれて無いので待ってます。
Discussion