Quality preferences can now be selected for non-YT videos and YT playlists

pull/809/head
Tzahi12345 3 years ago
parent 0161f544aa
commit 61973510f7

@ -1589,6 +1589,10 @@ components:
type: string type: string
description: Height of the video, if known description: Height of the video, if known
example: '1080' example: '1080'
maxHeight:
type: string
description: Max height that should be used, useful for playlists. selectedHeight will override this.
example: '1080'
maxBitrate: maxBitrate:
type: string type: string
description: Specify ffmpeg/avconv audio quality description: Specify ffmpeg/avconv audio quality

@ -813,6 +813,7 @@ app.post('/api/downloadFile', optionalJwt, async function(req, res) {
additionalArgs: req.body.additionalArgs, additionalArgs: req.body.additionalArgs,
customOutput: req.body.customOutput, customOutput: req.body.customOutput,
selectedHeight: req.body.selectedHeight, selectedHeight: req.body.selectedHeight,
maxHeight: req.body.maxHeight,
customQualityConfiguration: req.body.customQualityConfiguration, customQualityConfiguration: req.body.customQualityConfiguration,
youtubeUsername: req.body.youtubeUsername, youtubeUsername: req.body.youtubeUsername,
youtubePassword: req.body.youtubePassword, youtubePassword: req.body.youtubePassword,
@ -843,6 +844,7 @@ app.post('/api/generateArgs', optionalJwt, async function(req, res) {
additionalArgs: req.body.additionalArgs, additionalArgs: req.body.additionalArgs,
customOutput: req.body.customOutput, customOutput: req.body.customOutput,
selectedHeight: req.body.selectedHeight, selectedHeight: req.body.selectedHeight,
maxHeight: req.body.maxHeight,
customQualityConfiguration: req.body.customQualityConfiguration, customQualityConfiguration: req.body.customQualityConfiguration,
youtubeUsername: req.body.youtubeUsername, youtubeUsername: req.body.youtubeUsername,
youtubePassword: req.body.youtubePassword, youtubePassword: req.body.youtubePassword,

@ -433,7 +433,8 @@ exports.generateArgs = async (url, type, options, user_uid = null, simulated = f
if (customQualityConfiguration) { if (customQualityConfiguration) {
qualityPath = ['-f', customQualityConfiguration, '--merge-output-format', 'mp4']; qualityPath = ['-f', customQualityConfiguration, '--merge-output-format', 'mp4'];
} else if (heightParam && heightParam !== '' && !is_audio) { } else if (heightParam && heightParam !== '' && !is_audio) {
qualityPath = ['-f', `'(mp4)[height${maxHeight ? '<' : ''}=${heightParam}]`]; const heightFilter = (maxHeight && default_downloader === 'yt-dlp') ? ['-S', `res:${heightParam}`] : ['-f', `best[height${maxHeight ? '<' : ''}=${heightParam}]+bestaudio`]
qualityPath = [...heightFilter, '--merge-output-format', 'mp4'];
} else if (is_audio) { } else if (is_audio) {
qualityPath = ['--audio-quality', maxBitrate ? maxBitrate : '0'] qualityPath = ['--audio-quality', maxBitrate ? maxBitrate : '0']
} }

@ -35,6 +35,10 @@ export type DownloadRequest = {
* Height of the video, if known * Height of the video, if known
*/ */
selectedHeight?: string; selectedHeight?: string;
/**
* Max height that should be used, useful for playlists. selectedHeight will override this.
*/
maxHeight?: string;
/** /**
* Specify ffmpeg/avconv audio quality * Specify ffmpeg/avconv audio quality
*/ */

@ -19,17 +19,24 @@
Quality Quality
</ng-container> </ng-container>
</mat-label> </mat-label>
<mat-select [ngModelOptions]="{standalone: true}" [(ngModel)]="selectedQuality" (ngModelChange)="argsChanged($event)"> <mat-select [disabled]="url === '' || cachedAvailableFormats[url] && cachedAvailableFormats[url]['formats_loading']" [ngModelOptions]="{standalone: true}" [(ngModel)]="selectedQuality" (ngModelChange)="argsChanged($event)">
<mat-option [value]="''"> <mat-option i18n="Best" [value]="''">
Max Best
</mat-option> </mat-option>
<ng-container *ngIf="url && cachedAvailableFormats && cachedAvailableFormats[url]?.formats"> <ng-container *ngIf="url && cachedAvailableFormats && cachedAvailableFormats[url]?.formats && !cachedAvailableFormats[url]?.formats_failed">
<ng-container *ngFor="let option of cachedAvailableFormats[url]['formats'][audioOnly ? 'audio' : 'video']"> <ng-container *ngFor="let option of cachedAvailableFormats[url]['formats'][audioOnly ? 'audio' : 'video']">
<mat-option *ngIf="option.key !== 'best_audio_format'" [value]="option"> <mat-option *ngIf="option.key !== 'best_audio_format'" [value]="option">
{{option.key}} {{option.key}}
</mat-option> </mat-option>
</ng-container> </ng-container>
</ng-container> </ng-container>
<ng-container *ngIf="url && cachedAvailableFormats && cachedAvailableFormats[url]?.formats_failed">
<ng-container *ngFor="let option of qualityOptions[audioOnly ? 'audio' : 'video']">
<mat-option [value]="option.value">
{{option.label}}
</mat-option>
</ng-container>
</ng-container>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<div class="spinner-div" *ngIf="url !== '' && cachedAvailableFormats[url] && cachedAvailableFormats[url]['formats_loading']"> <div class="spinner-div" *ngIf="url !== '' && cachedAvailableFormats[url] && cachedAvailableFormats[url]['formats_loading']">
@ -60,7 +67,7 @@
</div> </div>
</form> </form>
<br/> <br/>
<mat-checkbox [disabled]="autoplay && current_download" (change)="videoModeChanged($event)" [(ngModel)]="audioOnly" style="float: left; margin-top: -12px"> <mat-checkbox [disabled]="autoplay && current_download" (change)="videoModeChanged($event)" [(ngModel)]="audioOnly" style="float: left; margin-top: -12px; margin-left: 4px;">
<ng-container i18n="Only Audio checkbox"> <ng-container i18n="Only Audio checkbox">
Only Audio Only Audio
</ng-container> </ng-container>
@ -74,7 +81,7 @@
</div> </div>
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button style="margin-left: 8px; margin-bottom: 8px" (click)="downloadClicked()" [disabled]="downloadingfile" type="submit" mat-stroked-button color="accent"> <button style="margin-left: 8px; margin-bottom: 8px" (click)="downloadClicked()" [disabled]="downloadingfile || url === ''" type="submit" mat-stroked-button color="accent">
<ng-container i18n="Main download button"> <ng-container i18n="Main download button">
Download Download
</ng-container> </ng-container>

@ -77,11 +77,6 @@ export class MainComponent implements OnInit {
qualityOptions = { qualityOptions = {
'video': [ 'video': [
{
'resolution': null,
'value': '',
'label': 'Max'
},
{ {
'resolution': '3840x2160', 'resolution': '3840x2160',
'value': '2160', 'value': '2160',
@ -124,50 +119,47 @@ export class MainComponent implements OnInit {
} }
], ],
'audio': [ 'audio': [
{ // TODO: implement
'kbitrate': null, // {
'value': '', // 'kbitrate': '256',
'label': 'Max' // 'value': '256K',
}, // 'label': '256 Kbps'
{ // },
'kbitrate': '256', // {
'value': '256K', // 'kbitrate': '160',
'label': '256 Kbps' // 'value': '160K',
}, // 'label': '160 Kbps'
{ // },
'kbitrate': '160', // {
'value': '160K', // 'kbitrate': '128',
'label': '160 Kbps' // 'value': '128K',
}, // 'label': '128 Kbps'
{ // },
'kbitrate': '128', // {
'value': '128K', // 'kbitrate': '96',
'label': '128 Kbps' // 'value': '96K',
}, // 'label': '96 Kbps'
{ // },
'kbitrate': '96', // {
'value': '96K', // 'kbitrate': '70',
'label': '96 Kbps' // 'value': '70K',
}, // 'label': '70 Kbps'
{ // },
'kbitrate': '70', // {
'value': '70K', // 'kbitrate': '50',
'label': '70 Kbps' // 'value': '50K',
}, // 'label': '50 Kbps'
{ // },
'kbitrate': '50', // {
'value': '50K', // 'kbitrate': '32',
'label': '50 Kbps' // 'value': '32K',
}, // 'label': '32 Kbps'
{ // }
'kbitrate': '32',
'value': '32K',
'label': '32 Kbps'
}
] ]
} }
selectedQuality = ''; selectedMaxQuality = '';
selectedQuality: string | unknown = '';
formats_loading = false; formats_loading = false;
@ViewChild('urlinput', { read: ElementRef }) urlInput: ElementRef; @ViewChild('urlinput', { read: ElementRef }) urlInput: ElementRef;
@ -378,7 +370,7 @@ export class MainComponent implements OnInit {
const urls = this.getURLArray(this.url); const urls = this.getURLArray(this.url);
for (let i = 0; i < urls.length; i++) { for (let i = 0; i < urls.length; i++) {
const url = urls[i]; const url = urls[i];
this.postsService.downloadFile(url, type as FileType, (selected_quality === '' ? null : selected_quality), this.postsService.downloadFile(url, type as FileType, (customQualityConfiguration || selected_quality === '' || typeof selected_quality !== 'string' ? null : selected_quality),
customQualityConfiguration, customArgs, additionalArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => { customQualityConfiguration, customArgs, additionalArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => {
this.current_download = res['download']; this.current_download = res['download'];
this.downloads.push(res['download']); this.downloads.push(res['download']);
@ -410,7 +402,7 @@ export class MainComponent implements OnInit {
} }
getSelectedAudioFormat(): string { getSelectedAudioFormat(): string {
if (this.selectedQuality === '') { return null; } if (typeof this.selectedQuality === 'string') { return null; }
const cachedFormatsExists = this.cachedAvailableFormats[this.url] && this.cachedAvailableFormats[this.url]['formats']; const cachedFormatsExists = this.cachedAvailableFormats[this.url] && this.cachedAvailableFormats[this.url]['formats'];
if (cachedFormatsExists) { if (cachedFormatsExists) {
return this.selectedQuality['format_id']; return this.selectedQuality['format_id'];
@ -420,7 +412,7 @@ export class MainComponent implements OnInit {
} }
getSelectedVideoFormat(): string { getSelectedVideoFormat(): string {
if (this.selectedQuality === '') { return null; } if (typeof this.selectedQuality === 'string') { return null; }
const cachedFormats = this.cachedAvailableFormats[this.url] && this.cachedAvailableFormats[this.url]['formats']; const cachedFormats = this.cachedAvailableFormats[this.url] && this.cachedAvailableFormats[this.url]['formats'];
if (cachedFormats) { if (cachedFormats) {
if (this.selectedQuality) { if (this.selectedQuality) {
@ -496,6 +488,7 @@ export class MainComponent implements OnInit {
} }
inputChanged(new_val: string): void { inputChanged(new_val: string): void {
this.selectedQuality = '';
if (new_val === '' || !new_val) { if (new_val === '' || !new_val) {
this.results_showing = false; this.results_showing = false;
} else { } else {
@ -537,13 +530,16 @@ export class MainComponent implements OnInit {
} }
getURLInfo(url: string): void { getURLInfo(url: string): void {
if (!this.cachedAvailableFormats[url]) {
this.cachedAvailableFormats[url] = {};
}
// if url is a youtube playlist, skip getting url info // if url is a youtube playlist, skip getting url info
if (url.includes('playlist')) { if (url.includes('playlist')) {
// make it think that formats errored so that users have options
this.cachedAvailableFormats[url]['formats_loading'] = false;
this.cachedAvailableFormats[url]['formats_failed'] = true;
return; return;
} }
if (!this.cachedAvailableFormats[url]) {
this.cachedAvailableFormats[url] = {};
}
if (!(this.cachedAvailableFormats[url] && this.cachedAvailableFormats[url]['formats'])) { if (!(this.cachedAvailableFormats[url] && this.cachedAvailableFormats[url]['formats'])) {
this.cachedAvailableFormats[url]['formats_loading'] = true; this.cachedAvailableFormats[url]['formats_loading'] = true;
this.postsService.getFileFormats([url]).subscribe(res => { this.postsService.getFileFormats([url]).subscribe(res => {
@ -584,7 +580,7 @@ export class MainComponent implements OnInit {
} }
} }
this.postsService.generateArgs(this.url, type as FileType, (this.selectedQuality === '' ? null : this.selectedQuality), this.postsService.generateArgs(this.url, type as FileType, (customQualityConfiguration || this.selectedQuality === '' || typeof this.selectedQuality !== 'string' ? null : this.selectedQuality),
customQualityConfiguration, customArgs, additionalArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => { customQualityConfiguration, customArgs, additionalArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => {
const simulated_args = res['args']; const simulated_args = res['args'];
if (simulated_args) { if (simulated_args) {
@ -601,6 +597,7 @@ export class MainComponent implements OnInit {
errorFormats(url: string): void { errorFormats(url: string): void {
this.cachedAvailableFormats[url]['formats_loading'] = false; this.cachedAvailableFormats[url]['formats_loading'] = false;
this.cachedAvailableFormats[url]['formats_failed'] = true;
console.error('Could not load formats for url ' + url); console.error('Could not load formats for url ' + url);
} }

@ -287,11 +287,10 @@ export class PostsService implements CanActivate {
}); });
} }
// tslint:disable-next-line: max-line-length
// tslint:disable-next-line: max-line-length // tslint:disable-next-line: max-line-length
downloadFile(url: string, type: FileType, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, additionalArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings: CropFileSettings = null) { downloadFile(url: string, type: FileType, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, additionalArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings: CropFileSettings = null) {
const body: DownloadRequest = {url: url, const body: DownloadRequest = {url: url,
selectedHeight: selectedQuality, maxHeight: selectedQuality,
customQualityConfiguration: customQualityConfiguration, customQualityConfiguration: customQualityConfiguration,
customArgs: customArgs, customArgs: customArgs,
additionalArgs: additionalArgs, additionalArgs: additionalArgs,
@ -305,7 +304,7 @@ export class PostsService implements CanActivate {
generateArgs(url: string, type: FileType, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, additionalArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings = null) { generateArgs(url: string, type: FileType, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, additionalArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings = null) {
const body: DownloadRequest = {url: url, const body: DownloadRequest = {url: url,
selectedHeight: selectedQuality, maxHeight: selectedQuality,
customQualityConfiguration: customQualityConfiguration, customQualityConfiguration: customQualityConfiguration,
customArgs: customArgs, customArgs: customArgs,
additionalArgs: additionalArgs, additionalArgs: additionalArgs,

Loading…
Cancel
Save