Added backend capability to select specific download qualities
This commit is contained in:
parent
818213da50
commit
c66883efd6
@ -17,22 +17,28 @@ void DownloadManager::PreInit()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DownloadManager::QueueDownload(std::string url, DOWNLOAD_MODE mode)
|
std::string DownloadManager::QueueDownload(std::string url, DOWNLOAD_MODE mode, DOWNLOAD_QUALITY quality)
|
||||||
{
|
{
|
||||||
|
// Create uniquie tubio id
|
||||||
std::string tubioId = CreateNewTubioID();
|
std::string tubioId = CreateNewTubioID();
|
||||||
FetchInformation(url, tubioId);
|
|
||||||
|
|
||||||
|
// Fetch metadata
|
||||||
|
FetchInformation(url, tubioId);
|
||||||
std::string jsString = FileSystem::ReadFile(XGConfig::downloader.cachedir + "/metadata/" + tubioId + ".json");
|
std::string jsString = FileSystem::ReadFile(XGConfig::downloader.cachedir + "/metadata/" + tubioId + ".json");
|
||||||
|
|
||||||
|
// Create download entry structure
|
||||||
DownloadEntry newDownload;
|
DownloadEntry newDownload;
|
||||||
newDownload.tubio_id = tubioId;
|
newDownload.tubio_id = tubioId;
|
||||||
newDownload.mode = mode;
|
newDownload.mode = mode;
|
||||||
|
newDownload.quality = quality;
|
||||||
newDownload.download_progress = 0;
|
newDownload.download_progress = 0;
|
||||||
newDownload.queued_timestamp = time(0);
|
newDownload.queued_timestamp = time(0);
|
||||||
newDownload.download_url = "/download/" + newDownload.tubio_id;
|
newDownload.download_url = "download/" + newDownload.tubio_id;
|
||||||
|
|
||||||
|
// Check for missing dependencies
|
||||||
WarnIfMissingDependenciesWIN();
|
WarnIfMissingDependenciesWIN();
|
||||||
|
|
||||||
|
// Interpret metadata
|
||||||
if (!IsJsonValid(jsString))
|
if (!IsJsonValid(jsString))
|
||||||
{
|
{
|
||||||
newDownload.status = DOWNLOAD_STATUS::FAILED;
|
newDownload.status = DOWNLOAD_STATUS::FAILED;
|
||||||
@ -92,6 +98,7 @@ std::string DownloadManager::QueueDownload(std::string url, DOWNLOAD_MODE mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add to list of unfinished downloads
|
||||||
unfinishedCache.push_back(newDownload);
|
unfinishedCache.push_back(newDownload);
|
||||||
|
|
||||||
return tubioId;
|
return tubioId;
|
||||||
@ -146,16 +153,19 @@ void DownloadManager::DownloadNext()
|
|||||||
|
|
||||||
std::thread* downloadThread = new std::thread([=]() {
|
std::thread* downloadThread = new std::thread([=]() {
|
||||||
DownloadEntry* entry = next;
|
DownloadEntry* entry = next;
|
||||||
|
std::string tubioId = entry->tubio_id;
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (entry->mode == DOWNLOAD_MODE::VIDEO)
|
if (entry->mode == DOWNLOAD_MODE::VIDEO)
|
||||||
{
|
{
|
||||||
std::string ytdl_call_video_base =
|
// Call template
|
||||||
|
std::string ytdl_call_video_base =
|
||||||
"youtube-dl --newline --no-call-home --no-playlist --no-part --no-warnings --socket-timeout 5 --limit-rate $$DL_RATE"
|
"youtube-dl --newline --no-call-home --no-playlist --no-part --no-warnings --socket-timeout 5 --limit-rate $$DL_RATE"
|
||||||
" --no-mtime --no-cache-dir --recode-video mp4 --prefer-ffmpeg"
|
" --no-mtime --no-cache-dir -f $$QUALITY --recode-video mp4 --prefer-ffmpeg"
|
||||||
" -o \"$$DL_FILE\" \"$$DL_URL\" > \"$$DL_PROG_BUF_FILE\"";
|
" -o \"$$DL_FILE\" \"$$DL_URL\" > \"$$DL_PROG_BUF_FILE\"";
|
||||||
|
|
||||||
|
// Fill template
|
||||||
|
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$QUALITY", DownloadQualityToStringParams(entry->quality));
|
||||||
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$DL_RATE", XGConfig::downloader.max_dlrate_per_thread);
|
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$DL_RATE", XGConfig::downloader.max_dlrate_per_thread);
|
||||||
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$DL_FILE", XGConfig::downloader.cachedir + "/download/" + entry->tubio_id + ".%(ext)s");
|
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$DL_FILE", XGConfig::downloader.cachedir + "/download/" + entry->tubio_id + ".%(ext)s");
|
||||||
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$DL_URL", entry->webpage_url);
|
ytdl_call_video_base = Internal::StringHelpers::Replace(ytdl_call_video_base, "$$DL_URL", entry->webpage_url);
|
||||||
@ -167,11 +177,15 @@ void DownloadManager::DownloadNext()
|
|||||||
}
|
}
|
||||||
else // DOWNLOAD_MODE::AUDIO
|
else // DOWNLOAD_MODE::AUDIO
|
||||||
{
|
{
|
||||||
|
// Call template
|
||||||
std::string ytdl_call_audio_base =
|
std::string ytdl_call_audio_base =
|
||||||
"youtube-dl --newline --no-call-home --no-playlist --no-part --no-warnings --socket-timeout 5 --limit-rate $$DL_RATE"
|
"youtube-dl --newline --no-call-home --no-playlist --no-part --no-warnings --socket-timeout 5 --limit-rate $$DL_RATE"
|
||||||
" --no-mtime --no-cache-dir --audio-format mp3 --audio-quality 0 --extract-audio -o \"$$DL_FILE\""
|
" --no-mtime --no-cache-dir -f $$QUALITY --audio-format mp3 --audio-quality 0 --extract-audio -o \"$$DL_FILE\""
|
||||||
" \"$$DL_URL\" > \"$$DL_PROG_BUF_FILE\"";
|
" \"$$DL_URL\" > \"$$DL_PROG_BUF_FILE\"";
|
||||||
|
|
||||||
|
|
||||||
|
// Fill template
|
||||||
|
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$QUALITY", DownloadQualityToStringParams(entry->quality));
|
||||||
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$DL_RATE", XGConfig::downloader.max_dlrate_per_thread);
|
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$DL_RATE", XGConfig::downloader.max_dlrate_per_thread);
|
||||||
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$DL_FILE", XGConfig::downloader.cachedir + "/download/" + entry->tubio_id + ".%(ext)s");
|
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$DL_FILE", XGConfig::downloader.cachedir + "/download/" + entry->tubio_id + ".%(ext)s");
|
||||||
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$DL_URL", entry->webpage_url);
|
ytdl_call_audio_base = Internal::StringHelpers::Replace(ytdl_call_audio_base, "$$DL_URL", entry->webpage_url);
|
||||||
@ -182,13 +196,21 @@ void DownloadManager::DownloadNext()
|
|||||||
ss << ytdl_call_audio_base;
|
ss << ytdl_call_audio_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This call takes a good while and is run in a seperate thread (look a few lines above. The lambda function)
|
||||||
int returnCode = system(ss.str().c_str());
|
int returnCode = system(ss.str().c_str());
|
||||||
|
|
||||||
|
// Fetch new instance
|
||||||
|
// Don't ask me why the old one isn't valid anymore -.-
|
||||||
|
for (std::size_t i = 0; i < unfinishedCache.size(); i++)
|
||||||
|
if (unfinishedCache[i].tubio_id == tubioId)
|
||||||
|
entry = &unfinishedCache[i];
|
||||||
|
|
||||||
if (returnCode == 0)
|
if (returnCode == 0)
|
||||||
{
|
{
|
||||||
// Download succeeded
|
// Download succeeded
|
||||||
entry->status = DOWNLOAD_STATUS::FINISHED;
|
entry->status = DOWNLOAD_STATUS::FINISHED;
|
||||||
entry->download_progress = 100;
|
entry->download_progress = 100;
|
||||||
|
|
||||||
shouldSave = true;
|
shouldSave = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -569,6 +591,25 @@ std::vector<DownloadEntry> DownloadManager::ParseJsonArrayToEntries(const JasonP
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DownloadManager::DownloadQualityToStringParams(DOWNLOAD_QUALITY quality)
|
||||||
|
{
|
||||||
|
switch (quality)
|
||||||
|
{
|
||||||
|
case DOWNLOAD_QUALITY::_BEST:
|
||||||
|
return "bestvideo[ext=mp4]+bestaudio";
|
||||||
|
case DOWNLOAD_QUALITY::_1080p:
|
||||||
|
return "bestvideo[ext=mp4][height^<=1080]+bestaudio";
|
||||||
|
case DOWNLOAD_QUALITY::_720p:
|
||||||
|
return "bestvideo[ext=mp4][height^<=720]+bestaudio";
|
||||||
|
case DOWNLOAD_QUALITY::_360p:
|
||||||
|
return "bestvideo[ext=mp4][height^<=360]+bestaudio";
|
||||||
|
case DOWNLOAD_QUALITY::_144p:
|
||||||
|
return "bestvideo[ext=mp4][height^<=144]+bestaudio";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
void DownloadManager::FetchInformation(std::string url, std::string tubId)
|
void DownloadManager::FetchInformation(std::string url, std::string tubId)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
@ -23,6 +23,14 @@ namespace Downloader
|
|||||||
FINISHED,
|
FINISHED,
|
||||||
FAILED
|
FAILED
|
||||||
};
|
};
|
||||||
|
enum class DOWNLOAD_QUALITY
|
||||||
|
{
|
||||||
|
_BEST, // best quality
|
||||||
|
_1080p, // 1080p
|
||||||
|
_720p, // 720p
|
||||||
|
_360p, // 360p
|
||||||
|
_144p // 144p
|
||||||
|
};
|
||||||
|
|
||||||
class DownloadEntry
|
class DownloadEntry
|
||||||
{
|
{
|
||||||
@ -41,6 +49,7 @@ namespace Downloader
|
|||||||
std::string download_url;
|
std::string download_url;
|
||||||
DOWNLOAD_STATUS status;
|
DOWNLOAD_STATUS status;
|
||||||
DOWNLOAD_MODE mode;
|
DOWNLOAD_MODE mode;
|
||||||
|
DOWNLOAD_QUALITY quality;
|
||||||
int download_progress;
|
int download_progress;
|
||||||
time_t queued_timestamp;
|
time_t queued_timestamp;
|
||||||
|
|
||||||
@ -61,7 +70,7 @@ namespace Downloader
|
|||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
/// <param name="mode">If video or audio</param>
|
/// <param name="mode">If video or audio</param>
|
||||||
/// <returns>Tubio download id</returns>
|
/// <returns>Tubio download id</returns>
|
||||||
static std::string QueueDownload(std::string url, DOWNLOAD_MODE mode);
|
static std::string QueueDownload(std::string url, DOWNLOAD_MODE mode, DOWNLOAD_QUALITY quality = DOWNLOAD_QUALITY::_BEST);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the number of videos queued
|
/// Returns the number of videos queued
|
||||||
@ -107,7 +116,24 @@ namespace Downloader
|
|||||||
static void Load();
|
static void Load();
|
||||||
static std::vector<DownloadEntry> ParseJsonArrayToEntries(const JasonPP::JsonArray& arr);
|
static std::vector<DownloadEntry> ParseJsonArrayToEntries(const JasonPP::JsonArray& arr);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will return a youtube-dl quality string based on 'quality'
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quality"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
static std::string DownloadQualityToStringParams(DOWNLOAD_QUALITY quality);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will fetch metadata of an url
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">Url to fetch from</param>
|
||||||
|
/// <param name="tubId">Tubio id to save data to</param>
|
||||||
static void FetchInformation(std::string url, std::string tubId);
|
static void FetchInformation(std::string url, std::string tubId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will create an unique tubio id (based on time())
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Unique tubio id</returns>
|
||||||
static std::string CreateNewTubioID();
|
static std::string CreateNewTubioID();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -73,6 +73,7 @@ bool RestQueryHandler::Example_Foo(const JsonBlock& request, JsonBlock& response
|
|||||||
|
|
||||||
bool RestQueryHandler::QueueDownload(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
|
bool RestQueryHandler::QueueDownload(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
|
||||||
{
|
{
|
||||||
|
// Fetch parameters
|
||||||
if ((!ValidateField("video_url", JDType::STRING, request, responseBody)) ||
|
if ((!ValidateField("video_url", JDType::STRING, request, responseBody)) ||
|
||||||
(!ValidateField("mode", JDType::STRING, request, responseBody)))
|
(!ValidateField("mode", JDType::STRING, request, responseBody)))
|
||||||
{
|
{
|
||||||
@ -80,8 +81,21 @@ bool RestQueryHandler::QueueDownload(const JsonBlock& request, JsonBlock& respon
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string modeParam = request.Get("mode").AsString;
|
|
||||||
std::string videoUrl = request.Get("video_url").AsString;
|
std::string videoUrl = request.Get("video_url").AsString;
|
||||||
|
std::string modeParam = request.Get("mode").AsString;
|
||||||
|
std::string qualityParam;
|
||||||
|
|
||||||
|
// 'quality' is an optional parameter. Default value is 'best'
|
||||||
|
if ((ValidateField("quality", JDType::STRING, request, responseBody)))
|
||||||
|
{
|
||||||
|
qualityParam = request.Get("quality").AsString;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qualityParam = "best";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process parameters
|
||||||
DOWNLOAD_MODE mode;
|
DOWNLOAD_MODE mode;
|
||||||
if (modeParam == "video") mode = DOWNLOAD_MODE::VIDEO;
|
if (modeParam == "video") mode = DOWNLOAD_MODE::VIDEO;
|
||||||
else if (modeParam == "audio") mode = DOWNLOAD_MODE::AUDIO;
|
else if (modeParam == "audio") mode = DOWNLOAD_MODE::AUDIO;
|
||||||
@ -92,10 +106,27 @@ bool RestQueryHandler::QueueDownload(const JsonBlock& request, JsonBlock& respon
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOWNLOAD_QUALITY quality;
|
||||||
|
if (qualityParam == "best")
|
||||||
|
quality = DOWNLOAD_QUALITY::_BEST;
|
||||||
|
else if (qualityParam == "1080p")
|
||||||
|
quality = DOWNLOAD_QUALITY::_1080p;
|
||||||
|
else if (qualityParam == "720p")
|
||||||
|
quality = DOWNLOAD_QUALITY::_720p;
|
||||||
|
else if (qualityParam == "360p")
|
||||||
|
quality = DOWNLOAD_QUALITY::_360p;
|
||||||
|
else if (qualityParam == "144p")
|
||||||
|
quality = DOWNLOAD_QUALITY::_144p;
|
||||||
|
else {
|
||||||
|
responseCode = HTTP_STATUS_CODE::BAD_REQUEST;
|
||||||
|
responseBody.CloneFrom(RestResponseTemplates::GetByCode(HTTP_STATUS_CODE::BAD_REQUEST, "Parameter 'quality' is of wrong value. Choose either 'best', '1080p', '720p', '360p', or '144p'."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
log->cout << "Queued video \"" << videoUrl << "\"...";
|
log->cout << "Queued video \"" << videoUrl << "\"...";
|
||||||
log->Flush();
|
log->Flush();
|
||||||
|
|
||||||
std::string tubId = DownloadManager::QueueDownload(videoUrl, mode);
|
std::string tubId = DownloadManager::QueueDownload(videoUrl, mode, quality);
|
||||||
|
|
||||||
responseCode = HTTP_STATUS_CODE::OK;
|
responseCode = HTTP_STATUS_CODE::OK;
|
||||||
responseBody.CloneFrom(RestResponseTemplates::GetByCode(HTTP_STATUS_CODE::OK));
|
responseBody.CloneFrom(RestResponseTemplates::GetByCode(HTTP_STATUS_CODE::OK));
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define TUBIO_SERVER_VERSION (0.537)
|
#define TUBIO_SERVER_VERSION (0.538)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user