mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-04-20 23:53:18 +03:00
Added support for custom arguments and custom output patch
This commit is contained in:
256
backend/app.js
256
backend/app.js
@@ -413,6 +413,30 @@ async function deleteVideoFile(name) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recFindByExt(base,ext,files,result)
|
||||||
|
{
|
||||||
|
files = files || fs.readdirSync(base)
|
||||||
|
result = result || []
|
||||||
|
|
||||||
|
files.forEach(
|
||||||
|
function (file) {
|
||||||
|
var newbase = path.join(base,file)
|
||||||
|
if ( fs.statSync(newbase).isDirectory() )
|
||||||
|
{
|
||||||
|
result = recFindByExt(newbase,ext,fs.readdirSync(newbase),result)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( file.substr(-1*(ext.length+1)) == '.' + ext )
|
||||||
|
{
|
||||||
|
result.push(newbase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
function getAudioInfos(fileNames) {
|
function getAudioInfos(fileNames) {
|
||||||
let result = [];
|
let result = [];
|
||||||
for (let i = 0; i < fileNames.length; i++) {
|
for (let i = 0; i < fileNames.length; i++) {
|
||||||
@@ -485,28 +509,40 @@ app.use(function(req, res, next) {
|
|||||||
app.post('/tomp3', function(req, res) {
|
app.post('/tomp3', function(req, res) {
|
||||||
var url = req.body.url;
|
var url = req.body.url;
|
||||||
var date = Date.now();
|
var date = Date.now();
|
||||||
var path = audioFolderPath;
|
|
||||||
var audiopath = '%(title)s';
|
var audiopath = '%(title)s';
|
||||||
|
|
||||||
var customQualityConfiguration = req.body.customQualityConfiguration;
|
var customQualityConfiguration = req.body.customQualityConfiguration;
|
||||||
var maxBitrate = req.body.maxBitrate;
|
var maxBitrate = req.body.maxBitrate;
|
||||||
|
var customArgs = req.body.customArgs;
|
||||||
|
var customOutput = req.body.customOutput;
|
||||||
|
|
||||||
let downloadConfig = ['-o', path + audiopath + ".mp3", '-x', '--audio-format', 'mp3', '--write-info-json', '--print-json']
|
|
||||||
|
let downloadConfig = null;
|
||||||
let qualityPath = '';
|
let qualityPath = '';
|
||||||
|
|
||||||
if (customQualityConfiguration) {
|
if (customArgs) {
|
||||||
qualityPath = `-f ${customQualityConfiguration}`;
|
downloadConfig = [customArgs];
|
||||||
} else if (maxBitrate) {
|
} else {
|
||||||
if (!maxBitrate || maxBitrate === '') maxBitrate = '0';
|
if (customOutput) {
|
||||||
qualityPath = `--audio-quality ${maxBitrate}`
|
downloadConfig = ['-o', audioFolderPath + customOutput + '.mp3', '-x', '--audio-format', 'mp3', '--write-info-json', '--print-json'];
|
||||||
}
|
} else {
|
||||||
|
downloadConfig = ['-o', audioFolderPath + audiopath + ".mp3", '-x', '--audio-format', 'mp3', '--write-info-json', '--print-json'];
|
||||||
|
}
|
||||||
|
|
||||||
if (qualityPath !== '') {
|
if (customQualityConfiguration) {
|
||||||
downloadConfig.splice(2, 0, qualityPath);
|
qualityPath = `-f ${customQualityConfiguration}`;
|
||||||
}
|
} else if (maxBitrate) {
|
||||||
|
if (!maxBitrate || maxBitrate === '') maxBitrate = '0';
|
||||||
|
qualityPath = `--audio-quality ${maxBitrate}`
|
||||||
|
}
|
||||||
|
|
||||||
if (!useDefaultDownloadingAgent && customDownloadingAgent === 'aria2c') {
|
if (qualityPath !== '') {
|
||||||
downloadConfig.splice(0, 0, '--external-downloader', 'aria2c');
|
downloadConfig.splice(2, 0, qualityPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useDefaultDownloadingAgent && customDownloadingAgent === 'aria2c') {
|
||||||
|
downloadConfig.splice(0, 0, '--external-downloader', 'aria2c');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
youtubedl.exec(url, downloadConfig, {}, function(err, output) {
|
youtubedl.exec(url, downloadConfig, {}, function(err, output) {
|
||||||
@@ -534,12 +570,14 @@ app.post('/tomp3', function(req, res) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var file_name = output_json['_filename'].replace(/^.*[\\\/]/, '');
|
var file_name = output_json['_filename'].replace(/^.*[\\\/]/, '');
|
||||||
|
var file_path = output_json['_filename'].substring(audioFolderPath.length, output_json['_filename'].length);
|
||||||
|
var alternate_file_path = file_path.substring(0, file_path.length-4);
|
||||||
var alternate_file_name = file_name.substring(0, file_name.length-4);
|
var alternate_file_name = file_name.substring(0, file_name.length-4);
|
||||||
if (alternate_file_name) file_names.push(alternate_file_name);
|
if (alternate_file_path) file_names.push(alternate_file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_playlist = file_names.length > 1;
|
let is_playlist = file_names.length > 1;
|
||||||
if (!is_playlist) audiopath = file_names[0];
|
// if (!is_playlist) audiopath = file_names[0];
|
||||||
|
|
||||||
var audiopathEncoded = encodeURIComponent(file_names[0]);
|
var audiopathEncoded = encodeURIComponent(file_names[0]);
|
||||||
res.send({
|
res.send({
|
||||||
@@ -555,22 +593,35 @@ app.post('/tomp4', function(req, res) {
|
|||||||
var date = Date.now();
|
var date = Date.now();
|
||||||
var path = videoFolderPath;
|
var path = videoFolderPath;
|
||||||
var videopath = '%(title)s';
|
var videopath = '%(title)s';
|
||||||
|
var customArgs = req.body.customArgs;
|
||||||
|
var customOutput = req.body.customOutput;
|
||||||
|
|
||||||
var selectedHeight = req.body.selectedHeight;
|
var selectedHeight = req.body.selectedHeight;
|
||||||
var customQualityConfiguration = req.body.customQualityConfiguration;
|
var customQualityConfiguration = req.body.customQualityConfiguration;
|
||||||
|
|
||||||
|
let downloadConfig = null;
|
||||||
let qualityPath = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4';
|
let qualityPath = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4';
|
||||||
|
|
||||||
if (customQualityConfiguration) {
|
if (customArgs) {
|
||||||
qualityPath = customQualityConfiguration;
|
downloadConfig = [customArgs];
|
||||||
} else if (selectedHeight && selectedHeight !== '') {
|
} else {
|
||||||
qualityPath = `bestvideo[height=${selectedHeight}]+bestaudio/best[height=${selectedHeight}]`;
|
if (customOutput) {
|
||||||
|
downloadConfig = ['-o', path + customOutput + ".mp4", '-f', qualityPath, '--write-info-json', '--print-json'];
|
||||||
|
} else {
|
||||||
|
downloadConfig = ['-o', path + videopath + ".mp4", '-f', qualityPath, '--write-info-json', '--print-json'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customQualityConfiguration) {
|
||||||
|
qualityPath = customQualityConfiguration;
|
||||||
|
} else if (selectedHeight && selectedHeight !== '') {
|
||||||
|
qualityPath = `bestvideo[height=${selectedHeight}]+bestaudio/best[height=${selectedHeight}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useDefaultDownloadingAgent && customDownloadingAgent === 'aria2c') {
|
||||||
|
downloadConfig.splice(0, 0, '--external-downloader', 'aria2c');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let downloadConfig = ['-o', path + videopath + ".mp4", '-f', qualityPath, '--write-info-json', '--print-json']
|
|
||||||
if (!useDefaultDownloadingAgent && customDownloadingAgent === 'aria2c') {
|
|
||||||
downloadConfig.splice(0, 0, '--external-downloader', 'aria2c');
|
|
||||||
}
|
|
||||||
youtubedl.exec(url, downloadConfig, {}, function(err, output) {
|
youtubedl.exec(url, downloadConfig, {}, function(err, output) {
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
let new_date = Date.now();
|
let new_date = Date.now();
|
||||||
@@ -606,7 +657,9 @@ app.post('/tomp4', function(req, res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var alternate_file_name = file_name.substring(0, file_name.length-4);
|
var alternate_file_name = file_name.substring(0, file_name.length-4);
|
||||||
if (alternate_file_name) file_names.push(alternate_file_name);
|
var file_path = output_json['_filename'].substring(audioFolderPath.length, output_json['_filename'].length);
|
||||||
|
var alternate_file_path = file_path.substring(0, file_path.length-4);
|
||||||
|
if (alternate_file_name) file_names.push(alternate_file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_playlist = file_names.length > 1;
|
let is_playlist = file_names.length > 1;
|
||||||
@@ -668,31 +721,25 @@ app.post('/fileStatusMp4', function(req, res) {
|
|||||||
app.post('/getMp3s', function(req, res) {
|
app.post('/getMp3s', function(req, res) {
|
||||||
var mp3s = [];
|
var mp3s = [];
|
||||||
var playlists = db.get('playlists.audio').value();
|
var playlists = db.get('playlists.audio').value();
|
||||||
var fullpath = audioFolderPath;
|
var files = recFindByExt(audioFolderPath, 'mp3'); // fs.readdirSync(audioFolderPath);
|
||||||
var files = fs.readdirSync(audioFolderPath);
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
let file = files[i];
|
||||||
|
var file_path = file.substring(audioFolderPath.length, file.length);
|
||||||
|
var id = file_path.substring(0, file_path.length-4);
|
||||||
|
var jsonobj = getJSONMp3(id);
|
||||||
|
if (!jsonobj) continue;
|
||||||
|
var title = jsonobj.title;
|
||||||
|
|
||||||
for (var i in files)
|
if (title.length > 14) // edits title if it's too long
|
||||||
{
|
|
||||||
var nameLength = path.basename(files[i]).length;
|
|
||||||
var ext = path.basename(files[i]).substring(nameLength-4, nameLength);
|
|
||||||
if (ext == ".mp3")
|
|
||||||
{
|
{
|
||||||
var jsonobj = getJSONMp3(path.basename(files[i]).substring(0, path.basename(files[i]).length-4));
|
title = title.substring(0,12) + "...";
|
||||||
if (!jsonobj) continue;
|
|
||||||
var id = path.basename(files[i]).substring(0, path.basename(files[i]).length-4);
|
|
||||||
var title = jsonobj.title;
|
|
||||||
|
|
||||||
if (title.length > 14) // edits title if it's too long
|
|
||||||
{
|
|
||||||
title = title.substring(0,12) + "...";
|
|
||||||
}
|
|
||||||
|
|
||||||
var thumbnail = jsonobj.thumbnail;
|
|
||||||
var duration = jsonobj.duration;
|
|
||||||
var isaudio = true;
|
|
||||||
var file = new File(id, title, thumbnail, isaudio, duration);
|
|
||||||
mp3s.push(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var thumbnail = jsonobj.thumbnail;
|
||||||
|
var duration = jsonobj.duration;
|
||||||
|
var isaudio = true;
|
||||||
|
var file_obj = new File(id, title, thumbnail, isaudio, duration);
|
||||||
|
mp3s.push(file_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
@@ -707,30 +754,25 @@ app.post('/getMp4s', function(req, res) {
|
|||||||
var mp4s = [];
|
var mp4s = [];
|
||||||
var playlists = db.get('playlists.video').value();
|
var playlists = db.get('playlists.video').value();
|
||||||
var fullpath = videoFolderPath;
|
var fullpath = videoFolderPath;
|
||||||
var files = fs.readdirSync(videoFolderPath);
|
var files = recFindByExt(videoFolderPath, 'mp4');
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
let file = files[i];
|
||||||
|
var file_path = file.substring(videoFolderPath.length, file.length);
|
||||||
|
var id = file_path.substring(0, file_path.length-4);
|
||||||
|
var jsonobj = getJSONMp4(id);
|
||||||
|
if (!jsonobj) continue;
|
||||||
|
var title = jsonobj.title;
|
||||||
|
|
||||||
for (var i in files)
|
if (title.length > 14) // edits title if it's too long
|
||||||
{
|
|
||||||
var nameLength = path.basename(files[i]).length;
|
|
||||||
var ext = path.basename(files[i]).substring(nameLength-4, nameLength);
|
|
||||||
if (ext == ".mp4")
|
|
||||||
{
|
{
|
||||||
var jsonobj = getJSONMp4(path.basename(files[i]).substring(0, path.basename(files[i]).length-4));
|
title = title.substring(0,12) + "...";
|
||||||
if (!jsonobj) continue;
|
|
||||||
var id = path.basename(files[i]).substring(0, path.basename(files[i]).length-4);
|
|
||||||
var title = jsonobj.title;
|
|
||||||
|
|
||||||
if (title.length > 14) // edits title if it's too long
|
|
||||||
{
|
|
||||||
title = title.substring(0,12) + "...";
|
|
||||||
}
|
|
||||||
|
|
||||||
var thumbnail = jsonobj.thumbnail;
|
|
||||||
var duration = jsonobj.duration;
|
|
||||||
var isaudio = false;
|
|
||||||
var file = new File(id, title, thumbnail, isaudio, duration);
|
|
||||||
mp4s.push(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var thumbnail = jsonobj.thumbnail;
|
||||||
|
var duration = jsonobj.duration;
|
||||||
|
var isaudio = false;
|
||||||
|
var file_obj = new File(id, title, thumbnail, isaudio, duration);
|
||||||
|
mp4s.push(file_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
@@ -882,46 +924,48 @@ app.post('/deleteFile', async (req, res) => {
|
|||||||
|
|
||||||
app.get('/video/:id', function(req , res){
|
app.get('/video/:id', function(req , res){
|
||||||
var head;
|
var head;
|
||||||
const path = "video/" + req.params.id + '.mp4';
|
let id = decodeURI(req.params.id);
|
||||||
const stat = fs.statSync(path)
|
const path = "video/" + id + '.mp4';
|
||||||
const fileSize = stat.size
|
const stat = fs.statSync(path)
|
||||||
const range = req.headers.range
|
const fileSize = stat.size
|
||||||
if (range) {
|
const range = req.headers.range
|
||||||
const parts = range.replace(/bytes=/, "").split("-")
|
if (range) {
|
||||||
const start = parseInt(parts[0], 10)
|
const parts = range.replace(/bytes=/, "").split("-")
|
||||||
const end = parts[1]
|
const start = parseInt(parts[0], 10)
|
||||||
? parseInt(parts[1], 10)
|
const end = parts[1]
|
||||||
: fileSize-1
|
? parseInt(parts[1], 10)
|
||||||
const chunksize = (end-start)+1
|
: fileSize-1
|
||||||
const file = fs.createReadStream(path, {start, end})
|
const chunksize = (end-start)+1
|
||||||
if (descriptors[req.params.id]) descriptors[req.params.id].push(file);
|
const file = fs.createReadStream(path, {start, end})
|
||||||
else descriptors[req.params.id] = [file];
|
if (descriptors[id]) descriptors[id].push(file);
|
||||||
file.on('close', function() {
|
else descriptors[id] = [file];
|
||||||
let index = descriptors[req.params.id].indexOf(file);
|
file.on('close', function() {
|
||||||
descriptors[req.params.id].splice(index, 1);
|
let index = descriptors[id].indexOf(file);
|
||||||
if (debugMode) console.log('Successfully closed stream and removed file reference.');
|
descriptors[id].splice(index, 1);
|
||||||
});
|
if (debugMode) console.log('Successfully closed stream and removed file reference.');
|
||||||
head = {
|
});
|
||||||
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
|
head = {
|
||||||
'Accept-Ranges': 'bytes',
|
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
|
||||||
'Content-Length': chunksize,
|
'Accept-Ranges': 'bytes',
|
||||||
'Content-Type': 'video/mp4',
|
'Content-Length': chunksize,
|
||||||
|
'Content-Type': 'video/mp4',
|
||||||
|
}
|
||||||
|
res.writeHead(206, head);
|
||||||
|
file.pipe(res);
|
||||||
|
} else {
|
||||||
|
head = {
|
||||||
|
'Content-Length': fileSize,
|
||||||
|
'Content-Type': 'video/mp4',
|
||||||
|
}
|
||||||
|
res.writeHead(200, head)
|
||||||
|
fs.createReadStream(path).pipe(res)
|
||||||
}
|
}
|
||||||
res.writeHead(206, head);
|
|
||||||
file.pipe(res);
|
|
||||||
} else {
|
|
||||||
head = {
|
|
||||||
'Content-Length': fileSize,
|
|
||||||
'Content-Type': 'video/mp4',
|
|
||||||
}
|
|
||||||
res.writeHead(200, head)
|
|
||||||
fs.createReadStream(path).pipe(res)
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/audio/:id', function(req , res){
|
app.get('/audio/:id', function(req , res){
|
||||||
var head;
|
var head;
|
||||||
let path = "audio/" + req.params.id + '.mp3';
|
let id = decodeURI(req.params.id);
|
||||||
|
let path = "audio/" + id + '.mp3';
|
||||||
path = path.replace(/\"/g, '\'');
|
path = path.replace(/\"/g, '\'');
|
||||||
const stat = fs.statSync(path)
|
const stat = fs.statSync(path)
|
||||||
const fileSize = stat.size
|
const fileSize = stat.size
|
||||||
@@ -934,11 +978,11 @@ app.get('/audio/:id', function(req , res){
|
|||||||
: fileSize-1
|
: fileSize-1
|
||||||
const chunksize = (end-start)+1
|
const chunksize = (end-start)+1
|
||||||
const file = fs.createReadStream(path, {start, end});
|
const file = fs.createReadStream(path, {start, end});
|
||||||
if (descriptors[req.params.id]) descriptors[req.params.id].push(file);
|
if (descriptors[id]) descriptors[id].push(file);
|
||||||
else descriptors[req.params.id] = [file];
|
else descriptors[id] = [file];
|
||||||
file.on('close', function() {
|
file.on('close', function() {
|
||||||
let index = descriptors[req.params.id].indexOf(file);
|
let index = descriptors[id].indexOf(file);
|
||||||
descriptors[req.params.id].splice(index, 1);
|
descriptors[id].splice(index, 1);
|
||||||
if (debugMode) console.log('Successfully closed stream and removed file reference.');
|
if (debugMode) console.log('Successfully closed stream and removed file reference.');
|
||||||
});
|
});
|
||||||
head = {
|
head = {
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": ""
|
"custom_downloading_agent": "",
|
||||||
|
"allow_advanced_download": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": ""
|
"custom_downloading_agent": "",
|
||||||
|
"allow_advanced_download": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ let CONFIG_ITEMS = {
|
|||||||
'key': 'ytdl_custom_downloading_agent',
|
'key': 'ytdl_custom_downloading_agent',
|
||||||
'path': 'YoutubeDLMaterial.Advanced.custom_downloading_agent'
|
'path': 'YoutubeDLMaterial.Advanced.custom_downloading_agent'
|
||||||
},
|
},
|
||||||
|
'ytdl_allow_advanced_download': {
|
||||||
|
'key': 'ytdl_allow_advanced_download',
|
||||||
|
'path': 'YoutubeDLMaterial.Advanced.allow_advanced_download'
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.CONFIG_ITEMS = CONFIG_ITEMS;
|
module.exports.CONFIG_ITEMS = CONFIG_ITEMS;
|
||||||
@@ -24,8 +24,9 @@ services:
|
|||||||
ytdl_allow_theme_change: 'true'
|
ytdl_allow_theme_change: 'true'
|
||||||
ytdl_use_default_downloading_agent: 'true'
|
ytdl_use_default_downloading_agent: 'true'
|
||||||
ytdl_custom_downloading_agent: 'false'
|
ytdl_custom_downloading_agent: 'false'
|
||||||
write_ytdl_config: 'true'
|
ytdl_allow_advanced_download: 'false'
|
||||||
# do not touch this
|
# do not touch this
|
||||||
|
write_ytdl_config: 'true'
|
||||||
ALLOW_CONFIG_MUTATIONS: 'true'
|
ALLOW_CONFIG_MUTATIONS: 'true'
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -116,3 +116,9 @@ mat-form-field.mat-form-field {
|
|||||||
.add-playlist-button {
|
.add-playlist-button {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.advanced-input {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
@@ -61,7 +61,36 @@
|
|||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="downloads.length > 0 && !current_download" style="margin-top: 15px;" class="big demo-basic">
|
<div *ngIf="allowAdvancedDownload" class="big demo-basic">
|
||||||
|
<form style="margin-left: 20px; margin-right: 20px;">
|
||||||
|
<mat-expansion-panel class="big">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Advanced
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="container" style="padding-bottom: 20px;">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<mat-checkbox color="accent" [disabled]="current_download" (change)="customArgsEnabledChanged($event)" [(ngModel)]="customArgsEnabled" style="position: absolute; z-index: 999" [ngModelOptions]="{standalone: true}">Use custom args</mat-checkbox>
|
||||||
|
<mat-form-field color="accent" class="advanced-input">
|
||||||
|
<input [(ngModel)]="customArgs" [ngModelOptions]="{standalone: true}" [disabled]="!customArgsEnabled" matInput placeholder="Custom args">
|
||||||
|
<mat-hint>No need to include URL, just everything after.</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<mat-checkbox color="accent" [disabled]="current_download" (change)="customOutputEnabledChanged($event)" [(ngModel)]="customOutputEnabled" style="position: absolute; z-index: 999" [ngModelOptions]="{standalone: true}">Use custom output</mat-checkbox>
|
||||||
|
<mat-form-field color="accent" class="advanced-input">
|
||||||
|
<input [(ngModel)]="customOutput" [ngModelOptions]="{standalone: true}" [disabled]="!customOutputEnabled" matInput placeholder="Custom output">
|
||||||
|
<mat-hint><a target="_blank" href="https://github.com/ytdl-org/youtube-dl/blob/master/README.md#output-template">This link</a> will be helpful. Path is relative to the config download path.</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="multiDownloadMode && downloads.length > 0 && !current_download" style="margin-top: 15px;" class="big demo-basic">
|
||||||
<mat-card id="card" style="margin-right: 20px; margin-left: 20px;">
|
<mat-card id="card" style="margin-right: 20px; margin-left: 20px;">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div *ngFor="let download of downloads; let i = index;" class="row">
|
<div *ngFor="let download of downloads; let i = index;" class="row">
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ export class MainComponent implements OnInit {
|
|||||||
downloadingfile = false;
|
downloadingfile = false;
|
||||||
audioOnly: boolean;
|
audioOnly: boolean;
|
||||||
multiDownloadMode = false;
|
multiDownloadMode = false;
|
||||||
|
customArgsEnabled = false;
|
||||||
|
customArgs = null;
|
||||||
|
customOutputEnabled = false;
|
||||||
|
customOutput = null;
|
||||||
urlError = false;
|
urlError = false;
|
||||||
path = '';
|
path = '';
|
||||||
url = '';
|
url = '';
|
||||||
@@ -61,6 +65,7 @@ export class MainComponent implements OnInit {
|
|||||||
baseStreamPath;
|
baseStreamPath;
|
||||||
audioFolderPath;
|
audioFolderPath;
|
||||||
videoFolderPath;
|
videoFolderPath;
|
||||||
|
allowAdvancedDownload = false;
|
||||||
|
|
||||||
cachedAvailableFormats = {};
|
cachedAvailableFormats = {};
|
||||||
|
|
||||||
@@ -209,6 +214,7 @@ export class MainComponent implements OnInit {
|
|||||||
result['YoutubeDLMaterial']['API']['youtube_API_key'];
|
result['YoutubeDLMaterial']['API']['youtube_API_key'];
|
||||||
this.youtubeAPIKey = this.youtubeSearchEnabled ? result['YoutubeDLMaterial']['API']['youtube_API_key'] : null;
|
this.youtubeAPIKey = this.youtubeSearchEnabled ? result['YoutubeDLMaterial']['API']['youtube_API_key'] : null;
|
||||||
this.allowQualitySelect = result['YoutubeDLMaterial']['Extra']['allow_quality_select'];
|
this.allowQualitySelect = result['YoutubeDLMaterial']['Extra']['allow_quality_select'];
|
||||||
|
this.allowAdvancedDownload = result['YoutubeDLMaterial']['Advanced']['allow_advanced_download'];
|
||||||
|
|
||||||
this.postsService.path = backendUrl;
|
this.postsService.path = backendUrl;
|
||||||
this.postsService.startPath = backendUrl;
|
this.postsService.startPath = backendUrl;
|
||||||
@@ -223,6 +229,18 @@ export class MainComponent implements OnInit {
|
|||||||
this.youtubeSearch.initializeAPI(this.youtubeAPIKey);
|
this.youtubeSearch.initializeAPI(this.youtubeAPIKey);
|
||||||
this.attachToInput();
|
this.attachToInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set final cache items
|
||||||
|
if (this.allowAdvancedDownload) {
|
||||||
|
if (localStorage.getItem('customArgsEnabled') !== null) {
|
||||||
|
this.customArgsEnabled = localStorage.getItem('customArgsEnabled') === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localStorage.getItem('customOutputEnabled') !== null) {
|
||||||
|
this.customOutputEnabled = localStorage.getItem('customOutputEnabled') === 'true';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}, error => {
|
}, error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
@@ -477,8 +495,12 @@ export class MainComponent implements OnInit {
|
|||||||
customQualityConfiguration = audio_formats[this.selectedQuality]['format_id'];
|
customQualityConfiguration = audio_formats[this.selectedQuality]['format_id'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customArgs = (this.customArgsEnabled ? this.customArgs : null);
|
||||||
|
const customOutput = (this.customOutputEnabled ? this.customOutput : null);
|
||||||
|
|
||||||
this.postsService.makeMP3(this.url, (this.selectedQuality === '' ? null : this.selectedQuality),
|
this.postsService.makeMP3(this.url, (this.selectedQuality === '' ? null : this.selectedQuality),
|
||||||
customQualityConfiguration).subscribe(posts => {
|
customQualityConfiguration, customArgs, customOutput).subscribe(posts => {
|
||||||
// update download object
|
// update download object
|
||||||
new_download.downloading = false;
|
new_download.downloading = false;
|
||||||
new_download.percent_complete = 100;
|
new_download.percent_complete = 100;
|
||||||
@@ -516,8 +538,11 @@ export class MainComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customArgs = (this.customArgsEnabled ? this.customArgs : null);
|
||||||
|
const customOutput = (this.customOutputEnabled ? this.customOutput : null);
|
||||||
|
|
||||||
this.postsService.makeMP4(this.url, (this.selectedQuality === '' ? null : this.selectedQuality),
|
this.postsService.makeMP4(this.url, (this.selectedQuality === '' ? null : this.selectedQuality),
|
||||||
customQualityConfiguration).subscribe(posts => {
|
customQualityConfiguration, customArgs, customOutput).subscribe(posts => {
|
||||||
// update download object
|
// update download object
|
||||||
new_download.downloading = false;
|
new_download.downloading = false;
|
||||||
new_download.percent_complete = 100;
|
new_download.percent_complete = 100;
|
||||||
@@ -744,6 +769,20 @@ export class MainComponent implements OnInit {
|
|||||||
localStorage.setItem('multiDownloadMode', new_val.checked.toString());
|
localStorage.setItem('multiDownloadMode', new_val.checked.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
customArgsEnabledChanged(new_val) {
|
||||||
|
localStorage.setItem('customArgsEnabled', new_val.checked.toString());
|
||||||
|
if (new_val.checked === true && this.customOutputEnabled) {
|
||||||
|
this.customOutputEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customOutputEnabledChanged(new_val) {
|
||||||
|
localStorage.setItem('customOutputEnabled', new_val.checked.toString());
|
||||||
|
if (new_val.checked === true && this.customArgsEnabled) {
|
||||||
|
this.customArgsEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getAudioAndVideoFormats(formats): any[] {
|
getAudioAndVideoFormats(formats): any[] {
|
||||||
const audio_formats = {};
|
const audio_formats = {};
|
||||||
const video_formats = {};
|
const video_formats = {};
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export class PlayerComponent implements OnInit {
|
|||||||
for (let i = 0; i < this.fileNames.length; i++) {
|
for (let i = 0; i < this.fileNames.length; i++) {
|
||||||
const fileName = this.fileNames[i];
|
const fileName = this.fileNames[i];
|
||||||
const baseLocation = (this.type === 'audio') ? this.audioFolderPath : this.videoFolderPath;
|
const baseLocation = (this.type === 'audio') ? this.audioFolderPath : this.videoFolderPath;
|
||||||
const fullLocation = this.baseStreamPath + baseLocation + fileName; // + (this.type === 'audio' ? '.mp3' : '.mp4');
|
const fullLocation = this.baseStreamPath + baseLocation + encodeURI(fileName); // + (this.type === 'audio' ? '.mp3' : '.mp4');
|
||||||
const mediaObject: IMedia = {
|
const mediaObject: IMedia = {
|
||||||
title: fileName,
|
title: fileName,
|
||||||
src: fullLocation,
|
src: fullLocation,
|
||||||
|
|||||||
@@ -43,16 +43,22 @@ export class PostsService {
|
|||||||
return this.http.get(this.startPath + 'audiofolder');
|
return this.http.get(this.startPath + 'audiofolder');
|
||||||
}
|
}
|
||||||
|
|
||||||
makeMP3(url: string, selectedQuality: string, customQualityConfiguration: string) {
|
// tslint:disable-next-line: max-line-length
|
||||||
|
makeMP3(url: string, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, customOutput: string = null) {
|
||||||
return this.http.post(this.path + 'tomp3', {url: url,
|
return this.http.post(this.path + 'tomp3', {url: url,
|
||||||
maxBitrate: selectedQuality,
|
maxBitrate: selectedQuality,
|
||||||
customQualityConfiguration: customQualityConfiguration});
|
customQualityConfiguration: customQualityConfiguration,
|
||||||
|
customArgs: customArgs,
|
||||||
|
customOutput: customOutput});
|
||||||
}
|
}
|
||||||
|
|
||||||
makeMP4(url: string, selectedQuality: string, customQualityConfiguration: string) {
|
// tslint:disable-next-line: max-line-length
|
||||||
|
makeMP4(url: string, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, customOutput: string = null) {
|
||||||
return this.http.post(this.path + 'tomp4', {url: url,
|
return this.http.post(this.path + 'tomp4', {url: url,
|
||||||
selectedHeight: selectedQuality,
|
selectedHeight: selectedQuality,
|
||||||
customQualityConfiguration: customQualityConfiguration});
|
customQualityConfiguration: customQualityConfiguration,
|
||||||
|
customArgs: customArgs,
|
||||||
|
customOutput: customOutput});
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileStatusMp3(name: string) {
|
getFileStatusMp3(name: string) {
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": ""
|
"custom_downloading_agent": "",
|
||||||
|
"allow_advanced_download": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user