9

Let me explain what I had set up. I've been using pytube (Python module) to download videos from YouTube. I would then extract a few random frames from the video and save them as jpegs. I don't need the audio, nor the video.

Now, I've been downloading tens of thousands of videos and then deleting them just to grab a couple of random frames per video. This seemed wasteful and cost a fair bit too. Is there a way to just download the frames themselves without having to download the video?

I would guess something like youtube-dl combined with ffmpeg would do the trick, but I can't find an example online to do that. There is a solution to download a random sample of video which would reduce network bandwidth consumption a good deal, but I want something more efficient and less time consuming. Any help would be appreciated.

WARNING: Could not send HEAD request to https://www.youtube.com/watch\?v\=oHg5SJYRHA0: HTTP Error 404: Not Found ERROR: Unable to download webpage: HTTP Error 404: Not Found (caused by HTTPError()); please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see https://yt-dl.org/update on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output. ffmpeg version 3.4.6-0ubuntu0.18.04.1 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 7 (Ubuntu 7.3.0-16ubuntu3) configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --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 WARNING: library configuration mismatch avcodec configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --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 --enable-version3 --disable-doc --disable-programs --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libtesseract --enable-libvo_amrwbenc 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 -vframes: No such file or directory
3
  • This answer unix.stackexchange.com/a/392350/83684 shows how to download a portion of a video using youtube-dl and ffmpeg, although it's unclear whether the whole video is downloaded then trimmed. It's a segment of video rather than a single frame but might be a good starting point.
    – Arronical
    Jul 2, 2019 at 12:11
  • Thanks, I did see that earlier. Couldn't find anything about frames or downloading just the video bit. I guess incredibly tiny clips and take a frame from there would be my workaround for now. Jul 2, 2019 at 12:23
  • Just working on an answer that gets single frames, unfortunately I won't be able to test it right now, but perhaps worth getting down and refining later.
    – Arronical
    Jul 2, 2019 at 12:24

2 Answers 2

4

Using a combination of this answer and this answer the following should be able to do what you want:

ffmpeg -ss "$screenshot_time" -i $(youtube-dl -f 22 --get-url "$youtube_url") -vframes 1 -q:v 2 "$output_file"
  • ffmpeg's -ss option is used here as an input option which is the fastest method available. It can be used as an output option, which will take a lot more time, but avoids the accidental artifact creation that the input version occasionally generates.

-ss position (input/output)

When used as an input option (before -i), seeks in this input file to position. Note the in most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and -accurate_seek is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when -noaccurate_seek is used, it will be preserved.

When used as an output option (before an output filename), decodes but discards input until the timestamps reach position.

position may be either in seconds or in hh:mm:ss[.xxx] form.

  • The -i option means to use the following as input to ffmpeg, here we use Bash's command substitution to use the output of youtube-dl.
  • -vframes 1 sets the number of output frames to 1.
  • -q:v 2 controls output quality. The full range is a linear scale of 1-31 where a lower value results in a higher quality. 2-5 is the range recommended in the source answer used for the ffmpeg part of this answer.
  • "$screenshot_time" should be replaced with the timestamp of the clip you wish to capture in the from shown above.
  • "$output_file" should be replaced with the path to your output file, screenshot.jpeg or similar perhaps.

In terms of the youtube-dl command, -f 22 downloads as the best possible quality mp4 format, and the "$youtube_url" should be replaced with the URL of the video.

2
  • Thanks much appreciated! Will test this is a bit and let you know how it goes. Jul 2, 2019 at 13:22
  • Hi @Arronical this doesn't seem to work. When I run: ffmpeg $(youtube-dl -g 'https://www.youtube.com/watch?v=oHg5SJYRHA0' | sed "s/.*/-ss 00:40 -i &/") -t 00:1 -c copy out.mkv It works fine, however, when I run your command with the same video, this is the message I get:, see my answer below. I did read that vframes is an alias that shouldn't be used anymore. But I tried -frames:v too and it didn't work. What could be wrong? Jul 3, 2019 at 2:50
2

The plumber tool offers the ability to grab a screenshot of a single frame in a youtube video. To install the tool, type the following in a terminal window:

sudo snap install plumber

Paste the youtube url in the box marked in yellow, or use the built-in search function by clicking the icon marked in red.

You can then find the desired frame in the video and click the icon marked in pink, followed by the icon marked in green, which will open another window to show a preview of the screenshot and allow you to save it as an image file.

The tool can also be used to save videos/gifs of a clip of a youtube video.

plumber main screen

screenshot window

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .