From 89383cff1ba5d8a928262fcb4c40382a981c78c8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 11 Jun 2021 04:51:03 +0200 Subject: Remove dependency on youtube-dl for streaming youtube, resulting in faster video startup --- src/QuickMedia.cpp | 229 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 130 insertions(+), 99 deletions(-) (limited to 'src/QuickMedia.cpp') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index fa0f0d8..7479299 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -2145,30 +2145,6 @@ namespace QuickMedia { return false; } - static bool youtube_url_extract_id(const std::string &youtube_url, std::string &youtube_video_id) { - size_t index = youtube_url.find("youtube.com/watch?v="); - if(index != std::string::npos) { - index += 20; - size_t end_index = youtube_url.find("&", index); - if(end_index == std::string::npos) - end_index = youtube_url.size(); - youtube_video_id = youtube_url.substr(index, end_index - index); - return true; - } - - index = youtube_url.find("youtu.be/"); - if(index != std::string::npos) { - index += 9; - size_t end_index = youtube_url.find("?", index); - if(end_index == std::string::npos) - end_index = youtube_url.size(); - youtube_video_id = youtube_url.substr(index, end_index - index); - return true; - } - - return false; - } - static int watch_history_get_item_by_id(const Json::Value &video_history_json, const char *id) { assert(video_history_json.isArray()); @@ -2372,68 +2348,14 @@ namespace QuickMedia { void Program::video_content_page(Page *parent_page, VideoPage *video_page, std::string video_title, bool download_if_streaming_fails, BodyItems &next_play_items, int play_index, int *parent_body_page, const std::string &parent_page_search) { PageType previous_page = pop_page_stack(); - std::string video_url = video_page->get_url(); - std::string original_video_url = video_url; sf::Clock time_watched_timer; bool video_loaded = false; - std::string youtube_video_id; - const bool is_youtube = youtube_url_extract_id(video_url, youtube_video_id); + 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_matrix = strcmp(plugin_name, "matrix") == 0; - bool video_url_is_local = false; - if(!is_youtube && download_if_streaming_fails) { - Path video_cache_dir = get_cache_dir().join("media"); - Path video_path = video_cache_dir; - SHA256 sha256; - sha256.add(video_url.data(), video_url.size()); - video_path.join(sha256.getHash()); - if(get_file_type(video_path) == FileType::REGULAR) { - fprintf(stderr, "%s is found in cache. Playing from cache...\n", video_url.c_str()); - video_url = std::move(video_path.data); - video_url_is_local = true; - } else { - TaskResult video_is_not_streamble_result = run_task_with_loading_screen([video_url]() { - return video_url_is_non_streamable_mp4(video_url.c_str()); - }); - if(video_is_not_streamble_result == TaskResult::TRUE) { - fprintf(stderr, "%s is detected to be a non-streamable mp4 file, downloading it before playing it...\n", video_url.c_str()); - if(create_directory_recursive(video_cache_dir) != 0) { - show_notification("QuickMedia", "Failed to create video cache directory", Urgency::CRITICAL); - current_page = previous_page; - return; - } - - TaskResult download_file_result = run_task_with_loading_screen([&video_path, video_url]() { - return download_to_file(video_url, video_path.data, {}, true) == DownloadResult::OK; - }); - switch(download_file_result) { - case TaskResult::TRUE: { - video_url = std::move(video_path.data); - video_url_is_local = true; - break; - } - case TaskResult::FALSE: { - show_notification("QuickMedia", "Failed to download " + video_url, Urgency::CRITICAL); - current_page = previous_page; - return; - } - case TaskResult::CANCEL: { - current_page = previous_page; - return; - } - } - } else if(video_is_not_streamble_result == TaskResult::CANCEL) { - current_page = previous_page; - return; - } - } - } - - window.setFramerateLimit(FPS_IDLE); - idle = true; - - time_watched_timer.restart(); + idle_active_handler(); std::unique_ptr video_player; BodyItems related_videos; @@ -2451,14 +2373,110 @@ namespace QuickMedia { std::function video_event_callback; - auto load_video_error_check = [this, &related_videos, &channel_url, &video_url, &video_title, &video_player, previous_page, &time_watched_timer, &video_loaded, video_page, &video_event_callback, &on_window_create, &video_player_window, is_youtube, is_matrix](bool resume_video) mutable { + auto load_video_error_check = [this, &related_videos, &channel_url, &video_title, &video_player, previous_page, &time_watched_timer, &video_loaded, video_page, &video_event_callback, &on_window_create, &video_player_window, is_youtube, is_matrix, download_if_streaming_fails](bool resume_video) mutable { + TaskResult load_result = run_task_with_loading_screen([video_page]() { + return video_page->load() == PluginResult::OK; + }); + + if(load_result == TaskResult::CANCEL) { + current_page = previous_page; + return; + } else if(load_result == TaskResult::FALSE) { + show_notification("QuickMedia", "Failed to load media", Urgency::CRITICAL); + current_page = previous_page; + return; + } + + bool is_audio_only = no_video; + bool has_embedded_audio = true; + const int largest_monitor_height = get_largest_monitor_height(disp); + std::string video_url = video_page->get_video_url(largest_monitor_height, has_embedded_audio); + std::string audio_url; + if(video_url.empty() || no_video) { + video_url = video_page->get_audio_url(); + if(video_url.empty()) { + video_url = video_page->get_url(); + has_embedded_audio = true; + } else { + is_audio_only = true; + has_embedded_audio = false; + } + } else if(!has_embedded_audio) { + audio_url = video_page->get_audio_url(); + } + + bool video_url_is_local = false; + if(!is_youtube && download_if_streaming_fails) { + Path video_cache_dir = get_cache_dir().join("media"); + Path video_path = video_cache_dir; + SHA256 sha256; + sha256.add(video_url.data(), video_url.size()); + video_path.join(sha256.getHash()); + if(get_file_type(video_path) == FileType::REGULAR) { + fprintf(stderr, "%s is found in cache. Playing from cache...\n", video_url.c_str()); + video_url = std::move(video_path.data); + video_url_is_local = true; + audio_url.clear(); + if(no_video) { + is_audio_only = true; + has_embedded_audio = false; + } else { + is_audio_only = false; + has_embedded_audio = true; + } + } else { + TaskResult video_is_not_streamble_result = run_task_with_loading_screen([video_url]() { + return video_url_is_non_streamable_mp4(video_url.c_str()); + }); + if(video_is_not_streamble_result == TaskResult::TRUE) { + fprintf(stderr, "%s is detected to be a non-streamable mp4 file, downloading it before playing it...\n", video_url.c_str()); + if(create_directory_recursive(video_cache_dir) != 0) { + show_notification("QuickMedia", "Failed to create video cache directory", Urgency::CRITICAL); + current_page = previous_page; + return; + } + + TaskResult download_file_result = run_task_with_loading_screen([&video_path, video_url]() { + return download_to_file(video_url, video_path.data, {}, true) == DownloadResult::OK; + }); + switch(download_file_result) { + case TaskResult::TRUE: { + video_url = std::move(video_path.data); + video_url_is_local = true; + audio_url.clear(); + if(no_video) { + is_audio_only = true; + has_embedded_audio = false; + } else { + is_audio_only = false; + has_embedded_audio = true; + } + break; + } + case TaskResult::FALSE: { + show_notification("QuickMedia", "Failed to download " + video_url, Urgency::CRITICAL); + current_page = previous_page; + return; + } + case TaskResult::CANCEL: { + current_page = previous_page; + return; + } + } + } else if(video_is_not_streamble_result == TaskResult::CANCEL) { + current_page = previous_page; + return; + } + } + } + time_watched_timer.restart(); video_loaded = false; video_player_window = None; watched_videos.insert(video_url); - video_player = std::make_unique(no_video, use_system_mpv_config, resume_video, is_matrix && !is_youtube, video_event_callback, on_window_create, resources_root, get_largest_monitor_height(disp)); - VideoPlayer::Error err = video_player->load_video(video_url.c_str(), window.getSystemHandle(), plugin_name, video_title); + video_player = std::make_unique(is_audio_only, use_system_mpv_config, resume_video, is_matrix && !is_youtube, video_event_callback, on_window_create, resources_root, largest_monitor_height); + VideoPlayer::Error err = video_player->load_video(video_url.c_str(), audio_url.c_str(), window.getSystemHandle(), plugin_name, video_title); if(err != VideoPlayer::Error::OK) { std::string err_msg = "Failed to play url: "; err_msg += video_url; @@ -2469,8 +2487,9 @@ namespace QuickMedia { return; channel_url.clear(); - TaskResult load_related_media_result = run_task_with_loading_screen([video_page, &related_videos, &video_url, &channel_url]{ - related_videos = video_page->get_related_media(video_url, channel_url); + TaskResult load_related_media_result = run_task_with_loading_screen([video_page, &related_videos, &channel_url]{ + // TODO: Do async + related_videos = video_page->get_related_media(video_page->get_url(), channel_url); return true; }); @@ -2484,9 +2503,9 @@ namespace QuickMedia { return; std::string video_id; - if(!youtube_url_extract_id(video_url, video_id)) { + if(!youtube_url_extract_id(video_page->get_url(), video_id)) { std::string err_msg = "Failed to extract id of youtube url "; - err_msg += video_url; + err_msg += video_page->get_url(); err_msg + ", video wont be saved in history"; show_notification("QuickMedia", err_msg.c_str(), Urgency::LOW); return; @@ -2545,20 +2564,21 @@ namespace QuickMedia { bool cursor_visible = true; sf::Clock cursor_hide_timer; - auto save_video_url_to_clipboard = [&original_video_url, &video_player]() { - if(video_url_supports_timestamp(original_video_url)) { + auto save_video_url_to_clipboard = [video_page, &video_player]() { + std::string url = video_page->get_url(); + if(video_url_supports_timestamp(url)) { // TODO: Remove timestamp (&t= or ?t=) from video_url double time_in_file = 0.0; if(video_player && (video_player->get_time_in_file(&time_in_file) != VideoPlayer::Error::OK)) time_in_file = 0.0; - std::string clipboard = original_video_url; + std::string clipboard = std::move(url); if((int)time_in_file > 0) clipboard += "&t=" + std::to_string((int)time_in_file); sf::Clipboard::setString(sf::String::fromUtf8(clipboard.begin(), clipboard.end())); } else { - sf::Clipboard::setString(sf::String::fromUtf8(original_video_url.begin(), original_video_url.end())); + sf::Clipboard::setString(sf::String::fromUtf8(url.begin(), url.end())); } }; @@ -2600,7 +2620,7 @@ namespace QuickMedia { } else if(pressed_keysym == XK_f && pressing_ctrl) { window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE); } else if(pressed_keysym == XK_s && pressing_ctrl) { - video_page_download_video(original_video_url, !is_matrix || is_youtube, video_player_window); + video_page_download_video(video_page->get_url(), !is_matrix || is_youtube, video_player_window); } else if(pressed_keysym == XK_r && pressing_ctrl) { if(!cursor_visible) window.setMouseCursorVisible(true); @@ -2609,7 +2629,7 @@ namespace QuickMedia { int search_delay = 0; auto search_page = video_page->create_search_page(this, search_delay); auto comments_page = video_page->create_comments_page(this); - auto related_videos_page = video_page->create_related_videos_page(this, video_url, video_title); + auto related_videos_page = video_page->create_related_videos_page(this); auto channels_page = video_page->create_channels_page(this, channel_url); if(search_page || related_videos_page || channels_page) { XUnmapWindow(disp, video_player_window); @@ -2654,7 +2674,6 @@ namespace QuickMedia { if(page_changed) { current_page = PageType::VIDEO_CONTENT; - //video_player = std::make_unique(no_video, use_system_mpv_config, true, video_event_callback, on_window_create, resources_root); load_video_error_check(true); } else { XMapWindow(disp, video_player_window); @@ -2729,8 +2748,20 @@ namespace QuickMedia { break; } - video_url = video_page->url_get_playable_url(new_video_url); - original_video_url = video_url; + TaskResult get_playable_url_result = run_task_with_loading_screen([video_page, &new_video_url]() { + video_page->set_url(video_page->url_get_playable_url(new_video_url)); + return true; + }); + + if(get_playable_url_result == TaskResult::CANCEL) { + current_page = previous_page; + return; + } else if(get_playable_url_result == TaskResult::FALSE) { + show_notification("QuickMedia", "Failed to get playable url", Urgency::CRITICAL); + current_page = previous_page; + return; + } + video_title = std::move(new_video_title); load_video_error_check(false); } else if(update_err != VideoPlayer::Error::OK) { @@ -3516,7 +3547,7 @@ namespace QuickMedia { page_stack.push(PageType::IMAGE_BOARD_THREAD); current_page = PageType::VIDEO_CONTENT; watched_videos.clear(); - thread_page->video_url = selected_item->url; + thread_page->set_url(selected_item->url); BodyItems next_items; // TODO: Use real title video_content_page(thread_page, thread_page, selected_item->get_title(), true, thread_body->items, thread_body->get_selected_item()); @@ -5054,7 +5085,7 @@ namespace QuickMedia { bool is_audio = (message_type == MessageType::AUDIO); bool prev_no_video = no_video; no_video = is_audio; - video_page->url = selected->url; + video_page->set_url(selected->url); BodyItems next_items; // TODO: Add title video_content_page(matrix_chat_page, video_page.get(), "", message_type == MessageType::VIDEO || message_type == MessageType::AUDIO, next_items, 0); -- cgit v1.2.3