Initial commit: Video analyzer with ffmpeg-next
This commit is contained in:
11
.cargo/config.toml
Normal file
11
.cargo/config.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = [
|
||||
"-L", "/opt/homebrew/lib",
|
||||
"-l", "c++"
|
||||
]
|
||||
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = [
|
||||
"-L", "/usr/local/lib",
|
||||
"-l", "c++"
|
||||
]
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/target/
|
||||
*.rs.bk
|
||||
.DS_Store
|
||||
test.mp4
|
||||
279
Cargo.lock
generated
Normal file
279
Cargo.lock
generated
Normal file
@@ -0,0 +1,279 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.72.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "ffmpeg-next"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d658424d233cbd993a972dd73a66ca733acd12a494c68995c9ac32ae1fe65b40"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"ffmpeg-sys-next",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ffmpeg-sys-next"
|
||||
version = "8.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bca20aa4ee774fe384c2490096c122b0b23cf524a9910add0686691003d797b"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
"libc",
|
||||
"num_cpus",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.182"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "video_analyzer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ffmpeg-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "video_analyzer"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
# 啟用 "static" feature 進行靜態編譯
|
||||
# 注意:版本號可能需要根據實際情況調整,目前推薦使用 7.0 或最新版本
|
||||
ffmpeg-next = { version = "8.0", features = ["static"] }
|
||||
|
||||
# [可選] 如果你希望進一步減小體積或指定編譯選項,可以添加 build-dependencies
|
||||
# 但通常 ffmpeg-next 的 static feature 會自動處理大部分事情
|
||||
14
README.md
14
README.md
@@ -0,0 +1,14 @@
|
||||
# Video Analyzer
|
||||
|
||||
A Rust-based tool to analyze video file metadata using FFmpeg.
|
||||
|
||||
## Features
|
||||
- Extract video format, resolution, duration
|
||||
- Analyze audio streams (sample rate, channels)
|
||||
- Static/Dynamic linking support
|
||||
|
||||
## Usage
|
||||
```bash
|
||||
cargo build --release
|
||||
./target/release/video_analyzer <video_file>
|
||||
```
|
||||
|
||||
135
src/main.rs
Normal file
135
src/main.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
use ffmpeg_next as ffmpeg;
|
||||
use ffmpeg::format::{input, Pixel};
|
||||
use ffmpeg::media::Type;
|
||||
use ffmpeg::codec::{context::Context, decoder};
|
||||
use std::path::Path;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
ffmpeg::init()?;
|
||||
|
||||
let input_path = "test.mp4";
|
||||
|
||||
if !Path::new(input_path).exists() {
|
||||
eprintln!("錯誤:找不到檔案 '{}'", input_path);
|
||||
eprintln!("請將一個視頻文件重命名為 'test.mp4' 並放在專案根目錄。");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ictx = input(&input_path)?;
|
||||
|
||||
println!("=== 檔案基本資訊 ===");
|
||||
println!("格式名稱 (Format): {}", ictx.format().name());
|
||||
println!("長描述: {}", ictx.format().description());
|
||||
|
||||
let duration_sec = ictx.duration() as f64 / ffmpeg::ffi::AV_TIME_BASE as f64;
|
||||
println!("總長度 (Duration): {:.2} 秒", duration_sec);
|
||||
|
||||
println!("\n=== 串流資訊 ===");
|
||||
|
||||
for (index, stream) in ictx.streams().enumerate() {
|
||||
let codec_params = stream.parameters();
|
||||
let codec_id = codec_params.id();
|
||||
let media_type = codec_params.medium();
|
||||
|
||||
println!("[串流 #{}]", index);
|
||||
println!(" 類型: {:?}", media_type);
|
||||
println!(" 編碼器 ID: {:?}", codec_id);
|
||||
|
||||
if let Some(codec_descriptor) = decoder::find(codec_id) {
|
||||
let mut context = Context::new_with_codec(codec_descriptor);
|
||||
|
||||
if let Err(e) = context.set_parameters(codec_params) {
|
||||
eprintln!(" 警告:無法設置參數: {}", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let ptr = context.as_mut_ptr();
|
||||
|
||||
match media_type {
|
||||
Type::Video => {
|
||||
let width = (*ptr).width;
|
||||
let height = (*ptr).height;
|
||||
let pix_fmt_val = (*ptr).pix_fmt;
|
||||
let format = Pixel::from(pix_fmt_val);
|
||||
|
||||
let frame_rate = stream.avg_frame_rate();
|
||||
let fps = if frame_rate.numerator() != 0 {
|
||||
frame_rate.numerator() as f64 / frame_rate.denominator() as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
println!(" 解析度: {}x{}", width, height);
|
||||
println!(" 像素格式: {:?}", format);
|
||||
println!(" 幀率: {:.2} fps", fps);
|
||||
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
},
|
||||
Type::Audio => {
|
||||
let sample_rate = (*ptr).sample_rate;
|
||||
|
||||
// 【關鍵修復】新版本使用 ch_layout.nb_channels 獲取聲道數
|
||||
// ch_layout 是一個 AVChannelLayout 結構體
|
||||
let channels = (*ptr).ch_layout.nb_channels;
|
||||
|
||||
let sample_fmt_val = (*ptr).sample_fmt;
|
||||
let format = ffmpeg::format::Sample::from(sample_fmt_val);
|
||||
|
||||
println!(" 採樣率: {} Hz", sample_rate);
|
||||
println!(" 聲道數: {}", channels);
|
||||
println!(" 音訊格式: {:?}", format);
|
||||
|
||||
// 可選:打印聲道佈局描述 (例如 "stereo", "5.1")
|
||||
// 需要引入 ffi 來調用 av_channel_layout_describe
|
||||
/*
|
||||
let mut buf = vec![0u8; 1024];
|
||||
let ret = ffmpeg::ffi::av_channel_layout_describe(
|
||||
&(*ptr).ch_layout,
|
||||
buf.as_mut_ptr() as *mut i8,
|
||||
buf.len() as i32
|
||||
);
|
||||
if ret >= 0 {
|
||||
if let Ok(layout_str) = std::ffi::CStr::from_bytes_until_nul(&buf) {
|
||||
println!(" 聲道佈局: {}", layout_str.to_string_lossy());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
},
|
||||
Type::Subtitle => {
|
||||
println!(" (字幕串流)");
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
println!(" (其他類型串流)");
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end unsafe
|
||||
} else {
|
||||
println!(" (未找到對應的解碼器)");
|
||||
}
|
||||
|
||||
// 輸出 Metadata
|
||||
for (key, value) in stream.metadata().iter() {
|
||||
println!(" Metadata [{}]: {}", key, value);
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n=== 檔案 Metadata ===");
|
||||
for (key, value) in ictx.metadata().iter() {
|
||||
println!("{}: {}", key, value);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
135
src/main.rs.bak
Normal file
135
src/main.rs.bak
Normal file
@@ -0,0 +1,135 @@
|
||||
use ffmpeg_next as ffmpeg;
|
||||
use ffmpeg::format::{input, Pixel};
|
||||
use ffmpeg::media::Type;
|
||||
use ffmpeg::codec::{context::Context, decoder};
|
||||
use std::path::Path;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
ffmpeg::init()?;
|
||||
|
||||
let input_path = "test.mp4";
|
||||
|
||||
if !Path::new(input_path).exists() {
|
||||
eprintln!("錯誤:找不到檔案 '{}'", input_path);
|
||||
eprintln!("請將一個視頻文件重命名為 'test.mp4' 並放在專案根目錄。");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut ictx = input(&input_path)?;
|
||||
|
||||
println!("=== 檔案基本資訊 ===");
|
||||
println!("格式名稱 (Format): {}", ictx.format().name());
|
||||
println!("長描述: {}", ictx.format().description());
|
||||
|
||||
let duration_sec = ictx.duration() as f64 / ffmpeg::ffi::AV_TIME_BASE as f64;
|
||||
println!("總長度 (Duration): {:.2} 秒", duration_sec);
|
||||
|
||||
println!("\n=== 串流資訊 ===");
|
||||
|
||||
for (index, stream) in ictx.streams().enumerate() {
|
||||
let codec_params = stream.parameters();
|
||||
let codec_id = codec_params.id();
|
||||
let media_type = codec_params.medium();
|
||||
|
||||
println!("[串流 #{}]", index);
|
||||
println!(" 類型: {:?}", media_type);
|
||||
println!(" 編碼器 ID: {:?}", codec_id);
|
||||
|
||||
if let Some(codec_descriptor) = decoder::find(codec_id) {
|
||||
let mut context = Context::new_with_codec(codec_descriptor);
|
||||
|
||||
if let Err(e) = context.set_parameters(codec_params) {
|
||||
eprintln!(" 警告:無法設置參數: {}", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let ptr = context.as_mut_ptr();
|
||||
|
||||
match media_type {
|
||||
Type::Video => {
|
||||
let width = (*ptr).width;
|
||||
let height = (*ptr).height;
|
||||
let pix_fmt_val = (*ptr).pix_fmt;
|
||||
let format = Pixel::from(pix_fmt_val);
|
||||
|
||||
let frame_rate = stream.avg_frame_rate();
|
||||
let fps = if frame_rate.numerator() != 0 {
|
||||
frame_rate.numerator() as f64 / frame_rate.denominator() as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
println!(" 解析度: {}x{}", width, height);
|
||||
println!(" 像素格式: {:?}", format);
|
||||
println!(" 幀率: {:.2} fps", fps);
|
||||
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
},
|
||||
Type::Audio => {
|
||||
let sample_rate = (*ptr).sample_rate;
|
||||
|
||||
// 【關鍵修復】新版本使用 ch_layout.nb_channels 獲取聲道數
|
||||
// ch_layout 是一個 AVChannelLayout 結構體
|
||||
let channels = (*ptr).ch_layout.nb_channels;
|
||||
|
||||
let sample_fmt_val = (*ptr).sample_fmt;
|
||||
let format = ffmpeg::format::Sample::from(sample_fmt_val);
|
||||
|
||||
println!(" 採樣率: {} Hz", sample_rate);
|
||||
println!(" 聲道數: {}", channels);
|
||||
println!(" 音訊格式: {:?}", format);
|
||||
|
||||
// 可選:打印聲道佈局描述 (例如 "stereo", "5.1")
|
||||
// 需要引入 ffi 來調用 av_channel_layout_describe
|
||||
/*
|
||||
let mut buf = vec![0u8; 1024];
|
||||
let ret = ffmpeg::ffi::av_channel_layout_describe(
|
||||
&(*ptr).ch_layout,
|
||||
buf.as_mut_ptr() as *mut i8,
|
||||
buf.len() as i32
|
||||
);
|
||||
if ret >= 0 {
|
||||
if let Ok(layout_str) = std::ffi::CStr::from_bytes_until_nul(&buf) {
|
||||
println!(" 聲道佈局: {}", layout_str.to_string_lossy());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
},
|
||||
Type::Subtitle => {
|
||||
println!(" (字幕串流)");
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
println!(" (其他類型串流)");
|
||||
if let Some(codec_name) = context.codec() {
|
||||
println!(" 編碼器名稱: {}", codec_name.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end unsafe
|
||||
} else {
|
||||
println!(" (未找到對應的解碼器)");
|
||||
}
|
||||
|
||||
// 輸出 Metadata
|
||||
for (key, value) in stream.metadata().iter() {
|
||||
println!(" Metadata [{}]: {}", key, value);
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n=== 檔案 Metadata ===");
|
||||
for (key, value) in ictx.metadata().iter() {
|
||||
println!("{}: {}", key, value);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user