feat: Add selectable video codec (#47)

This commit is contained in:
Jelle Glebbeek
2021-07-29 21:27:42 +02:00
parent 87706769bd
commit 4dba2b1a61
13 changed files with 155 additions and 25 deletions

View File

@@ -161,7 +161,7 @@ function startCriticalHandlers(env) {
queryManager.saveThumb(args.url);
break;
case "getSize":
return await queryManager.getSize(args.identifier, args.formatLabel, args.audioOnly, args.videoOnly, args.clicked);
return await queryManager.getSize(args.identifier, args.formatLabel, args.audioOnly, args.videoOnly, args.clicked, args.encoding);
case "setSubtitles":
queryManager.setSubtitle(args);
break;

View File

@@ -134,6 +134,7 @@ class QueryManager {
downloadVideo(args) {
let downloadVideo = this.getVideo(args.identifier);
downloadVideo.selectedEncoding = args.encoding;
downloadVideo.audioOnly = args.type === "audio";
downloadVideo.videoOnly = args.type === "videoOnly";
if(!downloadVideo.audioOnly) {
@@ -162,6 +163,7 @@ class QueryManager {
let videoMetadata = [];
for(const videoObj of args.videos) {
let video = this.getVideo(videoObj.identifier);
video.selectedEncoding = videoObj.encoding;
if(video.videos == null) {
if(video.downloaded || video.type !== "single") continue;
video.audioOnly = videoObj.type === "audio";
@@ -253,8 +255,9 @@ class QueryManager {
});
}
async getSize(identifier, formatLabel, audioOnly, videoOnly, clicked) {
async getSize(identifier, formatLabel, audioOnly, videoOnly, clicked, encoding) {
const video = this.getVideo(identifier);
video.selectedEncoding = encoding;
const cachedSize = this.getCachedSize(video, formatLabel, audioOnly, videoOnly);
if(cachedSize != null) {
//The size for this format was already looked up

View File

@@ -140,6 +140,13 @@ class Utils {
if(dataFormat.height == null) continue;
let format = new Format(dataFormat.height, dataFormat.fps, null, null);
if(!detectedFormats.includes(format.getDisplayName())) {
for(const dataFormat of metadata.formats) {
const vcodec = dataFormat.vcodec;
if(dataFormat.height !== format.height || dataFormat.fps !== format.fps) continue;
if(vcodec == null || vcodec === "none") continue;
if(format.encodings.includes(vcodec)) continue;
format.encodings.push(vcodec);
}
formats.push(format);
detectedFormats.push(format.getDisplayName());
}

View File

@@ -39,15 +39,16 @@ class DownloadQuery extends Query {
} else {
if (this.video.formats.length !== 0) {
let format;
const encoding = this.video.selectedEncoding === "none" ? "" : "[vcodec=" + this.video.selectedEncoding + "]"
if(this.video.videoOnly) {
format = `bestvideo[height=${this.format.height}][fps=${this.format.fps}]/bestvideo[height=${this.format.height}]/best[height=${this.format.height}]/bestvideo/best`;
format = `bestvideo[height=${this.format.height}][fps=${this.format.fps}]${encoding}/bestvideo[height=${this.format.height}][fps=${this.format.fps}]/bestvideo[height=${this.format.height}]/best[height=${this.format.height}]/bestvideo/best`;
if (this.format.fps == null) {
format = `bestvideo[height=${this.format.height}]/best[height=${this.format.height}]/bestvideo/best`
format = `bestvideo[height=${this.format.height}]${encoding}/bestvideo[height=${this.format.height}]/best[height=${this.format.height}]/bestvideo/best`
}
} else {
format = `bestvideo[height=${this.format.height}][fps=${this.format.fps}]+${this.video.audioQuality}audio/bestvideo[height=${this.format.height}]+${this.video.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`;
format = `bestvideo[height=${this.format.height}][fps=${this.format.fps}]${encoding}+${this.video.audioQuality}audio/bestvideo[height=${this.format.height}][fps=${this.format.fps}]+${this.video.audioQuality}audio/bestvideo[height=${this.format.height}]+${this.video.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`;
if (this.format.fps == null) {
format = `bestvideo[height=${this.format.height}]+${this.video.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`
format = `bestvideo[height=${this.format.height}]${encoding}+${this.video.audioQuality}audio/bestvideo[height=${this.format.height}]+${this.video.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`
}
}
args = [

View File

@@ -2,7 +2,7 @@ const os = require("os");
const fs = require("fs").promises;
class Settings {
constructor(paths, env, outputFormat, audioOutputFormat, downloadPath, proxy, rateLimit, autoFillClipboard, spoofUserAgent, validateCertificate, taskList, nameFormat, nameFormatMode, sizeMode, splitMode, maxConcurrent, updateBinary, updateApplication, cookiePath, statSend, downloadMetadata, downloadThumbnail, keepUnmerged, calculateTotalSize, theme) {
constructor(paths, env, outputFormat, audioOutputFormat, downloadPath, proxy, rateLimit, autoFillClipboard, spoofUserAgent, validateCertificate, enableEncoding, taskList, nameFormat, nameFormatMode, sizeMode, splitMode, maxConcurrent, updateBinary, updateApplication, cookiePath, statSend, downloadMetadata, downloadThumbnail, keepUnmerged, calculateTotalSize, theme) {
this.paths = paths;
this.env = env
this.outputFormat = outputFormat == null ? "none" : outputFormat;
@@ -13,6 +13,7 @@ class Settings {
this.autoFillClipboard = autoFillClipboard == null ? true : autoFillClipboard;
this.spoofUserAgent = spoofUserAgent == null ? true : spoofUserAgent;
this.validateCertificate = validateCertificate == null ? false : validateCertificate;
this.enableEncoding = enableEncoding == null ? false : enableEncoding;
this.taskList = taskList == null ? true : taskList;
this.nameFormat = nameFormat == null ? "%(title).200s-(%(height)sp%(fps).0d).%(ext)s" : nameFormat;
this.nameFormatMode = nameFormatMode == null ? "%(title).200s-(%(height)sp%(fps).0d).%(ext)s" : nameFormatMode;
@@ -45,6 +46,7 @@ class Settings {
data.autoFillClipboard,
data.spoofUserAgent,
data.validateCertificate,
data.enableEncoding,
data.taskList,
data.nameFormat,
data.nameFormatMode,
@@ -78,6 +80,7 @@ class Settings {
this.autoFillClipboard = settings.autoFillClipboard;
this.spoofUserAgent = settings.spoofUserAgent;
this.validateCertificate = settings.validateCertificate;
this.enableEncoding = settings.enableEncoding;
this.taskList = settings.taskList;
this.nameFormat = settings.nameFormat;
this.nameFormatMode = settings.nameFormatMode;
@@ -110,6 +113,7 @@ class Settings {
autoFillClipboard: this.autoFillClipboard,
spoofUserAgent: this.spoofUserAgent,
validateCertificate: this.validateCertificate,
enableEncoding: this.enableEncoding,
taskList: this.taskList,
nameFormat: this.nameFormat,
nameFormatMode: this.nameFormatMode,

View File

@@ -12,13 +12,15 @@ class SizeQuery extends Query {
}
async connect() {
let formatArgument = `bestvideo[height=${this.format.height}][fps=${this.format.fps}]+${this.audioQuality}audio/bestvideo[height=${this.format.height}]+${this.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`;
const encoding = this.video.selectedEncoding === "none" ? "" : "[vcodec=" + this.video.selectedEncoding + "]"
let formatArgument = `bestvideo[height=${this.format.height}][fps=${this.format.fps}]${encoding}+${this.audioQuality}audio/bestvideo[height=${this.format.height}][fps=${this.format.fps}]+${this.audioQuality}audio/bestvideo[height=${this.format.height}]+${this.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`;
if (this.format.fps == null) {
formatArgument = `bestvideo[height=${this.format.height}]+${this.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`;
formatArgument = `bestvideo[height=${this.format.height}]${encoding}+${this.audioQuality}audio/bestvideo[height=${this.format.height}]+${this.audioQuality}audio/best[height=${this.format.height}]/bestvideo+bestaudio/best`;
}
if(this.audioOnly) {
formatArgument = `bestvideo+${this.format}audio/bestvideo+bestaudio/best`;
}
let output = await this.environment.metadataLimiter.schedule(() => this.start(this.video.url, ["-J", "--flat-playlist", "-f", formatArgument]));
let data = JSON.parse(output);
let totalSize = 0;

View File

@@ -5,6 +5,7 @@ class Format {
this.fps = fps;
this.filesize = filesize;
this.filesize_label = filesize_label;
this.encodings = [];
}
getDisplayName() {
@@ -21,7 +22,8 @@ class Format {
fps: this.fps,
filesize: this.filesize,
filesize_label: this.filesize_label,
display_name: this.getDisplayName()
display_name: this.getDisplayName(),
encodings: this.encodings
};
}

View File

@@ -205,7 +205,8 @@ select {
.video-card {
max-width: 700px;
height: 140px;
min-height: 140px;
max-height: 155px;
margin: 1em 1em 0 1em;
background-color: var(--bg-color);
padding: 0.75em 0 0.75em 0.75em;
@@ -217,7 +218,7 @@ select {
white-space: nowrap;
overflow: hidden;
text-overflow: clip;
max-width: 330px;
max-width: 360px;
}
@media only screen and (max-width: 1483px) {
@@ -228,7 +229,7 @@ select {
.video-card .custom-select {
height: unset;
line-height: 1.2;
line-height: 1.3;
width: 160px;
margin-bottom: 1em;
}
@@ -255,6 +256,10 @@ select {
text-decoration: underline;
}
.video-card .metadata {
margin-top: 0.25em;
}
.video-card a {
cursor: pointer;
transition: 150ms color;
@@ -287,7 +292,7 @@ select {
border-radius: 3px;
object-fit: cover;
width: 100%;
max-height: 110px;
max-height: 130px;
background-color: var(--secondary-bg-color);
}
@@ -295,7 +300,7 @@ select {
content: ' ';
display: block;
position: absolute;
max-height: 110px;
max-height: 130px;
width: 100%;
object-fit: cover;
background-image: url("img/plain-placeholder.png");

View File

@@ -99,6 +99,9 @@
<option value="audio">Audio only</option>
<option value="videoOnly">Video only</option>
</select>
<select class="custom-select download-encoding">
<option class="none" value="none" selected>Video codec</option>
</select>
<p class="metadata left"></p>
</div>
<div class="col-6">
@@ -349,6 +352,10 @@
<input class="check-input" type="checkbox" value="" id="validateCertificate">
<label class="check-label" for="validateCertificate">Validate HTTPS certificates</label>
</div>
<div class="mb-1">
<input class="check-input" type="checkbox" value="" id="enableEncoding">
<label class="check-label" for="enableEncoding">Show available encodings to download</label>
</div>
<div>
<label for="splitMode" class="form-label">Split playlists into separate videos when:</label>
<select class="custom-select d-block rounded w-auto mb-2" id="splitMode">

View File

@@ -119,6 +119,9 @@ async function init() {
}).on('change', '.custom-select.download-quality', function() {
const card = $(this).closest('.video-card');
updateSize($(card).prop('id'), false);
}).on('change', '.custom-select.download-encoding', function() {
const card = $(this).closest('.video-card');
updateSize($(card).prop('id'), false);
});
$('#download-quality, #download-type').on('change', () => updateAllVideoSettings());
@@ -166,6 +169,7 @@ async function init() {
proxy: $('#proxySetting').val(),
spoofUserAgent: $('#spoofUserAgent').prop('checked'),
validateCertificate: $('#validateCertificate').prop('checked'),
enableEncoding: $('#enableEncoding').prop('checked'),
taskList: $('#taskList').prop('checked'),
nameFormatMode: $('#nameFormat').val(),
nameFormat: $('#nameFormatCustom').val(),
@@ -181,6 +185,7 @@ async function init() {
}
window.settings = settings;
window.main.invoke("settingsAction", {action: "save", settings});
updateEncodingDropdown(settings.enableEncoding);
toggleWhiteMode(settings.theme);
});
@@ -203,6 +208,7 @@ async function init() {
$('#updateApplication').prop('checked', settings.updateApplication);
$('#spoofUserAgent').prop('checked', settings.spoofUserAgent);
$('#validateCertificate').prop('checked', settings.validateCertificate);
$('#enableEncoding').prop('checked', settings.enableEncoding);
$('#taskList').prop('checked', settings.taskList);
$('#autoFillClipboard').prop('checked', settings.autoFillClipboard);
$('#ratelimitSetting').val(settings.rateLimit);
@@ -304,6 +310,7 @@ async function init() {
identifier: card.id,
url: $(card).find('.url').val(),
format: $(card).find('.custom-select.download-quality').val(),
encoding: $(card).find('.custom-select.download-encoding').val(),
type: $(card).find('.custom-select.download-type').val(),
downloadSubs: !$(card).find('.subtitle-btn i').hasClass("bi-card-text-strike")
})
@@ -311,12 +318,13 @@ async function init() {
videos.push({
identifier: card.id,
format: $(card).find('.custom-select.download-quality').val(),
encoding: $(card).find('.custom-select.download-encoding').val(),
type: $(card).find('.custom-select.download-type').val(),
downloadSubs: !$(card).find('.subtitle-btn i').hasClass("bi-card-text-strike")
})
}
$(card).find('.progress').addClass("d-flex");
$(card).find('.metadata.left').html('<strong>Speed: </strong>' + "0.00MiB/s");
$(card).find('.metadata.left').html('<strong>Speed: </strong>' + "0.00MiB/s").show();
$(card).find('.metadata.right').html('<strong>ETA: </strong>' + "Unknown");
$(card).find('.options').addClass("d-flex");
$(card).find('select').addClass("d-none");
@@ -459,6 +467,13 @@ function showToast(toastInfo) {
if($(`#${toastInfo.type}`).is(':visible')) $(`#${toastInfo.type}`).toast('show').css('visibility', 'visible');
}
function updateEncodingDropdown(enabled) {
$('.video-cards').children().each(function() {
$(this).find('.metadata.left').toggle(!enabled);
$(this).find('.custom-select.download-encoding').toggle(enabled);
})
}
function updateGlobalDownloadQuality() {
const formats = [];
const currentFormats = [];
@@ -500,7 +515,8 @@ function parseFormatString(string) {
};
}
function addVideo(args) {
async function addVideo(args) {
await settingExists();
let template = $('.template.video-card').clone();
$(template).removeClass('template');
$(template).prop('id', args.identifier);
@@ -517,6 +533,12 @@ function addVideo(args) {
$(template).find('.info').addClass("d-none");
$(template).find('.progress small').html("Setting up environment")
$(template).find('.metadata.left').html('<strong>Duration: </strong>' + ((args.duration == null) ? "Unknown" : args.duration));
if(window.settings.enableEncoding) {
$(template).find('.metadata.left').hide();
} else {
$(template).find('.custom-select.download-encoding').hide();
}
if(!args.hasFilesizes) {
$(template).find('.metadata.right').html('<strong>Size: </strong>Unknown');
} else if(args.loadSize) {
@@ -543,11 +565,44 @@ function addVideo(args) {
$(template).find('.subtitle-btn, .subtitle-btn i').addClass("disabled");
}
for(const format of args.formats) {
//Add the quality (1080p60)
let option = new Option(format.display_name, format.display_name);
$(template).find('.custom-select.download-quality').append(option);
$(option).addClass("video");
//Add the encoding (vp9) associated with the quality (1080p60)
for(const encoding of format.encodings) {
let encodingOption = new Option(encoding, encoding);
$(template).find('.custom-select.download-encoding').append(encodingOption);
$(encodingOption).addClass(format.display_name);
}
}
$(template).find('.custom-select.download-quality').on('change', function () {
const newValue = this.value;
const encodingValue = $(template).find('.custom-select.download-encoding :selected').val();
for(const elem of $(template).find('.custom-select.download-encoding option')) {
if($(elem).hasClass(newValue)) {
$(elem).show();
} else if(!$(elem).hasClass("none")) {
$(elem).hide();
}
}
let foundElement = false;
for(const elem of $(template).find('.custom-select.download-encoding option')) {
if($(elem).val() === encodingValue && $(elem).hasClass(newValue)) {
$(elem).attr('selected','selected');
foundElement = true;
break;
}
}
if(!foundElement) {
$(template).find('.custom-select.download-encoding').val("none");
}
});
$(template).find('.custom-select.download-type').change();
//Initialize remove video popover
$(template).find('.remove-btn').popover();
$(document).click(function(event) {
@@ -565,6 +620,7 @@ function addVideo(args) {
url: args.url,
identifier: args.identifier,
format: $(template).find('.custom-select.download-quality').val(),
encoding: $(template).find('.custom-select.download-encoding').val(),
type: $(template).find('.custom-select.download-type').val(),
downloadType: "single"
}
@@ -572,7 +628,7 @@ function addVideo(args) {
$('#downloadBtn, #clearBtn').prop("disabled", true);
updateGlobalDownloadQuality();
$(template).find('.progress').addClass("d-flex");
$(template).find('.metadata.left').html('<strong>Speed: </strong>' + "0.00MiB/s");
$(template).find('.metadata.left').html('<strong>Speed: </strong>' + "0.00MiB/s").show();
$(template).find('.metadata.right').html('<strong>ETA: </strong>' + "Unknown");
$(template).find('.options').addClass("d-flex");
$(template).find('select').addClass("d-none");
@@ -648,15 +704,21 @@ function removeVideo(card) {
}
}
function setUnifiedPlaylist(args) {
async function setUnifiedPlaylist(args) {
await settingExists();
const card = getCard(args.identifier);
$(card).addClass("unified");
$(card).append(`<input type="hidden" class="url" value="${args.url}">`);
$(card).find('.progress').addClass("d-none").removeClass("d-flex");
$(card).find('.options').addClass("d-flex");
$(card).find('.info').addClass("d-none").removeClass("d-flex");
$(card).find('.metadata.left').html('<strong>Playlist size: </strong>' + args.length);
if(args.uploader != null) $(card).find('.metadata.right').html('<strong>Uploader: </strong>' + args.uploader);
$(card).find('.metadata.right').html('<strong>Playlist size: </strong>' + args.length);
$(card).find('.metadata.left').html('<strong>Uploader: </strong>' + (args.uploader == null ? "Unknown" : args.uploader));
if(window.settings.enableEncoding) {
$(card).find('.metadata.left').hide();
} else {
$(card).find('.custom-select.download-encoding').hide();
}
if(args.subtitles) $(card).find('.subtitle-btn i').removeClass("bi-card-text-strike").addClass("bi-card-text").attr("title", "Subtitles enabled");
$(card).find('img').prop("src", args.thumb);
$(card).find('.card-title')
@@ -692,6 +754,7 @@ function setUnifiedPlaylist(args) {
identifier: args.identifier,
format: $(card).find('.custom-select.download-quality').val(),
type: $(card).find('.custom-select.download-type').val(),
encoding: $(card).find('.custom-select.download-encoding').val(),
downloadType: "unified"
}
window.main.invoke("videoAction", downloadArgs);
@@ -706,10 +769,44 @@ function setUnifiedPlaylist(args) {
});
for(const format of args.formats) {
//Add the quality (1080p60)
let option = new Option(format.display_name, format.display_name);
$(card).find('.custom-select.download-quality').append(option);
$(option).addClass("video");
//Add the encoding (vp9) associated with the quality (1080p60)
for(const encoding of format.encodings) {
let encodingOption = new Option(encoding, encoding);
$(card).find('.custom-select.download-encoding').append(encodingOption);
$(encodingOption).addClass(format.display_name);
}
}
$(card).find('.custom-select.download-quality').on('change', function () {
const newValue = this.value;
const encodingValue = $(card).find('.custom-select.download-encoding :selected').val();
for(const elem of $(card).find('.custom-select.download-encoding option')) {
if($(elem).hasClass(newValue)) {
$(elem).show();
} else if(!$(elem).hasClass("none")) {
$(elem).hide();
}
}
let foundElement = false;
for(const elem of $(card).find('.custom-select.download-encoding option')) {
if($(elem).val() === encodingValue && $(elem).hasClass(newValue)) {
$(elem).attr('selected','selected');
foundElement = true;
break;
}
}
if(!foundElement) {
$(card).find('.custom-select.download-encoding').val("none");
}
});
$(card).find('.custom-select.download-type').change();
$(card).find('.open .folder').on('click', () => {
window.main.invoke("videoAction", {action: "open", identifier: args.identifier, type: "folder"});
});
@@ -767,7 +864,7 @@ function updateProgress(args) {
if(!progressCooldown.includes(args.identifier)) {
progressCooldown.push(args.identifier);
$(card).find('.metadata.right').html('<strong>ETA: </strong>' + args.progress.eta);
$(card).find('.metadata.left').html('<strong>Speed: </strong>' + args.progress.speed);
$(card).find('.metadata.left').html('<strong>Speed: </strong>' + args.progress.speed).show();
setTimeout(() => {
progressCooldown = progressCooldown.filter(item => item !== args.identifier);
}, 200);
@@ -806,6 +903,7 @@ function updateSize(identifier, clicked) {
action: "getSize",
identifier: identifier,
formatLabel: formatLabel,
encoding: $(card).find('.custom-select.download-encoding').val(),
audioOnly: $(card).find('.custom-select.download-type').val() === "audio",
videoOnly: $(card).find('.custom-select.download-type').val() === "videoOnly",
clicked: clicked

View File

@@ -36,6 +36,7 @@ describe('Serialization', () => {
height: 1440,
fps: 30,
filesize: 999,
encodings: [],
filesize_label: "400 MB",
display_name: "1440p30"
});

View File

@@ -2,8 +2,8 @@ const fs = require('fs').promises;
const os = require("os");
const Settings = require('../modules/persistence/Settings');
const env = {version: "2.0.0-test1", app: {getPath: jest.fn().mockReturnValue("test/path")}};
const defaultSettingsInstance = new Settings({settings: "tests/test-settings.json"}, env, "none", "none", "test/path", "", "", true, true, false, true, "%(title).200s-(%(height)sp%(fps).0d).%(ext)s", "%(title).200s-(%(height)sp%(fps).0d).%(ext)s", "click", "49", 8, true, true, "C:\\Users\\user\\cookies.txt", false, true, false, false, true, "dark");
const defaultSettings = "{\"outputFormat\":\"none\",\"audioOutputFormat\":\"none\",\"downloadPath\":\"test/path\",\"proxy\":\"\",\"rateLimit\":\"\",\"autoFillClipboard\":true,\"spoofUserAgent\":true,\"validateCertificate\":false,\"taskList\":true,\"nameFormat\":\"%(title).200s-(%(height)sp%(fps).0d).%(ext)s\",\"nameFormatMode\":\"%(title).200s-(%(height)sp%(fps).0d).%(ext)s\",\"sizeMode\":\"click\",\"splitMode\":\"49\",\"maxConcurrent\":8,\"defaultConcurrent\":8,\"updateBinary\":true,\"updateApplication\":true,\"statSend\":false,\"downloadMetadata\":true,\"downloadThumbnail\":false,\"keepUnmerged\":false,\"calculateTotalSize\":true,\"theme\":\"dark\",\"version\":\"2.0.0-test1\"}"
const defaultSettingsInstance = new Settings({settings: "tests/test-settings.json"}, env, "none", "none", "test/path", "", "", true, true, false, false, true, "%(title).200s-(%(height)sp%(fps).0d).%(ext)s", "%(title).200s-(%(height)sp%(fps).0d).%(ext)s", "click", "49", 8, true, true, "C:\\Users\\user\\cookies.txt", false, true, false, false, true, "dark");
const defaultSettings = "{\"outputFormat\":\"none\",\"audioOutputFormat\":\"none\",\"downloadPath\":\"test/path\",\"proxy\":\"\",\"rateLimit\":\"\",\"autoFillClipboard\":true,\"spoofUserAgent\":true,\"validateCertificate\":false,\"enableEncoding\":false,\"taskList\":true,\"nameFormat\":\"%(title).200s-(%(height)sp%(fps).0d).%(ext)s\",\"nameFormatMode\":\"%(title).200s-(%(height)sp%(fps).0d).%(ext)s\",\"sizeMode\":\"click\",\"splitMode\":\"49\",\"maxConcurrent\":8,\"defaultConcurrent\":8,\"updateBinary\":true,\"updateApplication\":true,\"statSend\":false,\"downloadMetadata\":true,\"downloadThumbnail\":false,\"keepUnmerged\":false,\"calculateTotalSize\":true,\"theme\":\"dark\",\"version\":\"2.0.0-test1\"}"
describe('Load settings from file', () => {
beforeEach(() => {

View File

@@ -1 +1 @@
{"outputFormat":"none","audioOutputFormat":"none","downloadPath": "test/path","proxy": "","rateLimit": "","autoFillClipboard":true,"spoofUserAgent":true,"validateCertificate": false,"taskList":true,"nameFormat":"%(title).200s-(%(height)sp%(fps).0d).%(ext)s","nameFormatMode":"%(title).200s-(%(height)sp%(fps).0d).%(ext)s","sizeMode":"click","splitMode":"49","maxConcurrent":8,"defaultConcurrent":8,"updateBinary":true,"updateApplication":true,"cookiePath":"C:\\Users\\user\\cookies.txt","statSend":false,"downloadMetadata":true,"downloadThumbnail":false,"keepUnmerged":false,"calculateTotalSize":true,"theme": "dark","version":"2.0.0-test1"}
{"outputFormat":"none","audioOutputFormat":"none","downloadPath": "test/path","proxy": "","rateLimit": "","autoFillClipboard":true,"spoofUserAgent":true,"validateCertificate": false,"enableEncoding": false,"taskList":true,"nameFormat":"%(title).200s-(%(height)sp%(fps).0d).%(ext)s","nameFormatMode":"%(title).200s-(%(height)sp%(fps).0d).%(ext)s","sizeMode":"click","splitMode":"49","maxConcurrent":8,"defaultConcurrent":8,"updateBinary":true,"updateApplication":true,"cookiePath":"C:\\Users\\user\\cookies.txt","statSend":false,"downloadMetadata":true,"downloadThumbnail":false,"keepUnmerged":false,"calculateTotalSize":true,"theme": "dark","version":"2.0.0-test1"}