Saving a frame from a streamed video as fast as possible with ffmpeg

662 Views Asked by At

I am capturing a single frame from a streaming video from a GoPro camera. This is mostly to get a quick idea if my subject is in frame before recording video and / or a picture. The frame captures very quickly but then FFMPEG seems to take almost 10 seconds to "spit it out". I have been hacking this for days and not making much progress. Command line right now:

fmpeg -loglevel verbose -y -i udp://@0.0.0.0:8554 -f image2 -map 0:0 -map -0:1 -map -0:2 -map -0:3 -flush_packets 1 -blocksize 2048 -c:v mjpeg  -qscale:v 8 -frames:v 1 -vf "select='eq(pict_type\,I)'"  test_%03d.jpg

-loglevel verbose : tell me everything
-y : overwrite existing files 
-i udp://@0.0.0.0:8554 : input is a stream at this address
-f image2 : extract an image 
-map 0:0 -map -0:1 -map -0:2 -map -0:3 : ignore all streams except 0
-flush_packets 1 : attempt to say "don't buffer" 
-blocksize 2048 : blocksize made really small to get files to write 
-c:v mjpeg : output is a jpeg  
-qscale:v 8 : output quality 8 
-frames:v 1 : give me 1 frame 
-vf "select='eq(pict_type\,I)'" give me only key frames 
test_%03d.jpg : output file format

It works, and the output is like:

ffmpeg version 3.4.8-0ubuntu0.2 Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
[mpegts @ 0x55d3e049ab00] parser not found for codec none, packets or times may be invalid.
[h264 @ 0x55d3e04bffe0] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0x55d3e04bffe0] decode_slice_header error
[h264 @ 0x55d3e04bffe0] no frame!
[h264 @ 0x55d3e04bffe0] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0x55d3e04bffe0] decode_slice_header error
[h264 @ 0x55d3e04bffe0] no frame!
[h264 @ 0x55d3e04bffe0] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0x55d3e04bffe0] decode_slice_header error
[h264 @ 0x55d3e04bffe0] no frame!
[h264 @ 0x55d3e04bffe0] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0x55d3e04bffe0] decode_slice_header error
[h264 @ 0x55d3e04bffe0] no frame!
[h264 @ 0x55d3e04bffe0] Reinit context to 1280x720, pix_fmt: yuvj420p

---------- 8 seconds go by ----------

[mpegts @ 0x55d3e049ab00] max_analyze_duration 7000000 reached at 7018667 microseconds st:1
[mpegts @ 0x55d3e049ab00] Could not find codec parameters for stream 2 (Unknown: none ([128][0][0][0] / 0x0080)): unknown codec
Consider increasing the value for the 'analyzeduration' and 'probesize' options
[mpegts @ 0x55d3e049ab00] Could not find codec parameters for stream 3 (Audio: ac3 ([129][0][0][0] / 0x0081), 0 channels, fltp): unspecified sample rate
Consider increasing the value for the 'analyzeduration' and 'probesize' options
Input #0, mpegts, from 'udp://@0.0.0.0:8554':
  Duration: N/A, start: 399.253333, bitrate: N/A
  Program 1
    Stream #0:0[0x1011]: Video: h264 (High), 1 reference frame ([27][0][0][0] / 0x001B), yuvj420p(pc, bt709, progressive, left), 1280x720 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 180k tbc
    Stream #0:1[0x1100]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 189 kb/s
    Stream #0:2[0x200]: Unknown: none ([128][0][0][0] / 0x0080)
    Stream #0:3[0x201]: Audio: ac3 ([129][0][0][0] / 0x0081), 0 channels, fltp
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (native))
Press [q] to stop, [?] for help
[mpegts @ 0x55d3e049ab00] Correcting start time by 12200
[h264 @ 0x55d3e05c5260] Reinit context to 1280x720, pix_fmt: yuvj420p
[h264 @ 0x55d3e0582720] reference picture missing during reorder
[h264 @ 0x55d3e0582720] Missing reference picture, default is 65531
[h264 @ 0x55d3e050fa80] reference picture missing during reorder
[h264 @ 0x55d3e050fa80] Missing reference picture, default is 65532
[h264 @ 0x55d3e05203e0] mmco: unref short failure
[graph 0 input from stream 0:0 @ 0x55d3e049a6e0] w:1280 h:720 pixfmt:yuvj420p tb:1/90000 fr:30000/1001 sar:1/1 sws_param:flags=2
Output #0, image2, to 'test_%03d.jpg':
  Metadata:
    encoder         : Lavf57.83.100
    Stream #0:0: Video: mjpeg, 1 reference frame, yuvj420p(pc, left), 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 29.97 fps, 29.97 tbn, 29.97 tbc
    Metadata:
      encoder         : Lavc57.107.100 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
*** 4 dup!
    Last message repeated 1 times
No more output streams to write to, finishing.
frame=   10 fps=0.0 q=8.0 Lsize=N/A time=00:00:00.33 bitrate=N/A dup=9 drop=1 speed=5.96x
video:416kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Input file #0 (udp://@0.0.0.0:8554):
  Input stream #0:0 (video): 23 packets read (367296 bytes); 12 frames decoded;
  Input stream #0:1 (audio): 39 packets read (19992 bytes);
  Input stream #0:2 ((null)): 0 packets read (0 bytes);
  Input stream #0:3 (audio): 0 packets read (0 bytes);
  Total: 62 packets (387288 bytes) demuxed
Output file #0 (test_%03d.jpg):
  Output stream #0:0 (video): 10 frames encoded; 10 packets muxed (426390 bytes);
  Total: 10 packets (426390 bytes) muxed

The image I get back is from immediately when the script started.

Any idea why it pauses so long?

Any way to speed it up?

Even if I could get it to spit out a frame a second and keep going this would be great. My program could look at the latest image only. But since it only spits out frames at the end of the run this doesn't help me.

0

There are 0 best solutions below