def api(self, bestmatch=True): """ Use YouTube API to search and return a list of matching videos. """ query = {"part": "snippet", "maxResults": 50, "type": "video"} if const.args.music_videos_only: query["videoCategoryId"] = "10" if not self.meta_tags: song = self.raw_song query["q"] = song else: query["q"] = self.search_query log.debug("query: {0}".format(query)) data = pafy.call_gdata("search", query) data["items"] = list( filter(lambda x: x["id"].get("videoId") is not None, data["items"])) query_results = { "part": "contentDetails,snippet,statistics", "maxResults": 50, "id": ",".join(i["id"]["videoId"] for i in data["items"]), } log.debug("query_results: {0}".format(query_results)) vdata = pafy.call_gdata("videos", query_results) videos = [] for x in vdata["items"]: duration_s = pafy.playlist.parseISO8591( x["contentDetails"]["duration"]) youtubedetails = { "link": x["id"], "title": x["snippet"]["title"], "videotime": internals.videotime_from_seconds(duration_s), "seconds": duration_s, } if self.meta_tags["name"] in x["snippet"]["title"]: videos.append(youtubedetails) log.error("I'm hot") if bestmatch: return self._best_match(videos) return videos
def api(self, bestmatch=True): """ Use YouTube API to search and return a list of matching videos. """ query = {'part': 'snippet', 'maxResults': 50, 'type': 'video'} if const.args.music_videos_only: query['videoCategoryId'] = '10' if not self.meta_tags: song = self.raw_song query['q'] = song else: query['q'] = self.search_query log.debug('query: {0}'.format(query)) data = pafy.call_gdata('search', query) data['items'] = list( filter(lambda x: x['id'].get('videoId') is not None, data['items'])) query_results = { 'part': 'contentDetails,snippet,statistics', 'maxResults': 50, 'id': ','.join(i['id']['videoId'] for i in data['items']) } log.debug('query_results: {0}'.format(query_results)) vdata = pafy.call_gdata('videos', query_results) videos = [] for x in vdata['items']: duration_s = pafy.playlist.parseISO8591( x['contentDetails']['duration']) youtubedetails = { 'link': x['id'], 'title': x['snippet']['title'], 'videotime': internals.videotime_from_seconds(duration_s), 'seconds': duration_s } videos.append(youtubedetails) if bestmatch: return self._best_match(videos) return videos
def test_from_hours(self): expect_duration = "1:16:02" duration = internals.videotime_from_seconds(4562) assert duration == expect_duration
def test_from_minutes(self): expect_duration = "2:38" duration = internals.videotime_from_seconds(158) assert duration == expect_duration
def test_from_seconds(self): expect_duration = "35" duration = internals.videotime_from_seconds(35) assert duration == expect_duration
def _best_match(self, videos): if not videos: log.error("No videos found on YouTube for a given search") return None """ Select the best matching video from a list of videos. """ if const.args.manual: log.info(self.raw_song) log.info("0. Skip downloading this song.\n") # fetch all video links on first page on YouTube for i, v in enumerate(videos): log.info(u"{0}. {1} {2} {3}".format( i + 1, v["title"], v["videotime"], "http://youtube.com/watch?v=" + v["link"], )) # let user select the song to download result = internals.input_link(videos) if result is None: return None else: if not self.meta_tags: # if the metadata could not be acquired, take the first result # from Youtube because the proper song length is unknown result = videos[0] log.debug( "Since no metadata found on Spotify, going with the first result" ) else: # filter out videos that do not have a similar length to the Spotify song duration_tolerance = 55 max_duration_tolerance = 60 possible_videos_by_duration = [] log.info("Target Duration: " + internals.videotime_from_seconds( self.meta_tags["duration"])) # start with a reasonable duration_tolerance, and increment duration_tolerance # until one of the Youtube results falls within the correct duration or # the duration_tolerance has reached the max_duration_tolerance while len(possible_videos_by_duration) == 0: possible_videos_by_duration = list( filter( lambda x: abs(x["seconds"] - self.meta_tags[ "duration"]) <= duration_tolerance, videos, )) duration_tolerance += 1 if duration_tolerance > max_duration_tolerance: log.error("{0} by {1} was not found.".format( self.meta_tags["name"], self.meta_tags["artists"][0]["name"], )) return None result = possible_videos_by_duration[0] if result: url = "http://youtube.com/watch?v={0}".format(result["link"]) else: url = None return url
def test_video_time_from_seconds(sec_duration, str_duration): duration = internals.videotime_from_seconds(sec_duration) assert duration == str_duration