Reputation: 17
I'm trying to download only the first frame of every video in a large playlist on YouTube. Does anybody know how I can use ffmpeg and youtube-dl to do this?
Upvotes: 0
Views: 1606
Reputation: 1711
Due to the nature of video encoding, you need to download a small segments of each streams first.
yt-dlp -I 0:5 -f '(bestvideo+bestaudio/best)[protocol!*=dash]' \
--external-downloader ffmpeg \
--external-downloader-args "ffmpeg_i:-ss 0 -t 1" \
"https://youtu.be/channel/UCpVm7bg6pXKo1Pr6k5kxG9A"
option -I
will limit the playlist range. If an other playlist is found in a playlist, it will also download the items found inside of it and so on.
The same will work on a unique video.
Then you can convert every of them to images.
IFS=$'\n'; for files in $(ls *); do
ffmpeg -i "$files" -ss 0 -frames:v 1 $files-frames%03d.png;
done;
Play with the options -ss
if you need to skip seconds. Several frames are also possible.
This might fail on vp9 encoding and live streams.
Alternatively, you can also use the following to download one file and convert a segment to images:
ffmpeg $(yt-dlp -g 'https://youtu.be/watch?v=oHg5SJYRHA0' | sed "s/.*/-i &/") \
-ss 1 -frames:v 1 -q:v 2 frames%03d.png
Here the piping through sed
prefixes multiple streams, possibly presents in the input, usually one audio and one video, each with -i
. You can also save multiple frames over a segment this way.
This doesn't requires a reencoding, so depending on the size of the video and your download speed it might or might not be faster than the first solution.
Upvotes: 0
Reputation: 385
First you need to take the playlist ID of the youtube playlist and download the full playlist of the thumbnails you want to get like this:
youtube-dl -i PLwJ2VKmefmxpUJEGB1ff6yUZ5Zd7Gegn2
Then you use the following script, which will extract the first frame of the all the videos, (do note that after downloading the full playlist all of the videos are in the same directory):
i=1
for avi in *.mp4; do
name=`echo $avi | cut -f1 -d'.'`
jpg_ext='.jpg'
echo "$i": extracting the first frame of the video "$avi" into "$name$jpg_ext"
ffmpeg -loglevel panic -i $avi -vframes 1 -f image2 "$name$jpg_ext"
i=$((i+1))
done
Upvotes: 1