From 47d594f0676a644e7c072331a009ceb46de8f62e Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 19 Jun 2023 02:18:47 +0200 Subject: Lbry: fix videos not working --- src/plugins/Lbry.cpp | 62 ++++++++++++++++++++++++++++++++++++++++------ src/plugins/LocalAnime.cpp | 8 ++++-- 2 files changed, 61 insertions(+), 9 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/Lbry.cpp b/src/plugins/Lbry.cpp index a5806ab..1ce23c0 100644 --- a/src/plugins/Lbry.cpp +++ b/src/plugins/Lbry.cpp @@ -70,9 +70,6 @@ namespace QuickMedia { body_item->userdata = search_type_channel; is_channel = true; } else if(strcmp(value_type_json.asCString(), "stream") == 0) { - body_item->url = canonical_url_json.asString(); - body_item->userdata = search_type_video; - // Skip livestreams for now as they are pretty broken on lbry. // Livestream requests work by doing GET https://api.live.odysee.com/v1/odysee/live/ // then get stream url with .data.url. If that is missing then there is no livestream going on. What to do then? @@ -80,6 +77,25 @@ namespace QuickMedia { const Json::Value &stream_type_json = value_json["stream_type"]; if(!stream_type_json.isString() || strcmp(stream_type_json.asCString(), "video") != 0) return nullptr; + + if(!name_json.isString()) + return nullptr; + + const Json::Value &video_source_json = value_json["source"]; + if(!video_source_json.isObject()) + return nullptr; + + const Json::Value &media_type_json = video_source_json["media_type"]; + if(!media_type_json.isString() || !strstr(media_type_json.asCString(), "video/")) + return nullptr; + + const Json::Value &hash_json = video_source_json["hash"]; + const Json::Value &sd_hash_json = video_source_json["sd_hash"]; + if(!hash_json.isString() || !sd_hash_json.isString()) + return nullptr; + + body_item->url = "https://player.odycdn.com/api/v4/streams/tc/" + name_json.asString() + "/" + hash_json.asString() + "/" + sd_hash_json.asString() + "/master.m3u8"; + body_item->userdata = search_type_video; } body_item->thumbnail_size = { 220, 130 }; @@ -347,7 +363,8 @@ namespace QuickMedia { return get_page("", 0, result_items); } - static PluginResult video_get_stream_url(Page *page, const std::string &video_url, std::string &streaming_url, std::string &err_str) { + static PluginResult video_get_stream_url(Page *page, const std::string &video_url, std::vector &streams, std::string &err_str) { +#if 0 std::string url = "https://api.na-backend.odysee.com/api/v1/proxy?m=get"; Json::Value request_params_json(Json::objectValue); @@ -391,6 +408,14 @@ namespace QuickMedia { streaming_url = streaming_url_json.asString(); return PluginResult::OK; +#else + std::string website_data; + DownloadResult result = download_to_string(video_url.c_str(), website_data, {}, true); + if(result != DownloadResult::OK) return download_result_to_plugin_result(result); + + streams = m3u8_get_streams(website_data); + return PluginResult::OK; +#endif } // TODO: Support |max_height|. This can be done by gettin video source hash and checking for sd_hash and then resolution. @@ -404,7 +429,30 @@ namespace QuickMedia { std::string LbryVideoPage::get_video_url(int max_height, bool &has_embedded_audio, std::string &ext) { has_embedded_audio = true; ext = ".mp4"; // TODO: Check if this is always correct - return streaming_url; + + if(streams.empty()) + return url; + + std::sort(streams.begin(), streams.end(), [](const M3U8Stream &a, const M3U8Stream &b) { + return a.height > b.height; + }); + + size_t selected_stream = 0; + for(size_t i = 0; i < streams.size(); ++i) { + if(streams[i].height <= max_height) { + selected_stream = i; + break; + } + } + + std::string video_url = url; + size_t end_section = video_url.rfind('/'); + if(end_section != std::string::npos && end_section > 0 && end_section != video_url.size() - 1) { + end_section += 1; + video_url.replace(end_section, video_url.size() - end_section, streams[selected_stream].url); + } + + return video_url; } std::string LbryVideoPage::get_audio_url(std::string&) { @@ -412,10 +460,10 @@ namespace QuickMedia { } PluginResult LbryVideoPage::load(const SubmitArgs &args, VideoInfo &video_info, std::string &err_str) { - streaming_url.clear(); + streams.clear(); video_info.title = args.title; //title = this->title; video_info.duration = 0.0; - return video_get_stream_url(this, url, streaming_url, err_str); + return video_get_stream_url(this, url, streams, err_str); } } \ No newline at end of file diff --git a/src/plugins/LocalAnime.cpp b/src/plugins/LocalAnime.cpp index 3682ea5..a8cebab 100644 --- a/src/plugins/LocalAnime.cpp +++ b/src/plugins/LocalAnime.cpp @@ -330,11 +330,15 @@ namespace QuickMedia { LocalAnimeBodyItemData *item_data = static_cast(args.extra.get()); if(std::holds_alternative(*item_data->anime_item)) { const LocalAnime &anime = std::get(*item_data->anime_item); - result_tabs.push_back(Tab{ create_body(false, true), std::make_unique(program, anime.items, this), create_search_bar("Search...", SEARCH_DELAY_FILTER) }); + auto page = std::make_unique(program, anime.items, this); + page->title = anime.name; + result_tabs.push_back(Tab{ create_body(false, true), std::move(page), create_search_bar("Search...", SEARCH_DELAY_FILTER) }); return PluginResult::OK; } else if(std::holds_alternative(*item_data->anime_item)) { const LocalAnimeSeason &season = std::get(*item_data->anime_item); - result_tabs.push_back(Tab{ create_body(false, true), std::make_unique(program, season.episodes, this), create_search_bar("Search...", SEARCH_DELAY_FILTER) }); + auto page = std::make_unique(program, season.episodes, this); + page->title = title + " - " + season.name; + result_tabs.push_back(Tab{ create_body(false, true), std::move(page), create_search_bar("Search...", SEARCH_DELAY_FILTER) }); return PluginResult::OK; } else if(std::holds_alternative(*item_data->anime_item)) { const LocalAnimeEpisode &episode = std::get(*item_data->anime_item); -- cgit v1.2.3