rust-ffmpeg: ffmpeg v5.1.1 seems broken
Hello,
Thank you for your work on this project. It allows a lot of awesome implementations of ffmpeg.
I’m trying to make this work with ffmpeg
v5.1.1 (with ffmpeg-next
v5.1.1).
However I’m facing many issues with the transcode-x264.rs
example.
Here is an output of running the example:
x264 options: {"preset": "medium"}
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/path/to/video.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42mp41
creation_time : 2021-08-25T09:45:49.000000Z
Duration: 00:00:16.04, start: 0.000000, bitrate: 2549 kb/s
Stream #0:0[0x1](eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 2170 kb/s, 29.97 fps, 29.97 tbr, 30k tbn (default)
Metadata:
creation_time : 2021-08-25T09:45:49.000000Z
handler_name : ?Mainconcept Video Media Handler
vendor_id : [0][0][0][0]
encoder : AVC Coding
Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 317 kb/s (default)
Metadata:
creation_time : 2021-08-25T09:45:49.000000Z
handler_name : #Mainconcept MP4 Sound Media Handler
vendor_id : [0][0][0][0]
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', def/main.rs:62:52
stack backtrace:
0: rust_begin_unwind
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:142:14
2: core::panicking::panic
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:48:5
3: core::option::Option<T>::unwrap
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/option.rs:775:21
4: def::Transcoder::new
at ./def/main.rs:62:31
5: def::main
at ./def/main.rs:210:17
6: core::ops::function::FnOnce::call_once
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
As you can see, the decoder.frame_rate()
is None
but it’s not the case when using v4.
If I try to enforce frame_rate
and time_base
with static values, I have this error:
---SAME OUTPUT---
[NULL @ 0x5630fb191800] No codec provided to avcodec_open2()
thread 'main' panicked at 'error opening libx264 encoder with supplied settings: ffmpeg::Error(22: Invalid argument)', def/main.rs:69:14
stack backtrace:
0: rust_begin_unwind
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:142:14
2: core::result::unwrap_failed
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1814:5
3: core::result::Result<T,E>::expect
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1064:23
4: def::Transcoder::new
at ./def/main.rs:67:9
5: def::main
at ./def/main.rs:210:17
6: core::ops::function::FnOnce::call_once
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Any idea?
Edit 1
FYI, if I log the output of decoder.frame_rate()
and decoder.time_base()
, I get: fr: None, tb: Rational(0/2)
Edit 2:
If I enforce the codec using encoder.open_as_with()
, I get another error:
---SAME OUTPUT---
[libx264 @ 0x55de35f0d800] broken ffmpeg default settings detected
[libx264 @ 0x55de35f0d800] use an encoding preset (e.g. -vpre medium)
[libx264 @ 0x55de35f0d800] preset usage: -vpre <speed> -vpre <profile>
[libx264 @ 0x55de35f0d800] speed presets are listed in x264 --help
[libx264 @ 0x55de35f0d800] profile is optional; x264 defaults to high
thread 'main' panicked at 'error opening libx264 encoder with supplied settings: ffmpeg::Error(542398533: Generic error in an external library)', def/main.rs:69:14
stack backtrace:
0: rust_begin_unwind
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/panicking.rs:142:14
2: core::result::unwrap_failed
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1814:5
3: core::result::Result<T,E>::expect
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/result.rs:1064:23
4: def::Transcoder::new
at ./def/main.rs:67:9
5: def::main
at ./def/main.rs:210:17
6: core::ops::function::FnOnce::call_once
at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Edit 3
Another interesting input:
let codec = encoder::find(codec::Id::H264);
let mut ost = octx.add_stream(codec)?;
println!(
"{:?} = {:?}",
codec::context::Context::from_parameters(ost.parameters())?
.codec()
.map(|c| c.name().to_string()),
codec.map(|c| c.name().to_string())
);
//prints:
None = Some("libx264")
It seems that the method codec::context::Context::from_parameters
is not including the codec.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 7
- Comments: 15
For anyone else running into this, the library does have support for v6+ (and the v7 that just launched today, props to the guy who merged that on launch day 🥳 ), but as mentioned above, the API is a little different than v4, and the transcoding x264 example is assuming ffmpeg v4.
The fix is very simple to make it v6/v7 compatible:
also, toward the end of
Transcoder::new()
, ignore the part where they re-initialize a new encoder from the output parameters for some reason, and instead use the one returned from theopen_with
command:I have a working encoder implementation here (MIT licensed): https://github.com/nununoisy/spc-presenter-rs/tree/v0.1.1/src/video_builder
I’ve verified it works for:
I’ve tested it with FFmpeg 4.4 on Linux, FFmpeg 5 on Windows (from vcpkg on msvc), and FFmpeg 6 on Linux. FFmpeg 6 requires this code in your
build.rs
:I did need to write some
unsafe
functions to interact withffmpeg-sys-next
directly in some cases. Hopefully, those functions can be used to extend the current API to allow for constructing a working encoder.I see this same problem using
ffmpeg
5.1.2 andffmpeg-next
v5.1.1After messing around with this crate I’ve now found quite a few breaking API changes… there don’t appear to be any decent safe bindings for ffmpeg for rust… so have abandoned rust ffmpeg in favor of gstreamer, which has excellent rust support.
Test available
I did a quick test and seems like if we pass a codec to
avcodec_alloc_context3
instead of a null pointer, it works. 🤔The function docs can be found here.
This was the code that I used to test: