imageio / imageio-ffmpeg

FFMPEG wrapper for Python
BSD 2-Clause "Simplified" License
221 stars 50 forks source link

`RuntimeError: Could not get number of frames` (with ffmpeg-6.1?) #99

Closed mgorny closed 1 month ago

mgorny commented 6 months ago

When running the test suite today, I'm getting a number of failures:

FAILED tests/test_io.py::test_read_nframes - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write1 - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_pix_fmt_in - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_pix_fmt_out - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_quality - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_bitrate - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_macro_block_size - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_big_frames - RuntimeError: Could not get number of frames
FAILED tests/test_io.py::test_write_audio_path - RuntimeError: Could not get number of frames

Also some similar failures when running imageio's test suites. I'm pretty sure it worked around release time, so I suspect something changed on my system. I suspect it's because of ffmpeg upgrade to 6.1 but can't check right now.

# ffmpeg -i /tmp/portage/dev-python/imageio-ffmpeg-0.4.9/temp/test.mp4 -map 0:v:0 -c copy -f null -
ffmpeg version 6.1 Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 13 (Gentoo 13.2.1_p20231014 p8)
  configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --docdir=/usr/share/doc/ffmpeg-6.1-r1/html --mandir=/usr/share/man --enable-shared --cc=x86_64-pc-linux-gnu-gcc --cxx=x86_64-pc-linux-gnu-g++ --ar=x86_64-pc-linux-gnu-ar --nm=x86_64-pc-linux-gnu-nm --strip=x86_64-pc-linux-gnu-strip --ranlib=x86_64-pc-linux-gnu-ranlib --pkg-config=x86_64-pc-linux-gnu-pkg-config --optflags='-march=znver2 --param=l1-cache-size=32 --param=l1-cache-line-size=64 -O2 -pipe -frecord-gcc-switches' --disable-static --disable-libaribcaption --enable-avfilter --disable-stripping --disable-optimizations --disable-libcelt --enable-nonfree --enable-version3 --disable-indev=sndio --disable-outdev=sndio --enable-version3 --enable-version3 --enable-nonfree --enable-bzlib --disable-runtime-cpudetect --disable-debug --disable-gcrypt --enable-gnutls --enable-gmp --enable-gpl --disable-hardcoded-tables --enable-iconv --disable-libxml2 --enable-lzma --enable-network --disable-opencl --enable-openssl --enable-postproc --disable-libsmbclient --enable-ffplay --enable-sdl2 --enable-vaapi --enable-vdpau --enable-vulkan --enable-xlib --enable-libxcb --enable-libxcb-shm --enable-libxcb-xfixes --enable-zlib --enable-libcdio --enable-libiec61883 --enable-libdc1394 --enable-libcaca --enable-openal --enable-opengl --enable-libv4l2 --enable-libpulse --disable-libdrm --enable-libjack --enable-libopencore-amrwb --enable-libopencore-amrnb --disable-libcodec2 --enable-libdav1d --enable-libfdk-aac --enable-libopenjpeg --enable-libjxl --enable-libbluray --enable-libgme --enable-libgsm --disable-libaribb24 --disable-mmal --enable-libmodplug --enable-libopus --disable-libvpl --disable-libilbc --disable-librtmp --enable-libssh --enable-libspeex --disable-libsrt --enable-librsvg --disable-ffnvcodec --enable-libvorbis --enable-libvpx --enable-libzvbi --disable-appkit --disable-libbs2b --disable-chromaprint --disable-cuda-llvm --disable-libflite --enable-fontconfig --disable-frei0r --disable-libfribidi --disable-libglslang --enable-ladspa --enable-lcms2 --enable-libass --disable-libplacebo --disable-libtesseract --disable-lv2 --disable-librubberband --disable-libshaderc --enable-libfreetype --enable-libharfbuzz --enable-libvidstab --disable-libvmaf --disable-libzmq --disable-libzimg --enable-libsoxr --enable-pthreads --disable-amf --enable-libvo-amrwbenc --disable-libkvazaar --disable-libaom --enable-libmp3lame --disable-libopenh264 --enable-librav1e --disable-libsnappy --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --disable-gnutls --enable-version3 --disable-armv5te --disable-armv6 --disable-armv6t2 --disable-neon --disable-vfp --disable-vfpv3 --disable-armv8 --disable-mipsdsp --disable-mipsdspr2 --disable-mipsfpu --disable-altivec --disable-vsx --disable-power8 --disable-amd3dnow --disable-amd3dnowext --disable-fma4 --disable-xop --disable-dotprod --disable-i8mm --cpu=znver2 --disable-doc --disable-htmlpages --enable-manpages
  libavutil      58. 29.100 / 58. 29.100
  libavcodec     60. 31.102 / 60. 31.102
  libavformat    60. 16.100 / 60. 16.100
  libavdevice    60.  3.100 / 60.  3.100
  libavfilter     9. 12.100 /  9. 12.100
  libswscale      7.  5.100 /  7.  5.100
  libswresample   4. 12.100 /  4. 12.100
  libpostproc    57.  3.100 / 57.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/tmp/portage/dev-python/imageio-ffmpeg-0.4.9/temp/test.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:00:00.06, start: 0.000000, bitrate: 195 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 64x64, 90 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc60.31.102 libx264
Output #0, null, to 'pipe:':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 64x64, q=2-31, 90 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc60.31.102 libx264
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
[out#0/null @ 0x55f6f578ddc0] video:1kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
size=N/A time=00:00:00.00 bitrate=N/A speed=   0x    

Full log: imageio-ffmpeg.txt

almarklein commented 6 months ago

It looks like the output text has changed a bit. It looks for a line starting with frame=, but its not there.

https://github.com/imageio/imageio-ffmpeg/blob/9ab981a8d09138fb1b3b814cb4287b705f258ec5/imageio_ffmpeg/_io.py#L173-L187

mgorny commented 6 months ago

I think it doesn't output frame= with -c copy anymore. I guess it doesn't count frames if it doesn't decode the stream.

almarklein commented 6 months ago

😢 any idea about how we can modify the command to make ffmpeg include the frame count again?

mgorny commented 6 months ago

I'm afraid I don't know. I was able to find a solution involving ffprobe but I haven't tested it.

tvercaut commented 4 months ago

Same issue here... I quickly looked at ffmpeg code. It looks like the print command is still there but with an additional requirement for a filter:

ffmpeg 6.1: https://github.com/FFmpeg/FFmpeg/blob/33efa50fa4508567b1d84d0a84728b400e492a6a/fftools/ffmpeg.c#L539-L557

ffmpeg 5.1: https://github.com/FFmpeg/FFmpeg/blob/9bf90b12602845b1a07a4ba4e7452d9229195df5/fftools/ffmpeg.c#L1566-L1586

Changing -c copy to -vf copy in the current call thus seems to work for me although I don't know how robust or efficient that is. https://github.com/imageio/imageio-ffmpeg/blob/9ab981a8d09138fb1b3b814cb4287b705f258ec5/imageio_ffmpeg/_io.py#L150-L160 to

    cmd = [
        get_ffmpeg_exe(),
        "-i",
        path,
        "-map",
        "0:v:0",
        "-vf",
        "copy",
        "-f",
        "null",
        "-",

There is also a null filter which may be more appropriate: https://ffmpeg.org/ffmpeg-filters.html#null https://ffmpeg.org/ffmpeg-filters.html#copy

almarklein commented 4 months ago

@tvercaut Thanks, it would be great if this issue could be fixed with such a simple change.

@mgorny do you perhaps have a chance to check whether the fix proposed by @tvercaut works for you?

mgorny commented 4 months ago

@mgorny do you perhaps have a chance to check whether the fix proposed by @tvercaut works for you?

Yes, the tests pass for me with that change.

Thanks!

almarklein commented 4 months ago

@mgorny thanks for confirming this!

@tvercaut could I interest you in contributing this change via a PR? 😄

tvercaut commented 4 months ago

PR submitted in #107 but note that I haven't tested it with ffmpeg 5.X so hopefully the CI will do that