22# -*- coding: utf-8 -*-
33# vim: ai ts=4 sts=4 et sw=4 nu
44
5+ import json
56import requests
7+ import yt_dlp
68
79from contextlib import ExitStack
810from dateutil import parser as dt_parser
@@ -195,11 +197,14 @@ def get_videos_json(playlist_id):
195197 save_json (YOUTUBE .cache_dir , fname , items )
196198 return items
197199
198- def subset_videos_json (videos , subset_by , subset_videos ):
200+ def subset_videos_json (videos , subset_by , subset_videos , subset_gb ):
199201 """make a list of popular or recent videos"""
200- playlist_id = videos [0 ]["snippet" ]["playlistId" ]
202+ options = {
203+ "ignoreerrors" : True ,
204+ }
205+ # we need to query the API for the statistics of each video
206+ videos = json .loads (videos )
201207 video_ids = [video ["contentDetails" ]["videoId" ] for video in videos ]
202- # we get the video statistics via Youtube API
203208 video_stats = {}
204209 for i in range (0 , len (video_ids ), 50 ):
205210 video_ids_chunk = video_ids [i : i + 50 ]
@@ -215,13 +220,24 @@ def subset_videos_json(videos, subset_by, subset_videos):
215220 logger .error (f"HTTP { req .status_code } Error response: { req .text } " )
216221 req .raise_for_status ()
217222 video_stats_json = req .json ()
218- for video in video_stats_json [ "items" ] :
223+ for video in video_stats_json . get ( "items" , []) :
219224 video_stats [video ["id" ]] = video ["statistics" ]
220- for video_id in video_ids_chunk :
221- if video_id not in video_stats :
222- video_stats [video_id ] = {"viewCount" : 0 , "likeCount" : 0 , "dislikeCount" : 0 }
225+ # we add the statistics to the videos if they are in the video_stats dict
223226 for video in videos :
224- video ["statistics" ] = video_stats [video ["contentDetails" ]["videoId" ]]
227+ video_id = video ["contentDetails" ]["videoId" ]
228+ if video_id in video_stats :
229+ video ["statistics" ] = video_stats [video_id ]
230+ else :
231+ logger .error (f"video { video_id } not found in video_stats" )
232+ # we add a dummy statistics dict with "0" values
233+ video ["statistics" ] = {
234+ "viewCount" : "0" ,
235+ "likeCount" : "0" ,
236+ "dislikeCount" : "0" ,
237+ "favoriteCount" : "0" ,
238+ "commentCount" : "0" ,
239+ }
240+ # we sort the videos by views or recent or views-per-year
225241 if subset_by == "views" :
226242 videos = sorted (videos , key = lambda video : video ["statistics" ]["viewCount" ], reverse = True )
227243 elif subset_by == "recent" :
@@ -235,12 +251,32 @@ def subset_videos_json(videos, subset_by, subset_videos):
235251 years = now .year - published_at .year
236252 video ["statistics" ]["views_per_year" ] = int (views ) / (years + 1 )
237253 videos = sorted (videos , key = lambda video : video ["statistics" ]["views_per_year" ], reverse = True )
238- # we limit the number of videos if needed
239- if subset_videos is not None :
240- videos = videos [:subset_videos ]
241- save_json (YOUTUBE .cache_dir , f"playlist_{ playlist_id } _videos" , videos )
254+ if subset_videos != 0 :
255+ videos_ids = [video ["contentDetails" ]["videoId" ] for video in videos ]
256+ videos_ids_subset = videos_ids [:subset_videos ]
257+ videos = [video for video in videos if video ["contentDetails" ]["videoId" ] in videos_ids_subset ]
258+ if subset_gb != 0 :
259+ total_size = 0
260+ videos_ids_subset = []
261+ for video in videos :
262+ video_id = video ["contentDetails" ]["videoId" ]
263+ video_size = yt_dlp .YoutubeDL (options ).extract_info (
264+ video_id , download = False
265+ )["filesize_approx" ] / 1024 / 1024 / 1024
266+ if total_size + video_size <= subset_gb :
267+ total_size += video_size
268+ videos_ids_subset .append (video_id )
269+ if video_id == videos [- 1 ]["contentDetails" ]["videoId" ]:
270+ videos_ids = videos_ids_subset
271+ videos = [video for video in videos if video ["contentDetails" ]["videoId" ] in videos_ids ]
272+ break
273+ else :
274+ videos_ids = videos_ids_subset
275+ videos = [video for video in videos if video ["contentDetails" ]["videoId" ] in videos_ids ]
276+ break
242277 return videos
243278
279+
244280# Replace some video titles reading 2 text files, one for the video id and one for the title (called with --custom-titles)
245281def replace_titles (items , custom_titles ):
246282 """replace video titles with custom titles from file"""
0 commit comments