From 5ec1811fa7499386f324f13a3a49dbe7d8ea6741 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 19 Jun 2021 13:51:37 +0200 Subject: Fix youtube sometimes needing a redirect for media url --- src/plugins/Youtube.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'src/plugins/Youtube.cpp') diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index b45b5fe..717bc8f 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -1981,6 +1981,32 @@ R"END( return nullptr; } + // Sometimes youtube returns a redirect url (not in the header but in the body...). + // TODO: Find why this happens and if there is a way bypass it. + static std::string get_playback_url_recursive(std::string playback_url) { + const int max_redirects = 5; + for(int i = 0; i < max_redirects; ++i) { + std::string response_headers; + if(download_head_to_string(playback_url, response_headers, true) != DownloadResult::OK) + return ""; + + std::string content_type = header_extract_value(response_headers, "content-type"); + if(content_type.empty()) + return ""; + + if(string_starts_with(content_type, "video") || string_starts_with(content_type, "audio")) + return playback_url; + + // TODO: Download head and body in one request + std::string new_url; + if(download_to_string(playback_url, new_url, {}, true) != DownloadResult::OK) + return ""; + + playback_url = std::move(new_url); + } + return playback_url; + } + std::string YoutubeVideoPage::get_video_url(int max_height, bool &has_embedded_audio) { if(!hls_manifest_url.empty()) { has_embedded_audio = true; @@ -2007,7 +2033,7 @@ R"END( print_chosen_format(*chosen_video_format); has_embedded_audio = chosen_video_format->has_embedded_audio; - return chosen_video_format->base.url; + return get_playback_url_recursive(chosen_video_format->base.url); } std::string YoutubeVideoPage::get_audio_url() { @@ -2017,7 +2043,7 @@ R"END( // TODO: The "worst" (but still good) quality audio is chosen right now because youtube seeking freezes for up to 15 seconds when choosing the best quality const YoutubeAudioFormat *chosen_audio_format = &audio_formats.back(); fprintf(stderr, "Choosing youtube audio format: bitrate: %d, mime type: %s\n", chosen_audio_format->base.bitrate, chosen_audio_format->base.mime_type.c_str()); - return chosen_audio_format->base.url; + return get_playback_url_recursive(chosen_audio_format->base.url); } // Returns -1 if timestamp is in an invalid format -- cgit v1.2.3