aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-06-25 12:44:53 +0200
committerdec05eba <dec05eba@protonmail.com>2021-06-25 12:44:53 +0200
commit38202de4f953fca28aa884246ced0aadf0d25a4d (patch)
tree7a0a35a32404f1929238444d13a6c626856cc791 /plugins
parent738f2b1a89a5445a1f0f94229f2fc0637b7c4e71 (diff)
Add a http server proxy for better youtube downloading (bypassing rate limit cased by http range header). Fix youtube live streams
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Youtube.hpp3
-rw-r--r--plugins/youtube/YoutubeMediaProxy.hpp100
2 files changed, 102 insertions, 1 deletions
diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp
index 36094f0..5428de0 100644
--- a/plugins/Youtube.hpp
+++ b/plugins/Youtube.hpp
@@ -148,13 +148,14 @@ namespace QuickMedia {
void mark_watched() override;
private:
PluginResult get_video_info(const std::string &video_id, Json::Value &json_root);
+ PluginResult parse_video_response(Json::Value &json_root, std::string &title, std::string &channel_url, std::vector<MediaChapter> &chapters);
void parse_format(const Json::Value &format_json, bool is_adaptive);
void parse_formats(const Json::Value &streaming_data_json);
private:
std::string timestamp;
std::string xsrf_token;
std::string comments_continuation_token;
- std::string hls_manifest_url;
+ std::string livestream_url;
std::vector<YoutubeVideoFormat> video_formats;
std::vector<YoutubeAudioFormat> audio_formats;
diff --git a/plugins/youtube/YoutubeMediaProxy.hpp b/plugins/youtube/YoutubeMediaProxy.hpp
new file mode 100644
index 0000000..2d6ea93
--- /dev/null
+++ b/plugins/youtube/YoutubeMediaProxy.hpp
@@ -0,0 +1,100 @@
+#pragma once
+
+#include "../../include/Program.hpp"
+#include <string>
+
+// TODO: Sync sequence for video and audio (for live stream).
+
+namespace QuickMedia {
+ class YoutubeMediaProxy {
+ public:
+ enum Error {
+ OK,
+ ERROR
+ };
+
+ virtual ~YoutubeMediaProxy() = default;
+
+ virtual bool start(const std::string &youtube_media_url, int content_length) = 0;
+ // This should be the last call. Do not call |start| after this. TODO: Allow restarting with |start| after |stop| is called.
+ virtual void stop() = 0;
+ virtual Error update() = 0;
+ virtual bool get_address(std::string &address) = 0;
+
+ bool start_download(const std::string &media_url, ReadProgram &read_program, int range_start, bool include_header, bool is_livestream = false, int livestream_sequence = -1);
+ private:
+ int rn = 0;
+ int rbuf = 0;
+ };
+
+ class YoutubeStaticMediaProxy : public YoutubeMediaProxy {
+ public:
+ YoutubeStaticMediaProxy() = default;
+ YoutubeStaticMediaProxy(YoutubeStaticMediaProxy&) = delete;
+ YoutubeStaticMediaProxy&operator=(YoutubeStaticMediaProxy&) = delete;
+ ~YoutubeStaticMediaProxy();
+
+ bool start(const std::string &youtube_media_url, int content_length) override;
+ void stop() override;
+ Error update() override;
+ bool get_address(std::string &address) override;
+ private:
+ void on_client_disconnect();
+ Error read_client_data();
+ void clear_download_state();
+ // If |new_range_start| is not -1 then the start range is set to that
+ Error update_download_program_status(bool client_disconnected, int new_range_start = -1, bool restart_download = false);
+ Error continue_send(const char *buffer_start, size_t total_bytes_to_write, int &buffer_offset);
+ Error handle_download();
+ // Returns the client fd or -1
+ int accept_client();
+ private:
+ int socket_fd = -1;
+ int port = 0;
+ int client_fd = -1;
+ std::string youtube_media_url;
+ int content_length = 0;
+ ReadProgram downloader_read_program;
+ int download_read_buffer_offset = 0;
+ ssize_t downloader_num_read_bytes = 0;
+ int download_range_start = 0;
+ int current_download_range = 0;
+ std::string download_header;
+ bool download_header_finished = false;
+ bool download_header_sent = false;
+ bool download_header_remaining_sent = false;
+ int download_header_written_offset = 0;
+ int download_header_offset_to_end_of_header = 0;
+ bool client_request_finished = false;
+ std::string client_request_buffer;
+ char download_read_buffer[16384];
+ };
+
+ class YoutubeLiveStreamMediaProxy : public YoutubeMediaProxy {
+ public:
+ YoutubeLiveStreamMediaProxy() = default;
+ YoutubeLiveStreamMediaProxy(YoutubeLiveStreamMediaProxy&) = delete;
+ YoutubeLiveStreamMediaProxy&operator=(YoutubeLiveStreamMediaProxy&) = delete;
+ ~YoutubeLiveStreamMediaProxy();
+
+ bool start(const std::string &youtube_media_url, int content_length) override;
+ void stop() override;
+ Error update() override;
+ bool get_address(std::string &address) override;
+ private:
+ Error update_download_program_status();
+ Error continue_send(const char *buffer_start, size_t total_bytes_to_write, int &buffer_offset);
+ private:
+ ReadProgram downloader_read_program;
+ std::string youtube_media_url;
+ int fd[2];
+ int livestream_sequence_num = -1;
+ std::string download_header;
+ bool download_header_finished = false;
+ bool download_header_remaining_sent = false;
+ int download_header_written_offset = 0;
+ int download_read_buffer_offset = 0;
+ ssize_t downloader_num_read_bytes = 0;
+ char download_read_buffer[16384];
+ };
+} \ No newline at end of file