Added ability to select the max quality for a subscription. It defaults to 'best' which will get the best native mp4 video

This commit is contained in:
Isaac Abadi
2020-11-28 00:45:01 -05:00
parent 9895d77e01
commit 8938844ffa
7 changed files with 94 additions and 8 deletions

View File

@@ -2196,6 +2196,7 @@ app.post('/api/updateCategories', optionalJwt, async (req, res) => {
app.post('/api/subscribe', optionalJwt, async (req, res) => { app.post('/api/subscribe', optionalJwt, async (req, res) => {
let name = req.body.name; let name = req.body.name;
let url = req.body.url; let url = req.body.url;
let maxQuality = req.body.maxQuality;
let timerange = req.body.timerange; let timerange = req.body.timerange;
let streamingOnly = req.body.streamingOnly; let streamingOnly = req.body.streamingOnly;
let audioOnly = req.body.audioOnly; let audioOnly = req.body.audioOnly;
@@ -2205,6 +2206,7 @@ app.post('/api/subscribe', optionalJwt, async (req, res) => {
const new_sub = { const new_sub = {
name: name, name: name,
url: url, url: url,
maxQuality: maxQuality,
id: uuid(), id: uuid(),
streamingOnly: streamingOnly, streamingOnly: streamingOnly,
user_uid: user_uid, user_uid: user_uid,

View File

@@ -114,7 +114,11 @@ async function getSubscriptionInfo(sub, user_uid = null) {
continue; continue;
} }
if (!sub.name) { if (!sub.name) {
sub.name = sub.isPlaylist ? output_json.playlist_title : output_json.uploader; if (sub.isPlaylist) {
sub.name = output_json.playlist_title ? output_json.playlist_title : output_json.playlist;
} else {
sub.name = output_json.uploader;
}
// if it's now valid, update // if it's now valid, update
if (sub.name) { if (sub.name) {
if (user_uid) if (user_uid)
@@ -296,7 +300,8 @@ async function getVideosForSub(sub, user_uid = null) {
qualityPath.push('-x'); qualityPath.push('-x');
qualityPath.push('--audio-format', 'mp3'); qualityPath.push('--audio-format', 'mp3');
} else { } else {
qualityPath = ['-f', 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4'] if (!sub.maxQuality || sub.maxQuality === 'best') qualityPath = ['-f', 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4'];
else qualityPath = ['-f', `bestvideo[height<=${sub.maxQuality}]+bestaudio/best[height<=${sub.maxQuality}]`, '--merge-output-format', 'mp4'];
} }
downloadConfig.push(...qualityPath) downloadConfig.push(...qualityPath)
@@ -351,7 +356,7 @@ async function getVideosForSub(sub, user_uid = null) {
youtubedl.exec(sub.url, downloadConfig, {}, function(err, output) { youtubedl.exec(sub.url, downloadConfig, {}, function(err, output) {
logger.verbose('Subscription: finished check for ' + sub.name); logger.verbose('Subscription: finished check for ' + sub.name);
if (err && !output) { if (err && !output) {
logger.error(err.stderr); logger.error(err.stderr ? err.stderr : err.message);
if (err.stderr.includes('This video is unavailable')) { if (err.stderr.includes('This video is unavailable')) {
logger.info('An error was encountered with at least one video, backup method will be used.') logger.info('An error was encountered with at least one video, backup method will be used.')
try { try {

View File

@@ -24,6 +24,13 @@
<mat-checkbox [disabled]="true" [(ngModel)]="audioOnlyMode"><ng-container i18n="Streaming-only mode">Audio-only mode</ng-container></mat-checkbox> <mat-checkbox [disabled]="true" [(ngModel)]="audioOnlyMode"><ng-container i18n="Streaming-only mode">Audio-only mode</ng-container></mat-checkbox>
</div> </div>
</div> </div>
<div class="col-12 mt-2">
<mat-form-field>
<mat-select placeholder="Max quality" i18n-placeholder="Max quality placeholder" [disabled]="new_sub.type === 'audio'" [(ngModel)]="new_sub.maxQuality">
<mat-option *ngFor="let available_quality of available_qualities" [value]="available_quality['value']">{{available_quality['label']}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="col-12"> <div class="col-12">
<div> <div>
<mat-checkbox [disabled]="new_sub.type === 'audio'" [(ngModel)]="new_sub.streamingOnly"><ng-container i18n="Streaming-only mode">Streaming-only mode</ng-container></mat-checkbox> <mat-checkbox [disabled]="new_sub.type === 'audio'" [(ngModel)]="new_sub.streamingOnly"><ng-container i18n="Streaming-only mode">Streaming-only mode</ng-container></mat-checkbox>

View File

@@ -22,6 +22,36 @@ export class EditSubscriptionDialogComponent implements OnInit {
audioOnlyMode = null; audioOnlyMode = null;
download_all = null; download_all = null;
available_qualities = [
{
'label': 'Best',
'value': 'best'
},
{
'label': '4K',
'value': '2160'
},
{
'label': '1440p',
'value': '1440'
},
{
'label': '1080p',
'value': '1080'
},
{
'label': '720p',
'value': '720'
},
{
'label': '480p',
'value': '480'
},
{
'label': '360p',
'value': '360'
}
];
time_units = [ time_units = [
'day', 'day',

View File

@@ -35,6 +35,13 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-12 mt-2">
<mat-form-field>
<mat-select placeholder="Max quality" i18n-placeholder="Max quality placeholder" [disabled]="audioOnlyMode" [(ngModel)]="maxQuality">
<mat-option *ngFor="let available_quality of available_qualities" [value]="available_quality['value']">{{available_quality['label']}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="col-12"> <div class="col-12">
<div> <div>
<mat-checkbox [(ngModel)]="audioOnlyMode"><ng-container i18n="Streaming-only mode">Audio-only mode</ng-container></mat-checkbox> <mat-checkbox [(ngModel)]="audioOnlyMode"><ng-container i18n="Streaming-only mode">Audio-only mode</ng-container></mat-checkbox>

View File

@@ -17,6 +17,8 @@ export class SubscribeDialogComponent implements OnInit {
url = null; url = null;
name = null; name = null;
maxQuality = 'best';
// state // state
subscribing = false; subscribing = false;
@@ -29,12 +31,43 @@ export class SubscribeDialogComponent implements OnInit {
customFileOutput = ''; customFileOutput = '';
customArgs = ''; customArgs = '';
available_qualities = [
{
'label': 'Best',
'value': 'best'
},
{
'label': '4K',
'value': '2160'
},
{
'label': '1440p',
'value': '1440'
},
{
'label': '1080p',
'value': '1080'
},
{
'label': '720p',
'value': '720'
},
{
'label': '480p',
'value': '480'
},
{
'label': '360p',
'value': '360'
}
];
time_units = [ time_units = [
'day', 'day',
'week', 'week',
'month', 'month',
'year' 'year'
] ];
constructor(private postsService: PostsService, constructor(private postsService: PostsService,
private snackBar: MatSnackBar, private snackBar: MatSnackBar,
@@ -57,7 +90,7 @@ export class SubscribeDialogComponent implements OnInit {
if (!this.download_all) { if (!this.download_all) {
timerange = 'now-' + this.timerange_amount.toString() + this.timerange_unit; timerange = 'now-' + this.timerange_amount.toString() + this.timerange_unit;
} }
this.postsService.createSubscription(this.url, this.name, timerange, this.streamingOnlyMode, this.postsService.createSubscription(this.url, this.name, timerange, this.streamingOnlyMode, this.maxQuality,
this.audioOnlyMode, this.customArgs, this.customFileOutput).subscribe(res => { this.audioOnlyMode, this.customArgs, this.customFileOutput).subscribe(res => {
this.subscribing = false; this.subscribing = false;
if (res['new_sub']) { if (res['new_sub']) {

View File

@@ -337,9 +337,11 @@ export class PostsService implements CanActivate {
}); });
} }
createSubscription(url, name, timerange = null, streamingOnly = false, audioOnly = false, customArgs = null, customFileOutput = null) { createSubscription(url, name, timerange = null, streamingOnly = false, maxQuality = 'best', audioOnly = false,
return this.http.post(this.path + 'subscribe', {url: url, name: name, timerange: timerange, streamingOnly: streamingOnly, customArgs = null, customFileOutput = null) {
audioOnly: audioOnly, customArgs: customArgs, customFileOutput: customFileOutput}, this.httpOptions); return this.http.post(this.path + 'subscribe', {url: url, name: name, timerange: timerange, maxQuality: maxQuality,
streamingOnly: streamingOnly, audioOnly: audioOnly, customArgs: customArgs,
customFileOutput: customFileOutput}, this.httpOptions);
} }
updateSubscription(subscription) { updateSubscription(subscription) {