pdeljanov / Symphonia

Pure Rust multimedia format demuxing, tag reading, and audio decoding library
Mozilla Public License 2.0
2.42k stars 144 forks source link

I getting "unsupported codec" for one webm file, but it works for another. #307

Open gustawdaniel opened 3 months ago

gustawdaniel commented 3 months ago

Steps to reproduce:

1 Lets download files:

Lets inspect them by ffmpeg -i

Working file

ffmpeg -i file_example_WEBM_480_900KB.webm
ffmpeg version n7.0.1 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 14.1.1 (GCC) 20240522
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-frei0r --enable-gmp --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libdvdnav --enable-libdvdread --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libharfbuzz --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libplacebo --enable-libpulse --enable-librav1e --enable-librsvg --enable-librubberband --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpl --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-mbedtls --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-shared --enable-vapoursynth --enable-version3 --enable-vulkan
  libavutil      59.  8.100 / 59.  8.100
  libavcodec     61.  3.100 / 61.  3.100
  libavformat    61.  1.100 / 61.  1.100
  libavdevice    61.  1.100 / 61.  1.100
  libavfilter    10.  1.100 / 10.  1.100
  libswscale      8.  1.100 /  8.  1.100
  libswresample   5.  1.100 /  5.  1.100
  libpostproc    58.  1.100 / 58.  1.100
Input #0, matroska,webm, from 'file_example_WEBM_480_900KB.webm':
  Metadata:
    ENCODER         : Lavf57.83.100
  Duration: 00:00:30.54, start: 0.000000, bitrate: 236 kb/s
  Stream #0:0: Video: vp8, yuv420p(progressive), 480x270, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 1k tbn (default)
      Metadata:
        HANDLER_NAME    : L-SMASH Video Handler
        COMPATIBLE_BRANDS: mp42mp41isomavc1
        MAJOR_BRAND     : mp42
        MINOR_VERSION   : 0
        ENCODER         : Lavc57.107.100 libvpx
        DURATION        : 00:00:30.036000000
  Stream #0:1: Audio: vorbis, 48000 Hz, stereo, fltp (default)
      Metadata:
        HANDLER_NAME    : L-SMASH Audio Handler
        COMPATIBLE_BRANDS: mp42mp41isomavc1
        MAJOR_BRAND     : mp42
        MINOR_VERSION   : 0
        ENCODER         : Lavc57.107.100 libvorbis
        DURATION        : 00:00:30.543000000
At least one output file must be specified

Not working file

 ffmpeg -i video.webm                      
ffmpeg version n7.0.1 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 14.1.1 (GCC) 20240522
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-frei0r --enable-gmp --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libdvdnav --enable-libdvdread --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libharfbuzz --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libplacebo --enable-libpulse --enable-librav1e --enable-librsvg --enable-librubberband --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpl --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-mbedtls --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-shared --enable-vapoursynth --enable-version3 --enable-vulkan
  libavutil      59.  8.100 / 59.  8.100
  libavcodec     61.  3.100 / 61.  3.100
  libavformat    61.  1.100 / 61.  1.100
  libavdevice    61.  1.100 / 61.  1.100
  libavfilter    10.  1.100 / 10.  1.100
  libswscale      8.  1.100 /  8.  1.100
  libswresample   5.  1.100 /  5.  1.100
  libpostproc    58.  1.100 / 58.  1.100
Input #0, matroska,webm, from 'video.webm':
  Metadata:
    encoder         : Chrome
  Duration: 00:00:07.65, start: 0.000000, bitrate: 323 kb/s
  Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp (default)
  Stream #0:1(eng): Video: vp9 (Profile 0), yuv420p(tv), 640x480, SAR 1:1 DAR 4:3, 23 fps, 23 tbr, 1k tbn (default)
      Metadata:
        alpha_mode      : 1
At least one output file must be specified

Most important probably are lines:

working:

  Stream #0:0: Video: vp8, yuv420p(progressive), 480x270, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 1k tbn (default)
  Stream #0:1: Audio: vorbis, 48000 Hz, stereo, fltp (default)

not working

  Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp (default)
  Stream #0:1(eng): Video: vp9 (Profile 0), yuv420p(tv), 640x480, SAR 1:1 DAR 4:3, 23 fps, 23 tbr, 1k tbn (default)

My code:

use symphonia::core::formats::{FormatOptions};
use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use std::path::Path;
use symphonia::core::codecs::{CODEC_TYPE_NULL, DecoderOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // let input_path = Path::new("video.webm");
    let input_path = Path::new("file_example_WEBM_480_900KB.webm");

    let src = std::fs::File::open(&input_path).expect("failed to open media");
    let mss = MediaSourceStream::new(Box::new(src), Default::default());

    let mut hint = Hint::new();
    hint.with_extension("webm");

    // Use the default options for metadata and format readers.
    let meta_opts: MetadataOptions = Default::default();
    let fmt_opts: FormatOptions = Default::default();

    // Probe the media source.
    let probed = symphonia::default::get_probe().format(&hint, mss, &fmt_opts, &meta_opts)
        .expect("unsupported format");

    let format = probed.format;

    // Print codec information
    for track in format.tracks() {
        println!("Track ID: {}", track.id);
        println!("Codec: {:02}", track.codec_params.codec);
        println!("Channels: {:?}", track.codec_params.channels);
        println!("Sample Rate: {:?}", track.codec_params.sample_rate);
    }

    // Find the first audio track with a known (decodeable) codec.
    let track = format.tracks()
        .iter()
        .find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
        .expect("no supported audio tracks");

    let dec_opts: DecoderOptions = Default::default();

    // Create a decoder for the track.
    let _decoder = symphonia::default::get_codecs().make(&track.codec_params, &dec_opts)
        .expect("unsupported codec");

    println!("Conversion completed successfully!");
    Ok(())
}

for working file it will print result

Track ID: 1
Codec: 0x0
Channels: None
Sample Rate: None
Track ID: 2
Codec: 0x1000
Channels: None
Sample Rate: Some(48000)
Conversion completed successfully!

but for not working

Track ID: 1
Codec: 0x1005
Channels: None
Sample Rate: Some(48000)
Track ID: 2
Codec: 0x0
Channels: None
Sample Rate: None
thread 'main' panicked at src/bin/convert.rs:46:10:
unsupported codec: Unsupported("core (codec):unsupported codec")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I found that in working examle we using vorbis

pub const CODEC_TYPE_VORBIS: CodecType = CodecType(0x1000);

but for not working opus

pub const CODEC_TYPE_OPUS: CodecType = CodecType(0x1005);

and it can be potentially connected with issue https://github.com/pdeljanov/Symphonia/issues/8

but on the orher hand I see in both cases 0x0 for video stream but

vorbis and opus are audio streams recognized by ffmpeg

so it is issue of opus or vp8 and vp9?

hasezoey commented 2 weeks ago

and it can be potentially connected with issue https://github.com/pdeljanov/Symphonia/issues/8

if i understand this issue correctly, it is a duplicate of #8.

thread 'main' panicked at src/bin/convert.rs:46:10: let _decoder = symphonia::default::get_codecs().make(&track.codec_params, &dec_opts) .expect("unsupported codec");

if the error comes from the same code as provided, this is the line it panics on, which is expected as you are trying to make a decoder for opus in symphonia, which is a codec which is not yet implemented and explicitly expect it.

but on the orher hand I see in both cases 0x0 for video stream but

symphonia currently does not handle any video stream, only audio.


so it is issue of opus or vp8 and vp9?

TL;DR: the issue is opus and you trying to make a decoder for it