Answers.Body: <p>I have no idea if what you're doing is optimal, but "playing the video" to extract frames is essentially what has to happen, at least a little, if the frame you're extracting is not an I-frame (most frames are not). </p>
  
  <p>The chosen frame is likely represented as the accumulated differences since the last complete frame, which is what interframe compression does. In order to extract it, a program must read and reconstruct the intervening frames -- not from the beginning of the video, just from the most recent complete frame</p>
  
  <p>Depending on how many frames you need from each video, it might make sense to first convert to an "all-I" codec like MJPEG, where every frame stands alone. Then extracting any given frame would be much faster. When done you can delete the converted file.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-18T16:17:30.137Z
Answers.Text: I think the bottleneck here is frame seeking rather than decoding. Try encoding a file in ffmpeg from a mid-point in the source  (-ss 2400 or 40 minutes in) and ffmpeg will take some time to get going. Whereas on modern silicon, software players easily decode and process 24-30, if not 60, frames per second to provide realtime playback. That said, converting to I-frame only codec is the right way forward.
Answers.UserDisplayName: Gyan
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-29T00:09:26.237Z
Answers.Text: Converting the whole video to an MJPEG doesn't make sense to me over just converting all frames to JPEG then deleting the ones you don't want. Am I missing something here?
Answers.UserDisplayName: user3643
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-29T02:32:18.530Z
Answers.Text: @user24601 - One difference would be that once you have MJPEG you can still play the video to locate frames. Of course it depends on what the OP's process is -- decoding to a JPEG stack vs an MJPEG video should take about the same amount of time. It's what comes after that, that matters.
Answers.UserDisplayName: Jim Mack
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-29T17:19:26.557Z
Answers.Text: @Jim You can "programmatically play" a jpg stack, assuming they are sorted. If you're targeting specific frames, you'd just call the file name in a jpg stack ... Just thinking out loud. I'm working on a related project involving image extraction from a video.
Answers.UserDisplayName: user3643
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-18T12:25:47.047Z
Answers.LastActivityDate: 2015-09-18T12:25:47.047Z
Answers.UserDisplayName: Jim Mack
Body: <p>I am using <code>ffmpeg</code> to extract frames from videos. I have the following code thus far:</p>
  
  <pre><code>ffmpeg -i vid.mp4 -vf fps=1/10 images%05d.png
  </code></pre>
  
  <p>My issue is that it takes awhile! 6 seconds per image on average. Is there a way to speed this up? I am working with tens/hundreds of videos and I'm wanting to write up a shell script to automate the whole thing, but I don't want it to take days!</p>
  
  <p>I have seen other programs that can do this but they have to literally play through the video to reach the frames to extract. That would be far too slow. Perhaps <code>ffmpeg</code> is doing something like this?</p>
  
  <p>Any ideas how to speed this up?</p>
  
  <p>The videos at hand are 1920x1080 GoPro videos and I'd like full resolution images.</p>
  
  <p>Here's the output from the console:</p>
  
  <pre><code>ffmpeg version 2.7.2 Copyright (c) 2000-2015 the FFmpeg developers
    built with Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
    configuration: --prefix=/opt/local --enable-swscale --enable-avfilter --enable-avresample --enable-libmp3lame --enable-libvorbis --enable-libopus --enable-libtheora --enable-libschroedinger --enable-libopenjpeg --enable-libmodplug --enable-libvpx --enable-libspeex --enable-libass --enable-libbluray --enable-lzma --enable-gnutls --enable-fontconfig --enable-libfreetype --enable-libfribidi --disable-indev=jack --disable-outdev=xv --mandir=/opt/local/share/man --enable-shared --enable-pthreads --cc=/usr/bin/clang --enable-vda --arch=x86_64 --enable-yasm --enable-gpl --enable-postproc --enable-libx264 --enable-libxvid --enable-nonfree --enable-libfdk-aac --enable-libfaac
    libavutil      54. 27.100 / 54. 27.100
    libavcodec     56. 41.100 / 56. 41.100
    libavformat    56. 36.100 / 56. 36.100
    libavdevice    56.  4.100 / 56.  4.100
    libavfilter     5. 16.101 /  5. 16.101
    libavresample   2.  1.  0 /  2.  1.  0
    libswscale      3.  1.101 /  3.  1.101
    libswresample   1.  2.100 /  1.  2.100
    libpostproc    53.  3.100 / 53.  3.100
  Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'vid.mp4':
    Metadata:
  major_brand     : mp42
  minor_version   : 1
  compatible_brands: mp41mp42isom
  creation_time   : 2015-09-18 03:38:20
    Duration: 00:01:18.23, start: 0.969178, bitrate: 20388 kb/s
  Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 20004 kb/s, 29.97 fps, 29.97 tbr, 180k tbn, 59.94 tbc (default)
  Metadata:
    creation_time   : 2015-09-18 03:38:20
    handler_name    : Core Media Video
    encoder         : GoPro AVC encoder
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
  Metadata:
    creation_time   : 2015-09-18 03:38:20
    handler_name    : Core Media Audio
  [swscaler @ 0x7fdb12000000] deprecated pixel format used, make sure you did set range correctly
  Output #0, image2, to 'images%05d.png':
    Metadata:
  major_brand     : mp42
  minor_version   : 1
  compatible_brands: mp41mp42isom
  encoder         : Lavf56.36.100
  Stream #0:0(und): Video: png, rgb24, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 0.10 fps, 0.10 tbn, 0.10 tbc (default)
  Metadata:
    creation_time   : 2015-09-18 03:38:20
    handler_name    : Core Media Video
    encoder         : Lavc56.41.100 png
  Stream mapping:
    Stream #0:0 -&gt; #0:0 (h264 (native) -&gt; png (native))
  Press [q] to stop, [?] for help
  frame=    9 fps=0.2 q=0.0 Lsize=N/A time=00:01:30.00 bitrate=N/A    
  video:17647kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
  </code></pre>
  
Tags: <ffmpeg>
Title: quickly extract video frames with ffmpeg
UserDisplayName: CephBirk
ThreadText: # quickly extract video frames with ffmpeg
  
  (Asked by: username_0 on 2015-09-18)
  
  I am using `ffmpeg` to extract frames from videos. I have the following code thus far:
  
  ```
  ffmpeg -i vid.mp4 -vf fps=1/10 images%05d.png
  
  ```
  
  My issue is that it takes awhile! 6 seconds per image on average. Is there a way to speed this up? I am working with tens/hundreds of videos and I'm wanting to write up a shell script to automate the whole thing, but I don't want it to take days!
  
  I have seen other programs that can do this but they have to literally play through the video to reach the frames to extract. That would be far too slow. Perhaps `ffmpeg` is doing something like this?
  
  Any ideas how to speed this up?
  
  The videos at hand are 1920x1080 GoPro videos and I'd like full resolution images.
  
  Here's the output from the console:
  
  ```
  ffmpeg version 2.7.2 Copyright (c) 2000-2015 the FFmpeg developers
    built with Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
    configuration: --prefix=/opt/local --enable-swscale --enable-avfilter --enable-avresample --enable-libmp3lame --enable-libvorbis --enable-libopus --enable-libtheora --enable-libschroedinger --enable-libopenjpeg --enable-libmodplug --enable-libvpx --enable-libspeex --enable-libass --enable-libbluray --enable-lzma --enable-gnutls --enable-fontconfig --enable-libfreetype --enable-libfribidi --disable-indev=jack --disable-outdev=xv --mandir=/opt/local/share/man --enable-shared --enable-pthreads --cc=/usr/bin/clang --enable-vda --arch=x86_64 --enable-yasm --enable-gpl --enable-postproc --enable-libx264 --enable-libxvid --enable-nonfree --enable-libfdk-aac --enable-libfaac
    libavutil      54. 27.100 / 54. 27.100
    libavcodec     56. 41.100 / 56. 41.100
    libavformat    56. 36.100 / 56. 36.100
    libavdevice    56.  4.100 / 56.  4.100
    libavfilter     5. 16.101 /  5. 16.101
    libavresample   2.  1.  0 /  2.  1.  0
    libswscale      3.  1.101 /  3.  1.101
    libswresample   1.  2.100 /  1.  2.100
    libpostproc    53.  3.100 / 53.  3.100
  Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'vid.mp4':
    Metadata:
  major_brand     : mp42
  minor_version   : 1
  compatible_brands: mp41mp42isom
  creation_time   : 2015-09-18 03:38:20
    Duration: 00:01:18.23, start: 0.969178, bitrate: 20388 kb/s
  Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 20004 kb/s, 29.97 fps, 29.97 tbr, 180k tbn, 59.94 tbc (default)
  Metadata:
    creation_time   : 2015-09-18 03:38:20
    handler_name    : Core Media Video
    encoder         : GoPro AVC encoder
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
  Metadata:
    creation_time   : 2015-09-18 03:38:20
    handler_name    : Core Media Audio
  [swscaler @ 0x7fdb12000000] deprecated pixel format used, make sure you did set range correctly
  Output #0, image2, to 'images%05d.png':
    Metadata:
  major_brand     : mp42
  minor_version   : 1
  compatible_brands: mp41mp42isom
  encoder         : Lavf56.36.100
  Stream #0:0(und): Video: png, rgb24, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 0.10 fps, 0.10 tbn, 0.10 tbc (default)
  Metadata:
    creation_time   : 2015-09-18 03:38:20
    handler_name    : Core Media Video
    encoder         : Lavc56.41.100 png
  Stream mapping:
    Stream #0:0 -> #0:0 (h264 (native) -> png (native))
  Press [q] to stop, [?] for help
  frame=    9 fps=0.2 q=0.0 Lsize=N/A time=00:01:30.00 bitrate=N/A    
  video:17647kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
  
  ```
  
  **Tags:** ffmpeg
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2015-09-18. Score: 3 | Accepted answer
  
  I have no idea if what you're doing is optimal, but "playing the video" to extract frames is essentially what has to happen, at least a little, if the frame you're extracting is not an I-frame (most frames are not).
  
  The chosen frame is likely represented as the accumulated differences since the last complete frame, which is what interframe compression does. In order to extract it, a program must read and reconstruct the intervening frames -- not from the beginning of the video, just from the most recent complete frame
  
  Depending on how many frames you need from each video, it might make sense to first convert to an "all-I" codec like MJPEG, where every frame stands alone. Then extracting any given frame would be much faster. When done you can delete the converted file.
  
  > **Comments:**
  > **username_2**: I think the bottleneck here is frame seeking rather than decoding. Try encoding a file in ffmpeg from a mid-point in the source  (-ss 2400 or 40 minutes in) and ffmpeg will take some time to get going. Whereas on modern silicon, software players easily decode and process 24-30, if not 60, frames per second to provide realtime playback. That said, converting to I-frame only codec is the right way forward.  
  > **username_3**: Converting the whole video to an MJPEG doesn't make sense to me over just converting all frames to JPEG then deleting the ones you don't want. Am I missing something here?  
  > **username_1**: @user24601 - One difference would be that once you have MJPEG you can still play the video to locate frames. Of course it depends on what the OP's process is -- decoding to a JPEG stack vs an MJPEG video should take about the same amount of time. It's what comes after that, that matters.  
  > **username_3**: @Jim You can "programmatically play" a jpg stack, assuming they are sorted. If you're targeting specific frames, you'd just call the file name in a jpg stack ... Just thinking out loud. I'm working on a related project involving image extraction from a video.  
  
  ---
  
  