[tiktok] download best quality videos (#8846)
* [tiktok] download best quality videos * [tiktok] code formatting fix * simplify sorting in '_extract_video_urls'
This commit is contained in:
@@ -92,6 +92,7 @@ class TiktokExtractor(Extractor):
|
|||||||
ytdl_media = "video"
|
ytdl_media = "video"
|
||||||
elif self.video and (url := self._extract_video(post)):
|
elif self.video and (url := self._extract_video(post)):
|
||||||
yield Message.Url, url, post
|
yield Message.Url, url, post
|
||||||
|
del post["_fallback"]
|
||||||
if self.cover and (url := self._extract_cover(post, "video")):
|
if self.cover and (url := self._extract_cover(post, "video")):
|
||||||
yield Message.Url, url, post
|
yield Message.Url, url, post
|
||||||
|
|
||||||
@@ -212,13 +213,16 @@ class TiktokExtractor(Extractor):
|
|||||||
|
|
||||||
def _extract_video(self, post):
|
def _extract_video(self, post):
|
||||||
video = post["video"]
|
video = post["video"]
|
||||||
try:
|
urls = self._extract_video_urls(video)
|
||||||
url = video["playAddr"]
|
if not urls:
|
||||||
except KeyError:
|
raise exception.ExtractionError(
|
||||||
raise exception.ExtractionError("Failed to extract video URL, you "
|
f"{post['id']}: Failed to extract video URLs. "
|
||||||
"may need cookies to continue")
|
f"You may need cookies to continue.")
|
||||||
|
|
||||||
|
url = urls[0]
|
||||||
text.nameext_from_url(url, post)
|
text.nameext_from_url(url, post)
|
||||||
post.update({
|
post.update({
|
||||||
|
"_fallback": urls[1:],
|
||||||
"type" : "video",
|
"type" : "video",
|
||||||
"image" : None,
|
"image" : None,
|
||||||
"title" : post["desc"] or f"TikTok video #{post['id']}",
|
"title" : post["desc"] or f"TikTok video #{post['id']}",
|
||||||
@@ -232,6 +236,37 @@ class TiktokExtractor(Extractor):
|
|||||||
post["extension"] = video.get("format", "mp4")
|
post["extension"] = video.get("format", "mp4")
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
def _extract_video_urls(self, video):
|
||||||
|
# First, look for bitrateInfo.
|
||||||
|
# This will include URLs pointing to the best quality videos.
|
||||||
|
if "bitrateInfo" in video:
|
||||||
|
bitrate_info = video["bitrateInfo"]
|
||||||
|
if not isinstance(bitrate_info, list):
|
||||||
|
bitrate_info = [bitrate_info]
|
||||||
|
bitrate_urls = {}
|
||||||
|
for video_info in bitrate_info:
|
||||||
|
play_addr = video_info["PlayAddr"]
|
||||||
|
width = text.parse_int(play_addr.get("Width"))
|
||||||
|
height = text.parse_int(play_addr.get("Height"))
|
||||||
|
size = width * height
|
||||||
|
if size in bitrate_urls:
|
||||||
|
bitrate_urls[size] += play_addr.get("UrlList")
|
||||||
|
else:
|
||||||
|
bitrate_urls[size] = play_addr.get("UrlList").copy()
|
||||||
|
# Sort the URLs by descending quality.
|
||||||
|
sizes = list(bitrate_urls)
|
||||||
|
sizes.sort(reverse=True)
|
||||||
|
urls = [url for size in sizes for url in bitrate_urls[size]]
|
||||||
|
else:
|
||||||
|
urls = []
|
||||||
|
|
||||||
|
# As a fallback, try to look for the root playAddr,
|
||||||
|
# which won't necessarily point to the best quality.
|
||||||
|
if "playAddr" in video:
|
||||||
|
urls.append(video["playAddr"])
|
||||||
|
|
||||||
|
return urls
|
||||||
|
|
||||||
def _extract_audio(self, post):
|
def _extract_audio(self, post):
|
||||||
audio = post["music"]
|
audio = post["music"]
|
||||||
url = audio["playUrl"]
|
url = audio["playUrl"]
|
||||||
|
|||||||
Reference in New Issue
Block a user