diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-03-08 16:39:55 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-03-08 16:39:55 +0100 |
commit | a26d0fcc0a30a28ce0e458ea275fc0787c693bc6 (patch) | |
tree | ffe2212b81d9fdc93b49383c102e7c0ece0d225a /src/plugins/Youtube.cpp | |
parent | 21c50903a68c253fa5fcb9ed5ac8ba5abb1142b9 (diff) |
Save youtube watch progress and resume next time the video is played
Diffstat (limited to 'src/plugins/Youtube.cpp')
-rw-r--r-- | src/plugins/Youtube.cpp | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index d80d86c..2d92cd8 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -7,6 +7,7 @@ #include "../../include/VideoPlayer.hpp" #include "../../include/Utils.hpp" #include "../../include/Theme.hpp" +#include "../../plugins/WatchProgress.hpp" #include <optional> #include <json/reader.h> extern "C" { @@ -1858,6 +1859,30 @@ namespace QuickMedia { VideoPage::set_url(std::move(new_url)); } + std::string YoutubeVideoPage::get_url_timestamp() { + if(!timestamp.empty()) + return timestamp; + + std::string video_id; + if(!youtube_url_extract_id(url, video_id)) { + fprintf(stderr, "Failed to extract youtube id from %s\n", url.c_str()); + return ""; + } + + std::unordered_map<std::string, WatchProgress> watch_progress = get_watch_progress_for_plugin("youtube"); + auto it = watch_progress.find(video_id); + if(it == watch_progress.end()) + return ""; + + // If we are very close to the end then start from the beginning. + // This is the same behavior as mpv. + // This is better because we dont want the video player to stop immediately after we start playing and we dont get any chance to seek. + if(it->second.time_pos_sec + 10.0 >= it->second.duration_sec) + return ""; + else + return std::to_string(it->second.time_pos_sec); + } + BodyItems YoutubeVideoPage::get_related_media(const std::string &url) { comments_continuation_token.clear(); BodyItems result_items; @@ -2213,6 +2238,7 @@ namespace QuickMedia { video_details.author.clear(); video_details.views.clear(); video_details.description.clear(); + video_details.duration = 0.0; } PluginResult YoutubeVideoPage::parse_video_response(const Json::Value &json_root, std::string &title, std::string &channel_url, std::vector<MediaChapter> &chapters, std::string &err_str) { @@ -2274,11 +2300,18 @@ namespace QuickMedia { const Json::Value &author_json = video_details_json["author"]; const Json::Value &view_count_json = video_details_json["viewCount"]; const Json::Value &short_description_json = video_details_json["shortDescription"]; + const Json::Value &length_seconds_json = video_details_json["lengthSeconds"]; if(title_json.isString()) video_details.title = title_json.asString(); if(author_json.isString()) video_details.author = author_json.asString(); if(view_count_json.isString()) video_details.views = view_count_json.asString(); if(short_description_json.isString()) video_details.description = short_description_json.asString(); + if(length_seconds_json.isString()) { + const char *length_seconds_str = length_seconds_json.asCString(); + int duration = 0; + to_num(length_seconds_str, strlen(length_seconds_str), duration); + video_details.duration = duration; + } title = video_details.title; if(!video_details.description.empty()) @@ -2333,7 +2366,7 @@ namespace QuickMedia { return PluginResult::OK; } - PluginResult YoutubeVideoPage::load(std::string &title, std::string &channel_url, std::vector<MediaChapter> &chapters, std::string &err_str) { + PluginResult YoutubeVideoPage::load(std::string &title, std::string &channel_url, double &duration, std::vector<MediaChapter> &chapters, std::string &err_str) { std::string video_id; if(!youtube_url_extract_id(url, video_id)) { fprintf(stderr, "Failed to extract youtube id from %s\n", url.c_str()); @@ -2408,6 +2441,7 @@ R"END( PluginResult result = parse_video_response(json_root, title, channel_url, chapters, err_str); if(result == PluginResult::OK) { err_str.clear(); + duration = video_details.duration; return PluginResult::OK; } } @@ -2483,15 +2517,6 @@ R"END( if(!format.isObject()) continue; - if(is_adaptive) { - // TODO: Fix. Some streams use &sq=num instead of index - const Json::Value &index_range_json = format["indexRange"]; - if(index_range_json.isNull()) { - fprintf(stderr, "Ignoring adaptive stream without indexRange\n"); - continue; - } - } - // TODO: Support HDR? const Json::Value &quality_label_json = format["qualityLabel"]; if(quality_label_json.isString() && strstr(quality_label_json.asCString(), "HDR")) continue; @@ -2574,4 +2599,13 @@ R"END( const Json::Value &adaptive_formats_json = streaming_data_json["adaptiveFormats"]; parse_format(adaptive_formats_json, true); } + + void YoutubeVideoPage::set_watch_progress(int64_t time_pos_sec, int64_t duration_sec) { + std::string video_id; + if(!youtube_url_extract_id(url, video_id)) { + show_notification("QuickMedia", "Failed to extract youtube id from " + url); + return; + } + set_watch_progress_for_plugin("youtube", video_id, time_pos_sec, duration_sec, video_id); + } } |