aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp109
-rw-r--r--src/plugins/Youtube.cpp107
2 files changed, 120 insertions, 96 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 279cb28..7641f79 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -1346,8 +1346,6 @@ namespace QuickMedia {
pipe_body->set_items(std::move(body_items));
tabs.push_back(Tab{std::move(pipe_body), std::make_unique<PipePage>(this), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "youtube") == 0) {
- check_youtube_dl_installed(plugin_name);
- use_youtube_dl = true;
if(launch_url_type == LaunchUrlType::YOUTUBE_CHANNEL) {
YoutubeChannelPage::create_each_type(this, std::move(launch_url), "", "Channel", tabs);
} else if(launch_url_type == LaunchUrlType::YOUTUBE_VIDEO) {
@@ -3058,8 +3056,6 @@ namespace QuickMedia {
return url.find("pornhub.com") != std::string::npos
|| url.find("xhamster.com") != std::string::npos
|| url.find("spankbang.com") != std::string::npos
- || url.find("youtube.com") != std::string::npos
- || url.find("youtu.be") != std::string::npos
// TODO: Remove when youtube-dl is no longer required to download soundcloud music
|| is_soundcloud(url);
}
@@ -3244,11 +3240,9 @@ namespace QuickMedia {
mgl::Clock update_window_focus_time; // HACK!
std::string youtube_video_id_dummy;
- //const bool is_youtube = youtube_url_extract_id(video_page->get_url(), youtube_video_id_dummy);
+ const bool is_youtube = youtube_url_extract_id(video_page->get_url(), youtube_video_id_dummy);
const bool is_matrix = strcmp(plugin_name, "matrix") == 0;
const bool is_youtube_plugin = strcmp(plugin_name, "youtube") == 0;
- const bool is_youtube = false;
- const bool is_youtube_rel = youtube_url_extract_id(video_page->get_url(), youtube_video_id_dummy);
bool added_recommendations = false;
mgl::Clock time_watched_timer;
@@ -3270,11 +3264,10 @@ namespace QuickMedia {
redirect_focus_to_video_player_window(video_player_window);
XSync(disp, False);
- // TODO: Readd when we no longer depend on yt-dlp
- //SubtitleData subtitle_data;
- //video_page->get_subtitles(subtitle_data);
- //if(!subtitle_data.url.empty())
- // video_player->add_subtitle(subtitle_data.url, subtitle_data.title, "eng");
+ SubtitleData subtitle_data;
+ video_page->get_subtitles(subtitle_data);
+ if(!subtitle_data.url.empty())
+ video_player->add_subtitle(subtitle_data.url, subtitle_data.title, "eng");
update_time_pos = true;
update_window_focus_timer = true;
@@ -3479,7 +3472,7 @@ namespace QuickMedia {
startup_args.resume = false;
startup_args.resource_root = resources_root;
startup_args.monitor_height = video_max_height;
- startup_args.use_youtube_dl = (use_youtube_dl || is_youtube_rel) && !video_page->is_local();
+ startup_args.use_youtube_dl = use_youtube_dl && !video_page->is_local();
startup_args.title = video_title;
startup_args.start_time = start_time;
startup_args.chapters = std::move(video_info.chapters);
@@ -3775,7 +3768,7 @@ namespace QuickMedia {
current_page = previous_page;
go_to_previous_page = true;
break;
- } else if(update_err == VideoPlayer::Error::EXITED && video_player->exit_status == 0 && (!is_matrix || is_youtube_rel)) {
+ } else if(update_err == VideoPlayer::Error::EXITED && video_player->exit_status == 0 && (!is_matrix || is_youtube)) {
std::string new_video_url;
if(!video_page->should_autoplay()) {
@@ -8025,14 +8018,14 @@ namespace QuickMedia {
const bool download_use_youtube_dl = url_should_download_with_youtube_dl(url);
std::string filename;
std::string video_id;
- //const bool url_is_youtube = youtube_url_extract_id(url, video_id);
+ const bool url_is_youtube = youtube_url_extract_id(url, video_id);
//const bool url_is_youtube = false;
std::unique_ptr<YoutubeVideoPage> youtube_video_page;
std::string video_url;
std::string audio_url;
- //int64_t video_content_length = 0;
- //int64_t audio_content_length = 0;
+ int64_t video_content_length = 0;
+ int64_t audio_content_length = 0;
TaskResult task_result = TaskResult::TRUE;
if(download_use_youtube_dl) {
@@ -8082,6 +8075,78 @@ namespace QuickMedia {
return !filename.empty();
});
+ } else if(url_is_youtube) {
+ youtube_video_page = std::make_unique<YoutubeVideoPage>(this, url);
+ bool cancelled = false;
+ bool load_successful = false;
+ const int video_max_height = video_get_max_height();
+
+ std::string err_str;
+ for(int i = 0; i < 3; ++i) {
+ task_result = run_task_with_loading_screen([&]{
+ VideoInfo video_info;
+ SubmitArgs submit_args;
+ if(youtube_video_page->load(submit_args, video_info, err_str) != PluginResult::OK)
+ return false;
+
+ filename = video_info.title;
+ std::string ext;
+ bool has_embedded_audio = true;
+ video_url = no_video ? "" : youtube_video_page->get_video_url(video_max_height, has_embedded_audio, ext);
+ audio_url.clear();
+
+ if(!has_embedded_audio || no_video)
+ audio_url = youtube_video_page->get_audio_url(ext);
+
+ if(video_url.empty() && audio_url.empty())
+ return false;
+
+ if(!youtube_url_is_live_stream(video_url) && !youtube_url_is_live_stream(audio_url)) {
+ video_content_length = 0;
+ audio_content_length = 0;
+ std::string new_video_url = video_url;
+ std::string new_audio_url = audio_url;
+ auto current_thread_id = std::this_thread::get_id();
+ if(!youtube_custom_redirect(new_video_url, new_audio_url, video_content_length, audio_content_length, [current_thread_id]{ return !program_is_dead_in_thread(current_thread_id); })) {
+ if(program_is_dead_in_current_thread())
+ cancelled = true;
+ return false;
+ }
+
+ video_url = std::move(new_video_url);
+ audio_url = std::move(new_audio_url);
+ }
+
+ if(!video_url.empty() && !audio_url.empty())
+ filename += ".mkv";
+ else
+ filename += ext;
+
+ return true;
+ });
+
+ if(task_result == TaskResult::CANCEL || cancelled) {
+ exit_code = 1;
+ return;
+ } else if(task_result == TaskResult::FALSE) {
+ continue;
+ }
+
+ load_successful = true;
+ break;
+ }
+
+ if(!load_successful) {
+ show_notification("QuickMedia", "Download failed" + (err_str.empty() ? "" : ", error: " + err_str), Urgency::CRITICAL);
+ exit_code = 1;
+ return;
+ }
+
+ if(youtube_url_is_live_stream(video_url) || youtube_url_is_live_stream(audio_url)) {
+ show_notification("QuickMedia", "Downloading youtube live streams is currently not supported", Urgency::CRITICAL);
+ exit_code = 1;
+ return;
+ }
} else {
if(download_filename.empty()) {
task_result = run_task_with_loading_screen([url, &filename]{
@@ -8173,6 +8238,16 @@ namespace QuickMedia {
std::unique_ptr<Downloader> downloader;
if(download_use_youtube_dl) {
downloader = std::make_unique<YoutubeDlDownloader>(yt_dl_name, url, output_filepath, no_video);
+ } else if(url_is_youtube) {
+ MediaMetadata video_metadata;
+ video_metadata.url = std::move(video_url);
+ video_metadata.content_length = video_content_length;
+
+ MediaMetadata audio_metadata;
+ audio_metadata.url = std::move(audio_url);
+ audio_metadata.content_length = audio_content_length;
+
+ downloader = std::make_unique<YoutubeDownloader>(video_metadata, audio_metadata, output_filepath);
} else {
downloader = std::make_unique<CurlDownloader>(url, output_filepath);
}
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index f3226de..0c9580f 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -2396,11 +2396,7 @@ namespace QuickMedia {
}
std::string YoutubeVideoPage::get_video_url(int max_height, bool &has_embedded_audio, std::string &ext) {
- has_embedded_audio = true;
- ext = ".mp4";
- return url;
-#if 0
- if(!livestream_url.empty()) {
+ if(!livestream_url.empty() && video_formats.empty() && audio_formats.empty()) {
has_embedded_audio = true;
return livestream_url;
}
@@ -2432,7 +2428,23 @@ namespace QuickMedia {
ext = ".webm";
return chosen_video_format->base.url;
-#endif
+ }
+
+ std::string YoutubeVideoPage::get_audio_url(std::string &ext) {
+ if(audio_formats.empty())
+ return "";
+
+ const YoutubeAudioFormat *chosen_audio_format = &audio_formats.front();
+ 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());
+
+ if(chosen_audio_format->base.mime_type.find("mp4") != std::string::npos)
+ ext = ".m4a";
+ else if(chosen_audio_format->base.mime_type.find("webm") != std::string::npos)
+ ext = ".opus"; // TODO: Detect if vorbis (.ogg) or opus (.opus)
+ else if(chosen_audio_format->base.mime_type.find("opus") != std::string::npos)
+ ext = ".opus";
+
+ return chosen_audio_format->base.url;
}
// Returns -1 if timestamp is in an invalid format
@@ -2532,8 +2544,10 @@ namespace QuickMedia {
static void subtitle_url_set_vtt_format(std::string &subtitle_url) {
const size_t index = subtitle_url.find("&fmt=");
- if(index == std::string::npos)
+ if(index == std::string::npos) {
+ subtitle_url += "&fmt=vtt";
return;
+ }
size_t end_index = subtitle_url.find('&');
if(end_index == std::string::npos)
@@ -2622,11 +2636,9 @@ namespace QuickMedia {
}
*/
- if(livestream_url.empty()) {
- parse_formats(*streaming_data_json);
- if(video_formats.empty() && audio_formats.empty())
- return PluginResult::ERR;
- }
+ parse_formats(*streaming_data_json);
+ if(video_formats.empty() && audio_formats.empty() && livestream_url.empty())
+ return PluginResult::ERR;
const Json::Value &video_details_json = json_root["videoDetails"];
if(video_details_json.isObject()) {
@@ -2715,82 +2727,19 @@ namespace QuickMedia {
// The second one works for age restricted videos and regular videos but only if they can be embedded. It doesn't work for copyrighted videos.
// The third one works for all non-copyrighted, non-age restricted videos, embeddable or not.
- const int num_request_types = 3;
+ const int num_request_types = 1;
std::string request_data[num_request_types] = {
R"END(
-{
- "context": {
- "client": {
- "clientName": "ANDROID",
- "clientVersion": "16.20",
- "hl": "en",
- "clientScreen": "EMBED"
- },
- "thirdParty": {
- "embedUrl": "https://google.com"
- }
- },
- "videoId": "%VIDEO_ID%",
- "playbackContext": {
- "contentPlaybackContext": {
- "html5Preference": "HTML5_PREF_WANTS"
- }
- },
- "contentCheckOk": true,
- "racyCheckOk": true
-}
-)END",
-R"END(
-{
- "context": {
- "client": {
- "clientName": "TVHTML5_SIMPLY_EMBEDDED_PLAYER",
- "clientVersion": "2.0",
- "hl": "en"
- },
- "thirdParty": {
- "embedUrl": "https://youtube.com/"
- }
- },
- "videoId": "%VIDEO_ID%",
- "contentCheckOk": true,
- "racyCheckOk": true
-}
-)END",
-R"END(
-{
- "context": {
- "client": {
- "clientName": "ANDROID",
- "clientVersion": "16.20",
- "hl": "en"
- },
- "thirdParty": {
- "embedUrl": "https://google.com"
- }
- },
- "videoId": "%VIDEO_ID%",
- "playbackContext": {
- "contentPlaybackContext": {
- "html5Preference": "HTML5_PREF_WANTS"
- }
- },
- "contentCheckOk": true,
- "racyCheckOk": true
-}
+ {"context":{"client":{"hl":"en","gl":"US","clientName":"IOS","clientVersion":"17.33.2","deviceModel":"iPhone14,3"}},"videoId":"%VIDEO_ID%"}
)END",
};
std::string client_names[num_request_types] = {
- "3",
- "85",
- "3"
+ "1"
};
std::string client_versions[num_request_types] = {
- "16.20",
- "2.0",
- "16.20"
+ "2.20210622.10.00"
};
for(int i = 0; i < num_request_types; ++i) {