From 53b84bbe9daffd56002afb657ecd4871d6196861 Mon Sep 17 00:00:00 2001 From: vefve Date: Wed, 29 Nov 2023 06:02:11 +0530 Subject: [PATCH 1/6] [JioCinema] Add extractor --- yt_dlp/extractor/_extractors.py | 5 + yt_dlp/extractor/jiocinema.py | 326 ++++++++++++++++++++++++++++++++ 2 files changed, 331 insertions(+) create mode 100644 yt_dlp/extractor/jiocinema.py diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py index 9b96bd5b4..e35af16ee 100644 --- a/yt_dlp/extractor/_extractors.py +++ b/yt_dlp/extractor/_extractors.py @@ -858,6 +858,11 @@ from .japandiet import ( SangiinIE, ) from .jeuxvideo import JeuxVideoIE +from .jiocinema import ( + JioCinemaTVIE, + JioCinemaMovieIE, + JioCinemaTVSeasonIE +) from .jiosaavn import ( JioSaavnSongIE, JioSaavnAlbumIE, diff --git a/yt_dlp/extractor/jiocinema.py b/yt_dlp/extractor/jiocinema.py new file mode 100644 index 000000000..68f68f118 --- /dev/null +++ b/yt_dlp/extractor/jiocinema.py @@ -0,0 +1,326 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor + +import json +import math +import re +import uuid + + +class JioCinemaBaseIE(InfoExtractor): + deviceId = None + auth_token = None + + def _get_auth_token(self): + token_endpoint = "https://auth-jiocinema.voot.com/tokenservice/apis/v4/guest" + + headers = { + 'authority': 'auth-jiocinema.voot.com', + 'accept': 'application/json, text/plain, */*', + 'accept-language': 'en-IN,en;q=0.9', + 'content-type': 'application/json', + 'dnt': '1', + 'origin': 'https://www.jiocinema.com', + 'referer': 'https://www.jiocinema.com/', + 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'cross-site', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' + } + + payload = { + "appName": "RJIL_JioCinema", + "deviceType": "phone", + "os": "ios", + "deviceId": self.deviceId, + "freshLaunch": True, + "adId": self.deviceId, + "appVersion": "23.11.22.0-dc532c79" + } + + token_response = self._download_json(url_or_request=token_endpoint, video_id=None, note='Fetching Auth Token', data=bytes(json.dumps(payload), encoding='utf8'), headers=headers) + + if "authToken" in token_response: + return token_response["authToken"] + + return None + + def _get_media_metadata(self, media_id): + media_metadata = {} + metadata_endpoint_template = 'https://content-jiovoot.voot.com/psapi/voot/v1/voot-web/content/query/asset-details?&ids=include:{media_id}&responseType=common&devicePlatformType=desktop' + + metadata_endpoint = metadata_endpoint_template.format(media_id=media_id) + + media_metadata_response = self._download_json(metadata_endpoint, None, 'Fetching Episode Metadata') + + if media_metadata_response and 'result' in media_metadata_response and media_metadata_response['result']: + media_metadata_response = media_metadata_response['result'][0] + + media_metadata['showName'] = media_metadata_response['showName'] + media_metadata['title'] = media_metadata_response['fullTitle'] + media_metadata['shortTitle'] = media_metadata_response['shortTitle'] + media_metadata['shortSynopsis'] = media_metadata_response['shortSynopsis'] + media_metadata['fullSynopsis'] = media_metadata_response['fullSynopsis'] + media_metadata['showName'] = media_metadata_response['showName'] + media_metadata['season'] = media_metadata_response['season'] + media_metadata['episode'] = media_metadata_response['episode'] + media_metadata['multiTrackAudioEnabled'] = media_metadata_response['multiTrackAudioEnabled'] + media_metadata['introStart'] = media_metadata_response['introStart'] + media_metadata['introEnd'] = media_metadata_response['introEnd'] + media_metadata['recapStart'] = media_metadata_response['recapStart'] + media_metadata['recapEnd'] = media_metadata_response['recapEnd'] + media_metadata['creditStart'] = media_metadata_response['creditStart'] + media_metadata['creditEnd'] = media_metadata_response['creditEnd'] + media_metadata['is4KSupported'] = media_metadata_response['is4KSupported'] + media_metadata['is1080PSupported'] = media_metadata_response['is1080PSupported'] + media_metadata['isDolbySupported'] = media_metadata_response['isDolbySupported'] + media_metadata['hasSubtitles'] = media_metadata_response['hasSubtitles'] + media_metadata['subtitles'] = media_metadata_response['subtitles'] + + return media_metadata + + def _get_stream_url(self, auth_token, media_id): + stream_endpoint = 'https://apis-jiovoot.voot.com/playbackjv/v4/{media_id}' + + stream_endpoint = stream_endpoint.format(media_id=media_id) + + headers = { + 'authority': 'apis-jiovoot.voot.com', + 'accept': 'application/json, text/plain, */*', + 'accept-language': 'en-IN,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,hi;q=0.6', + 'accesstoken': auth_token, + 'appname': 'RJIL_JioCinema', + 'content-type': 'application/json', + 'deviceid': self.deviceId, + 'dnt': '1', + 'origin': 'https://www.jiocinema.com', + 'referer': 'https://www.jiocinema.com/', + 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'cross-site', + 'uniqueid': self.deviceId, + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', + 'versioncode': '2311030', + 'x-platform': 'androidweb', + 'x-platform-token': 'web' + } + + payload = { + "4k": False, + "ageGroup": "18+", + "appVersion": "3.4.0", + "bitrateProfile": "xhdpi", + "capability": { + "drmCapability": { + "aesSupport": "yes", + "fairPlayDrmSupport": "yes", + "playreadyDrmSupport": "none", + "widevineDRMSupport": "yes" + }, + "frameRateCapability": [ + { + "frameRateSupport": "30fps", + "videoQuality": "1440p" + } + ] + }, + "continueWatchingRequired": True, + "dolby": False, + "downloadRequest": False, + "hevc": False, + "kidsSafe": False, + "manufacturer": "Mac OS", + "model": "Mac OS", + "multiAudioRequired": True, + "osVersion": "10.15.7", + "parentalPinValid": True + } + + stream_response = self._download_json(url_or_request=stream_endpoint, video_id=None, note='Extracting Stream URL', data=bytes(json.dumps(payload), encoding='utf8'), headers=headers) + + for url_data in stream_response['data']['playbackUrls']: + if url_data['encryption'] == 'widevine': + return url_data['url'] + + def _real_initialize(self): + super()._real_initialize() + if self.deviceId is None: + self.deviceId = str(uuid.uuid4()) + + self.auth_token = self._get_auth_token() + + def _real_extract(self, url): + media_name, season_number, episode_name, media_id = re.match(self._VALID_URL, url).groups() + + if not self.auth_token: + return + + media_metadata = self._get_media_metadata(media_id) + mpd_url = self._get_stream_url(self.auth_token, media_id) + + formats = [] + formats.extend(self._extract_mpd_formats(mpd_url, media_id)) + + self._sort_formats(formats) + response_dict = { + 'id': media_id, + 'formats': formats, + } + response_dict.update(media_metadata) + return response_dict + + +class JioCinemaTVIE(JioCinemaBaseIE): + _VALID_URL = r'https?://(?:www\.)?jiocinema\.com/tv-shows/(?P[a-zA-Z0-9\-]*)/(?P[0-9]*)/(?P[a-zA-Z0-9\-]*)/(?P[a-zA-Z0-9\-]*)' + _TEST = { + 'url': 'https://www.jiocinema.com/tv-shows/cedric/2/mister-fixit/3769452', + 'info_dict': { + 'id': '3769452', + 'ext': 'mp4', + 'title': 'Mister Fixit', + 'shortTitle': 'Mister Fixit', + 'shortSynopsis': 'Cedric offers to fix Chen\'s broken walkman, however he realises that it is much harder than he thought it\'d be. He thinks of taking help from his father and Poppy, but th', + 'fullSynopsis': 'Cedric offers to fix Chen\'s broken walkman, however he realises that it is much harder than he thought it\'d be. He thinks of taking help from his father and Poppy, but they get into an argument over who is a better handyman. Will Cedric be able to fix Chen\'s walkman as promised?', + 'is4KSupported': False, + 'is1080PSupported': False, + 'isDolbySupported': False, + 'introStart': 0, + 'introEnd': 5, + 'creditStart': 765, + 'creditEnd': 770, + 'recapStart': 0, + 'recapEnd': 0, + 'hasSubtitles': False, + 'multiTrackAudioEnabled': False, + 'season': '2', + 'showName': 'Cedric', + 'episode': '1' + }, + 'params': { + 'skip_download': True, + 'format': 'bestvideo' + } + } + + +class JioCinemaMovieIE(JioCinemaBaseIE): + _VALID_URL = r'https?://(?:www\.)?jiocinema\.com/movies/(?P[a-zA-Z0-9\-]*)/?(?P[0-9]*)?/?(?P[a-zA-Z0-9\-]*)?/(?P[a-zA-Z0-9\-]*)' + _TEST = { + 'url': 'https://www.jiocinema.com/movies/i-choose-you-pokemon-the-movie/3777402', + 'info_dict': { + 'id': '3777402', + 'ext': 'mp4', + 'title': 'I Choose You! - Pokemon the Movie', + 'shortTitle': 'I Choose You! - Pokemon the Movie', + 'shortSynopsis': 'When Ash Ketchum oversleeps on his 10th birthday, he ends up with a stubborn Pikachu instead of the first partner Pokémon he wanted! But after a rocky start, Ash and Pika', + 'fullSynopsis': 'When Ash Ketchum oversleeps on his 10th birthday, he ends up with a stubborn Pikachu instead of the first partner Pokémon he wanted! But after a rocky start, Ash and Pikachu become close friends and true partners—and when they catch a rare glimpse of the Legendary Pokémon Ho-Oh in flight, they make plans to seek it out together, guided by the Rainbow Wing it leaves behind. Trainers Verity and Sorrel join Ash on his journey. Along the way, Ash catches an abandoned Charmander, raises a Pokémon from Caterpie to Butterfree and then releases it to follow its heart, and meets the mysterious Mythical Pokémon Marshadow. When they near their goal, the arrogant Cross—Charmander\'s former Trainer—stands in their way! Can Ash and Pikachu defeat this powerful Trainer and reach Ho-Oh as they promised, or will their journey end here?', + 'is4KSupported': False, + 'is1080PSupported': False, + 'isDolbySupported': False, + 'introStart': 0, + 'introEnd': 0, + 'creditStart': 0, + 'creditEnd': 0, + 'recapStart': 0, + 'recapEnd': 0, + 'showName': '', + 'episode': '', + 'season': '', + 'hasSubtitles': False, + 'multiTrackAudioEnabled': False + }, + 'params': { + 'skip_download': True, + 'format': 'bestvideo' + } + } + + +class JioCinemaTVSeasonIE(JioCinemaBaseIE): + _VALID_URL = r'https?://(?:www\.)?jiocinema\.com/tv-shows/(?P[a-zA-Z0-9\-]*)/(?P[a-zA-Z0-9\-]*)$' + _TEST = { + 'url': 'https://www.jiocinema.com/tv-shows/cedric/3768448', + 'info_dict': { + 'id': '3769333', + 'ext': 'mp4', + 'title': 'I Love School', + 'shortTitle': 'I Love School', + 'shortSynopsis': 'Cedric loves going to school but his report card doesn\'t reflect his enthusiasm. Cedric\'s dad scolds him for his poor performance but he is least bothered and starts drea', + 'fullSynopsis': 'Cedric loves going to school but his report card doesn\'t reflect his enthusiasm. Cedric\'s dad scolds him for his poor performance but he is least bothered and starts dreaming about his teacher at school, with whom he is in love with.', + 'is4KSupported': False, + 'is1080PSupported': False, + 'isDolbySupported': False, + 'introStart': 0, + 'introEnd': 5, + 'creditStart': 764, + 'creditEnd': 769, + 'recapStart': 0, + 'recapEnd': 0, + 'showName': 'Cedric', + 'episode': '1', + 'season': '1', + 'hasSubtitles': False, + 'multiTrackAudioEnabled': False + }, + 'params': { + 'skip_download': True, + 'format': 'bestvideo' + } + } + + def _real_extract(self, url): + playlist_entries = [] + playlist_name, playlist_id = re.match(self._VALID_URL, url).groups() + season_data_url_template = 'https://content-jiovoot.voot.com/psapi/voot/v1/voot-web/view/show/{playlist_id}?responseType=common&devicePlatformType=desktop&layoutCohort=default' + season_data_url = season_data_url_template.format(playlist_id=playlist_id) + season_data_response = self._download_json(season_data_url, None, 'Fetching Season Info') + season_id_list = self._extract_season_id_list(season_data_response) + playlist_entries = self._fetch_episode_data(season_id_list) + return self.playlist_result(playlist_entries) + + def _extract_season_id_list(self, season_data_response): + season_count = 0 + season_id_list = [] + + for tray in season_data_response['trays']: + if tray['title'] == 'Episodes': + season_count = tray['totalTrayTabs'] + for season in tray['trayTabs']: + season_id_list.append(season['id']) + break + return season_id_list + + def _fetch_episode_data(self, season_id_list): + episode_url_list = [] + for season_id in season_id_list: + episode_list_template = 'https://content-jiovoot.voot.com/psapi/voot/v1/voot-web/content/generic/series-wise-episode?sort=episode%3Aasc&id={season_id}&responseType=common&page={page_number}' + page_number = 1 + total_pages = 1 + + episode_details_list_url = episode_list_template.format(season_id=season_id, page_number=page_number) + + paginated_episode_list = self._download_json(episode_details_list_url, None, 'Fetching Episode List') + episode_url_list.extend(self._extract_episode_urls(paginated_episode_list)) + total_pages = math.ceil(paginated_episode_list['totalAsset'] / 10) + + page_number += 1 + while page_number <= total_pages: + episode_details_list_url = episode_list_template.format(season_id=season_id, page_number=page_number) + paginated_episode_list = self._download_json(episode_details_list_url, None, 'Fetching Episode List') + episode_url_list.extend(self._extract_episode_urls(paginated_episode_list)) + page_number += 1 + return episode_url_list + + def _extract_episode_urls(self, episode_response_list): + episode_url_list = [] + for episode in episode_response_list['result']: + episode_url_list.append(self.url_result(episode['slug'])) + return episode_url_list From 1becd335d639f361249e9d85c2b5535b20e74a7f Mon Sep 17 00:00:00 2001 From: vefve Date: Wed, 29 Nov 2023 06:15:53 +0530 Subject: [PATCH 2/6] [JioCinema] Removing unused variable --- yt_dlp/extractor/jiocinema.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/yt_dlp/extractor/jiocinema.py b/yt_dlp/extractor/jiocinema.py index 68f68f118..af97b69d2 100644 --- a/yt_dlp/extractor/jiocinema.py +++ b/yt_dlp/extractor/jiocinema.py @@ -287,12 +287,10 @@ class JioCinemaTVSeasonIE(JioCinemaBaseIE): return self.playlist_result(playlist_entries) def _extract_season_id_list(self, season_data_response): - season_count = 0 season_id_list = [] for tray in season_data_response['trays']: if tray['title'] == 'Episodes': - season_count = tray['totalTrayTabs'] for season in tray['trayTabs']: season_id_list.append(season['id']) break From f56c7421ee3fdc6750eb4e43be5291a82b3ed2aa Mon Sep 17 00:00:00 2001 From: vefve Date: Thu, 30 Nov 2023 06:15:26 +0530 Subject: [PATCH 3/6] Removing unnecessary headers and using standard field names in info_dict. --- yt_dlp/extractor/jiocinema.py | 146 +++++++--------------------------- 1 file changed, 30 insertions(+), 116 deletions(-) diff --git a/yt_dlp/extractor/jiocinema.py b/yt_dlp/extractor/jiocinema.py index af97b69d2..145b96fd2 100644 --- a/yt_dlp/extractor/jiocinema.py +++ b/yt_dlp/extractor/jiocinema.py @@ -16,23 +16,6 @@ class JioCinemaBaseIE(InfoExtractor): def _get_auth_token(self): token_endpoint = "https://auth-jiocinema.voot.com/tokenservice/apis/v4/guest" - headers = { - 'authority': 'auth-jiocinema.voot.com', - 'accept': 'application/json, text/plain, */*', - 'accept-language': 'en-IN,en;q=0.9', - 'content-type': 'application/json', - 'dnt': '1', - 'origin': 'https://www.jiocinema.com', - 'referer': 'https://www.jiocinema.com/', - 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'cross-site', - 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' - } - payload = { "appName": "RJIL_JioCinema", "deviceType": "phone", @@ -43,7 +26,7 @@ class JioCinemaBaseIE(InfoExtractor): "appVersion": "23.11.22.0-dc532c79" } - token_response = self._download_json(url_or_request=token_endpoint, video_id=None, note='Fetching Auth Token', data=bytes(json.dumps(payload), encoding='utf8'), headers=headers) + token_response = self._download_json(url_or_request=token_endpoint, video_id=None, note='Fetching Auth Token', data=bytes(json.dumps(payload), encoding='utf8')) if "authToken" in token_response: return token_response["authToken"] @@ -61,26 +44,15 @@ class JioCinemaBaseIE(InfoExtractor): if media_metadata_response and 'result' in media_metadata_response and media_metadata_response['result']: media_metadata_response = media_metadata_response['result'][0] - media_metadata['showName'] = media_metadata_response['showName'] + if media_metadata_response['showName']: + media_metadata['series'] = media_metadata_response['showName'] media_metadata['title'] = media_metadata_response['fullTitle'] - media_metadata['shortTitle'] = media_metadata_response['shortTitle'] - media_metadata['shortSynopsis'] = media_metadata_response['shortSynopsis'] - media_metadata['fullSynopsis'] = media_metadata_response['fullSynopsis'] - media_metadata['showName'] = media_metadata_response['showName'] - media_metadata['season'] = media_metadata_response['season'] - media_metadata['episode'] = media_metadata_response['episode'] - media_metadata['multiTrackAudioEnabled'] = media_metadata_response['multiTrackAudioEnabled'] - media_metadata['introStart'] = media_metadata_response['introStart'] - media_metadata['introEnd'] = media_metadata_response['introEnd'] - media_metadata['recapStart'] = media_metadata_response['recapStart'] - media_metadata['recapEnd'] = media_metadata_response['recapEnd'] - media_metadata['creditStart'] = media_metadata_response['creditStart'] - media_metadata['creditEnd'] = media_metadata_response['creditEnd'] - media_metadata['is4KSupported'] = media_metadata_response['is4KSupported'] - media_metadata['is1080PSupported'] = media_metadata_response['is1080PSupported'] - media_metadata['isDolbySupported'] = media_metadata_response['isDolbySupported'] - media_metadata['hasSubtitles'] = media_metadata_response['hasSubtitles'] - media_metadata['subtitles'] = media_metadata_response['subtitles'] + media_metadata['description'] = media_metadata_response['fullSynopsis'] + if media_metadata_response['season']: + media_metadata['season_number'] = int(media_metadata_response['season']) + if media_metadata_response['episode']: + media_metadata['episode_number'] = int(media_metadata_response['episode']) + # media_metadata['subtitles'] = media_metadata_response['subtitles'] return media_metadata @@ -90,31 +62,12 @@ class JioCinemaBaseIE(InfoExtractor): stream_endpoint = stream_endpoint.format(media_id=media_id) headers = { - 'authority': 'apis-jiovoot.voot.com', - 'accept': 'application/json, text/plain, */*', - 'accept-language': 'en-IN,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,hi;q=0.6', 'accesstoken': auth_token, - 'appname': 'RJIL_JioCinema', - 'content-type': 'application/json', - 'deviceid': self.deviceId, - 'dnt': '1', - 'origin': 'https://www.jiocinema.com', - 'referer': 'https://www.jiocinema.com/', - 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'cross-site', - 'uniqueid': self.deviceId, - 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', - 'versioncode': '2311030', - 'x-platform': 'androidweb', - 'x-platform-token': 'web' + 'x-platform': 'androidweb' } payload = { - "4k": False, + "4k": True, "ageGroup": "18+", "appVersion": "3.4.0", "bitrateProfile": "xhdpi", @@ -127,15 +80,15 @@ class JioCinemaBaseIE(InfoExtractor): }, "frameRateCapability": [ { - "frameRateSupport": "30fps", - "videoQuality": "1440p" + "frameRateSupport": "60fps", + "videoQuality": "2160p" } ] }, "continueWatchingRequired": True, "dolby": False, "downloadRequest": False, - "hevc": False, + "hevc": True, "kidsSafe": False, "manufacturer": "Mac OS", "model": "Mac OS", @@ -169,7 +122,6 @@ class JioCinemaBaseIE(InfoExtractor): formats = [] formats.extend(self._extract_mpd_formats(mpd_url, media_id)) - self._sort_formats(formats) response_dict = { 'id': media_id, 'formats': formats, @@ -181,28 +133,17 @@ class JioCinemaBaseIE(InfoExtractor): class JioCinemaTVIE(JioCinemaBaseIE): _VALID_URL = r'https?://(?:www\.)?jiocinema\.com/tv-shows/(?P[a-zA-Z0-9\-]*)/(?P[0-9]*)/(?P[a-zA-Z0-9\-]*)/(?P[a-zA-Z0-9\-]*)' _TEST = { - 'url': 'https://www.jiocinema.com/tv-shows/cedric/2/mister-fixit/3769452', + 'url': 'https://www.jiocinema.com/tv-shows/cedric/1/i-love-school/3769333', 'info_dict': { - 'id': '3769452', + 'id': '3769333', 'ext': 'mp4', - 'title': 'Mister Fixit', - 'shortTitle': 'Mister Fixit', - 'shortSynopsis': 'Cedric offers to fix Chen\'s broken walkman, however he realises that it is much harder than he thought it\'d be. He thinks of taking help from his father and Poppy, but th', - 'fullSynopsis': 'Cedric offers to fix Chen\'s broken walkman, however he realises that it is much harder than he thought it\'d be. He thinks of taking help from his father and Poppy, but they get into an argument over who is a better handyman. Will Cedric be able to fix Chen\'s walkman as promised?', - 'is4KSupported': False, - 'is1080PSupported': False, - 'isDolbySupported': False, - 'introStart': 0, - 'introEnd': 5, - 'creditStart': 765, - 'creditEnd': 770, - 'recapStart': 0, - 'recapEnd': 0, - 'hasSubtitles': False, - 'multiTrackAudioEnabled': False, - 'season': '2', - 'showName': 'Cedric', - 'episode': '1' + 'title': 'I Love School', + 'description': 'md5:71cc843e4ec65f62c6fd33cf38920198', + 'series': 'Cedric', + 'season_number': 1, + 'episode_number': 1, + 'episode': 'Episode 1', + 'season': 'Season 1', }, 'params': { 'skip_download': True, @@ -219,23 +160,7 @@ class JioCinemaMovieIE(JioCinemaBaseIE): 'id': '3777402', 'ext': 'mp4', 'title': 'I Choose You! - Pokemon the Movie', - 'shortTitle': 'I Choose You! - Pokemon the Movie', - 'shortSynopsis': 'When Ash Ketchum oversleeps on his 10th birthday, he ends up with a stubborn Pikachu instead of the first partner Pokémon he wanted! But after a rocky start, Ash and Pika', - 'fullSynopsis': 'When Ash Ketchum oversleeps on his 10th birthday, he ends up with a stubborn Pikachu instead of the first partner Pokémon he wanted! But after a rocky start, Ash and Pikachu become close friends and true partners—and when they catch a rare glimpse of the Legendary Pokémon Ho-Oh in flight, they make plans to seek it out together, guided by the Rainbow Wing it leaves behind. Trainers Verity and Sorrel join Ash on his journey. Along the way, Ash catches an abandoned Charmander, raises a Pokémon from Caterpie to Butterfree and then releases it to follow its heart, and meets the mysterious Mythical Pokémon Marshadow. When they near their goal, the arrogant Cross—Charmander\'s former Trainer—stands in their way! Can Ash and Pikachu defeat this powerful Trainer and reach Ho-Oh as they promised, or will their journey end here?', - 'is4KSupported': False, - 'is1080PSupported': False, - 'isDolbySupported': False, - 'introStart': 0, - 'introEnd': 0, - 'creditStart': 0, - 'creditEnd': 0, - 'recapStart': 0, - 'recapEnd': 0, - 'showName': '', - 'episode': '', - 'season': '', - 'hasSubtitles': False, - 'multiTrackAudioEnabled': False + 'description': 'md5:c224c04ce664ac2f41d85e2fb1d49b2f' }, 'params': { 'skip_download': True, @@ -252,23 +177,12 @@ class JioCinemaTVSeasonIE(JioCinemaBaseIE): 'id': '3769333', 'ext': 'mp4', 'title': 'I Love School', - 'shortTitle': 'I Love School', - 'shortSynopsis': 'Cedric loves going to school but his report card doesn\'t reflect his enthusiasm. Cedric\'s dad scolds him for his poor performance but he is least bothered and starts drea', - 'fullSynopsis': 'Cedric loves going to school but his report card doesn\'t reflect his enthusiasm. Cedric\'s dad scolds him for his poor performance but he is least bothered and starts dreaming about his teacher at school, with whom he is in love with.', - 'is4KSupported': False, - 'is1080PSupported': False, - 'isDolbySupported': False, - 'introStart': 0, - 'introEnd': 5, - 'creditStart': 764, - 'creditEnd': 769, - 'recapStart': 0, - 'recapEnd': 0, - 'showName': 'Cedric', - 'episode': '1', - 'season': '1', - 'hasSubtitles': False, - 'multiTrackAudioEnabled': False + 'description': 'md5:71cc843e4ec65f62c6fd33cf38920198', + 'series': 'Cedric', + 'season_number': 1, + 'episode_number': 1, + 'episode': 'Episode 1', + 'season': 'Season 1', }, 'params': { 'skip_download': True, From 03df786397177f0079f0fa76b8312bb09a6a15f7 Mon Sep 17 00:00:00 2001 From: vefve Date: Sat, 9 Dec 2023 13:38:29 +0530 Subject: [PATCH 5/6] Extracting additional m3u8 stream URLs. --- yt_dlp/extractor/jiocinema.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/yt_dlp/extractor/jiocinema.py b/yt_dlp/extractor/jiocinema.py index 145b96fd2..3d3b6a84b 100644 --- a/yt_dlp/extractor/jiocinema.py +++ b/yt_dlp/extractor/jiocinema.py @@ -99,9 +99,16 @@ class JioCinemaBaseIE(InfoExtractor): stream_response = self._download_json(url_or_request=stream_endpoint, video_id=None, note='Extracting Stream URL', data=bytes(json.dumps(payload), encoding='utf8'), headers=headers) + mpd_url = None + m3u8_url = None + for url_data in stream_response['data']['playbackUrls']: if url_data['encryption'] == 'widevine': - return url_data['url'] + mpd_url = url_data['url'] + elif url_data['encryption'] == 'aes128': + m3u8_url = url_data['url'] + + return mpd_url, m3u8_url def _real_initialize(self): super()._real_initialize() @@ -117,10 +124,11 @@ class JioCinemaBaseIE(InfoExtractor): return media_metadata = self._get_media_metadata(media_id) - mpd_url = self._get_stream_url(self.auth_token, media_id) + mpd_url, m3u8_url = self._get_stream_url(self.auth_token, media_id) formats = [] formats.extend(self._extract_mpd_formats(mpd_url, media_id)) + formats.extend(self._extract_m3u8_formats(m3u8_url, media_id)) response_dict = { 'id': media_id, @@ -147,7 +155,7 @@ class JioCinemaTVIE(JioCinemaBaseIE): }, 'params': { 'skip_download': True, - 'format': 'bestvideo' + 'format': 'best' } } @@ -164,7 +172,7 @@ class JioCinemaMovieIE(JioCinemaBaseIE): }, 'params': { 'skip_download': True, - 'format': 'bestvideo' + 'format': 'best' } } @@ -186,7 +194,7 @@ class JioCinemaTVSeasonIE(JioCinemaBaseIE): }, 'params': { 'skip_download': True, - 'format': 'bestvideo' + 'format': 'best' } }