Skip to content

Commit

Permalink
[hotstart] fix and improve extraction
Browse files Browse the repository at this point in the history
- fix format extraction (closes #26690)
- extract thumbnail URL (closes #16079, closes #20412)
- support country specific playlist URLs (closes #23496)
- select the last id in video URL (closes #26412)
  • Loading branch information
remitamine committed Dec 12, 2020
1 parent bcc8ef0 commit bb38a12
Showing 1 changed file with 69 additions and 27 deletions.
96 changes: 69 additions & 27 deletions youtube_dl/extractor/hotstar.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import hashlib
import hmac
import json
import re
import time
import uuid
Expand All @@ -25,43 +26,50 @@
class HotStarBaseIE(InfoExtractor):
_AKAMAI_ENCRYPTION_KEY = b'\x05\xfc\x1a\x01\xca\xc9\x4b\xc4\x12\xfc\x53\x12\x07\x75\xf9\xee'

def _call_api_impl(self, path, video_id, query):
def _call_api_impl(self, path, video_id, headers, query, data=None):
st = int(time.time())
exp = st + 6000
auth = 'st=%d~exp=%d~acl=/*' % (st, exp)
auth += '~hmac=' + hmac.new(self._AKAMAI_ENCRYPTION_KEY, auth.encode(), hashlib.sha256).hexdigest()
response = self._download_json(
'https://api.hotstar.com/' + path, video_id, headers={
'hotstarauth': auth,
'x-country-code': 'IN',
'x-platform-code': 'JIO',
}, query=query)
if response['statusCode'] != 'OK':
raise ExtractorError(
response['body']['message'], expected=True)
return response['body']['results']
h = {'hotstarauth': auth}
h.update(headers)
return self._download_json(
'https://api.hotstar.com/' + path,
video_id, headers=h, query=query, data=data)

def _call_api(self, path, video_id, query_name='contentId'):
return self._call_api_impl(path, video_id, {
response = self._call_api_impl(path, video_id, {
'x-country-code': 'IN',
'x-platform-code': 'JIO',
}, {
query_name: video_id,
'tas': 10000,
})
if response['statusCode'] != 'OK':
raise ExtractorError(
response['body']['message'], expected=True)
return response['body']['results']

def _call_api_v2(self, path, video_id):
return self._call_api_impl(
'%s/in/contents/%s' % (path, video_id), video_id, {
'desiredConfig': 'encryption:plain;ladder:phone,tv;package:hls,dash',
'client': 'mweb',
'clientVersion': '6.18.0',
'deviceId': compat_str(uuid.uuid4()),
'osName': 'Windows',
'osVersion': '10',
})
def _call_api_v2(self, path, video_id, headers, query=None, data=None):
h = {'X-Request-Id': compat_str(uuid.uuid4())}
h.update(headers)
try:
return self._call_api_impl(
path, video_id, h, query, data)
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError):
if e.cause.code == 402:
self.raise_login_required()
message = self._parse_json(e.cause.read().decode(), video_id)['message']
if message in ('Content not available in region', 'Country is not supported'):
raise self.raise_geo_restricted(message)
raise ExtractorError(message)
raise e


class HotStarIE(HotStarBaseIE):
IE_NAME = 'hotstar'
_VALID_URL = r'https?://(?:www\.)?hotstar\.com/(?:.+?[/-])?(?P<id>\d{10})'
_VALID_URL = r'https?://(?:www\.)?hotstar\.com/(?:.+[/-])?(?P<id>\d{10})'
_TESTS = [{
# contentData
'url': 'https://www.hotstar.com/can-you-not-spread-rumours/1000076273',
Expand Down Expand Up @@ -92,8 +100,13 @@ class HotStarIE(HotStarBaseIE):
# only available via api v2
'url': 'https://www.hotstar.com/tv/ek-bhram-sarvagun-sampanna/s-2116/janhvi-targets-suman/1000234847',
'only_matching': True,
}, {
'url': 'https://www.hotstar.com/in/tv/start-music/1260005217/cooks-vs-comalis/1100039717',
'only_matching': True,
}]
_GEO_BYPASS = False
_DEVICE_ID = None
_USER_TOKEN = None

def _real_extract(self, url):
video_id = self._match_id(url)
Expand Down Expand Up @@ -121,7 +134,30 @@ def _real_extract(self, url):
headers = {'Referer': url}
formats = []
geo_restricted = False
playback_sets = self._call_api_v2('h/v2/play', video_id)['playBackSets']

if not self._USER_TOKEN:
self._DEVICE_ID = compat_str(uuid.uuid4())
self._USER_TOKEN = self._call_api_v2('um/v3/users', video_id, {
'X-HS-Platform': 'PCTV',
'Content-Type': 'application/json',
}, data=json.dumps({
'device_ids': [{
'id': self._DEVICE_ID,
'type': 'device_id',
}],
}).encode())['user_identity']

playback_sets = self._call_api_v2(
'play/v2/playback/content/' + video_id, video_id, {
'X-HS-Platform': 'web',
'X-HS-AppVersion': '6.99.1',
'X-HS-UserToken': self._USER_TOKEN,
}, query={
'device-id': self._DEVICE_ID,
'desired-config': 'encryption:plain',
'os-name': 'Windows',
'os-version': '10',
})['data']['playBackSets']
for playback_set in playback_sets:
if not isinstance(playback_set, dict):
continue
Expand Down Expand Up @@ -163,27 +199,30 @@ def _real_extract(self, url):
for f in formats:
f.setdefault('http_headers', {}).update(headers)

image = try_get(video_data, lambda x: x['image']['h'], compat_str)

return {
'id': video_id,
'title': title,
'thumbnail': 'https://img1.hotstarext.com/image/upload/' + image if image else None,
'description': video_data.get('description'),
'duration': int_or_none(video_data.get('duration')),
'timestamp': int_or_none(video_data.get('broadcastDate') or video_data.get('startDate')),
'formats': formats,
'channel': video_data.get('channelName'),
'channel_id': video_data.get('channelId'),
'channel_id': str_or_none(video_data.get('channelId')),
'series': video_data.get('showName'),
'season': video_data.get('seasonName'),
'season_number': int_or_none(video_data.get('seasonNo')),
'season_id': video_data.get('seasonId'),
'season_id': str_or_none(video_data.get('seasonId')),
'episode': title,
'episode_number': int_or_none(video_data.get('episodeNo')),
}


class HotStarPlaylistIE(HotStarBaseIE):
IE_NAME = 'hotstar:playlist'
_VALID_URL = r'https?://(?:www\.)?hotstar\.com/tv/[^/]+/s-\w+/list/[^/]+/t-(?P<id>\w+)'
_VALID_URL = r'https?://(?:www\.)?hotstar\.com/(?:[a-z]{2}/)?tv/[^/]+/s-\w+/list/[^/]+/t-(?P<id>\w+)'
_TESTS = [{
'url': 'https://www.hotstar.com/tv/savdhaan-india/s-26/list/popular-clips/t-3_2_26',
'info_dict': {
Expand All @@ -193,6 +232,9 @@ class HotStarPlaylistIE(HotStarBaseIE):
}, {
'url': 'https://www.hotstar.com/tv/savdhaan-india/s-26/list/extras/t-2480',
'only_matching': True,
}, {
'url': 'https://www.hotstar.com/us/tv/masterchef-india/s-830/list/episodes/t-1_2_830',
'only_matching': True,
}]

def _real_extract(self, url):
Expand Down

15 comments on commit bb38a12

@GourangaDas
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOT WORKING

youtube-dl https://www.hotstar.com/in/tv/kopalkundola/1260014391/bhairabs-clever-disguise/1000247592 -F

[hotstar] 1000247592: Downloading webpage
[hotstar] 1000247592: Downloading JSON metadata
ERROR: 1000247592: Failed to parse JSON (caused by ValueError('Expecting value: line 1 column 1 (char 0)',)); please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; type youtube-dl -U to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

@remitamine
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

youtube-dl https://www.hotstar.com/in/tv/kopalkundola/1260014391/bhairabs-clever-disguise/1000247592
[hotstar] 1000247592: Downloading webpage
[hotstar] 1000247592: Downloading JSON metadata
[hotstar] 1000247592: Downloading JSON metadata
[hotstar] 1000247592: Downloading m3u8 information
[hotstar] 1000247592: Downloading m3u8 information
[hotstar] 1000247592: Downloading MPD manifest
[hotstar] 1000247592: Downloading m3u8 information
[hotstar] 1000247592: Downloading m3u8 information
[hotstar] 1000247592: Downloading MPD manifest
[hotstar] 1000247592: Downloading m3u8 information
[hotstar] 1000247592: Downloading MPD manifest
[download] Destination: Bhairab's Clever Disguise-1000247592.mp4
...

@GourangaDas
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yaah, Now its working

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

youtube-dl "https://www.hotstar.com/in/tv/saanjher-baati/1260007251/chinis-innocent-demand/1000256251"
[hotstar] 1000256251: Downloading webpage
[hotstar] 1000256251: Downloading JSON metadata
ERROR: 1000256251: Failed to parse JSON (caused by ValueError('Expecting value: line 1 column 1 (char 0)',)); please report this issue on https://yt-dl.org/bug. Make sure you are using the latest version; type youtube-dl -U to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

can u please tell me how to fix this issue?

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can someone please tell me how to add my credentials to download VIP/Premium videos of hotstar, i have logins of hotstar but cant b able to download VIP/Premium or videos available for registered users, i also tried using --username MYUSERNAME --password MYPASSWORD option

@theincognito-inc
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Admire1231 Can you post a vip link here? Premium videos won't work mostly, because they are all DRM videos.

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://www.hotstar.com/us/tv/mohor/1260012894/shankha-yells-at-mohor/1000258544
this video is working perfectly in browser with account credentials but when i provide my account details to youtube-dl via --username --password option for downloading it still not working showing this: http://prntscr.com/109b0bi

@theincognito-inc
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Admire1231 The url you provided gets downloaded without credentials (PS: I am in India, and my VPN gets detected by Hotstar, when I change it to US).

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

till the time u check this video it becomes non-vip as hotstar mostly made it non-vip after the day of upload can u please try some VIP (v) marked video / latest episode of any tv serial

@Admire1231 The url you provided gets downloaded without credentials (PS: I am in India, and my VPN gets detected by Hotstar, when I change it to US).

@theincognito-inc
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Admire1231 I tried it with a VIP video today. You are right. I cannot download it using youtube-dl. Tried the username, password way and the cookies way. No effect. Can watch it via browser, and can download using other tools.

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Admire1231 I tried it with a VIP video today. You are right. I cannot download it using youtube-dl. Tried the username, password way and the cookies way. No effect. Can watch it via browser, and can download using other tools.

looking forward for solution of it and update of hotstar for VIP videos or any other solution u can suggest?

@theincognito-inc
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure we can't discuss 3rd party tools here. Do you have discord? Or reddit?

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure we can't discuss 3rd party tools here. Do you have discord? Or reddit?

yup i have reddit with the same name Admire1231

@OyeRishab
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Admire1231 I tried it with a VIP video today. You are right. I cannot download it using youtube-dl. Tried the username, password way and the cookies way. No effect. Can watch it via browser, and can download using other tools.

looking forward for solution of it and update of hotstar for VIP videos or any other solution u can suggest?

Does this work anymore??

@Admire1231
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

youtube-dl --verbose "https://www.hotstar.com/i
n/tv/bigg-boss/14455/day-1-in-the-house/1260070577"
[debug] System config: []
[debug] User config: []
[debug] Custom config: []
[debug] Command-line args: ['--verbose', 'https://www.hotstar.com/in/tv/bigg-bos
s/14455/day-1-in-the-house/1260070577']
[debug] Encodings: locale cp1252, fs mbcs, out cp437, pref cp1252
[debug] youtube-dl version 2021.06.06
[debug] Python version 3.4.4 (CPython) - Windows-2012ServerR2-6.3.9600
[debug] exe versions: ffmpeg N-92391-g07bc603757
[debug] Proxy map: {}
[hotstar] 1260070577: Downloading webpage
[hotstar] 1260070577: Downloading JSON metadata
ERROR: 1260070577: Failed to parse JSON (caused by ValueError('Expecting value:
line 1 column 1 (char 0)',)); please report this issue on https://yt-dl.org/bug
. Make sure you are using the latest version; type youtube-dl -U to update. B
e sure to call youtube-dl with the --verbose flag and include its complete outpu
t.
Traceback (most recent call last):
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\extractor\common.py", line 906, in parse_json
File "C:\Python\Python34\lib\json_init
.py", line 318, in loads
File "C:\Python\Python34\lib\json\decoder.py", line 343, in decode
File "C:\Python\Python34\lib\json\decoder.py", line 361, in raw_decode
ValueError: Expecting value: line 1 column 1 (char 0)
Traceback (most recent call last):
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\extractor\common.py", line 906, in parse_json
File "C:\Python\Python34\lib\json_init
.py", line 318, in loads
File "C:\Python\Python34\lib\json\decoder.py", line 343, in decode
File "C:\Python\Python34\lib\json\decoder.py", line 361, in raw_decode
ValueError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\YoutubeDL.py", line 815, in wrapper
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\YoutubeDL.py", line 836, in __extract_info
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\extractor\common.py", line 534, in extract
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\extractor\hotstar.py", line 146, in _real_extract
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\extractor\hotstar.py", line 63, in _call_api_v2
File "C:\Users\dst\AppData\Roaming\Build archive\youtube-dl\ytdl-org\tmpkqxnwl
31\build\youtube_dl\extractor\common.py", line 910, in _parse_json
youtube_dl.utils.ExtractorError: 1260070577: Failed to parse JSON (caused by Va
lueError('Expecting value: line 1 column 1 (char 0)',)); please report this issu
e on https://yt-dl.org/bug . Make sure you are using the latest version; type y
outube-dl -U to update. Be sure to call youtube-dl with the --verbose flag and
include its complete output.

Can u fix this please file is playable in browser

Please sign in to comment.