Add maximum allowed video resolution selector

This commit is contained in:
Dmitry Lyzo 2022-06-17 00:17:10 +03:00
parent 0bd774dd45
commit f06cd961d5
6 changed files with 80 additions and 6 deletions

View File

@ -39,7 +39,8 @@ function getDeviceProfile(item) {
profile = profileBuilder(builderOpts); profile = profileBuilder(builderOpts);
} }
const maxTranscodingVideoWidth = appHost.screen()?.maxAllowedWidth; const maxVideoWidth = appSettings.maxVideoWidth();
const maxTranscodingVideoWidth = maxVideoWidth < 0 ? appHost.screen()?.maxAllowedWidth : maxVideoWidth;
if (maxTranscodingVideoWidth) { if (maxTranscodingVideoWidth) {
profile.TranscodingProfiles.forEach((transcodingProfile) => { profile.TranscodingProfiles.forEach((transcodingProfile) => {

View File

@ -41,7 +41,7 @@ import template from './playbackSettings.template.html';
select.innerHTML = html; select.innerHTML = html;
} }
function setMaxBitrateIntoField(select, isInNetwork, mediatype) { function fillQuality(select, isInNetwork, mediatype, maxVideoWidth) {
const options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({ const options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({
currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype), currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype),
@ -52,7 +52,8 @@ import template from './playbackSettings.template.html';
currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype), currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype),
isAutomaticBitrateEnabled: appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype), isAutomaticBitrateEnabled: appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype),
enableAuto: true enableAuto: true,
maxVideoWidth
}); });
@ -60,6 +61,10 @@ import template from './playbackSettings.template.html';
// render empty string instead of 0 for the auto option // render empty string instead of 0 for the auto option
return `<option value="${i.bitrate || ''}">${i.name}</option>`; return `<option value="${i.bitrate || ''}">${i.name}</option>`;
}).join(''); }).join('');
}
function setMaxBitrateIntoField(select, isInNetwork, mediatype) {
fillQuality(select, isInNetwork, mediatype);
if (appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype)) { if (appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype)) {
select.value = ''; select.value = '';
@ -68,12 +73,13 @@ import template from './playbackSettings.template.html';
} }
} }
function fillChromecastQuality(select) { function fillChromecastQuality(select, maxVideoWidth) {
const options = qualityoptions.getVideoQualityOptions({ const options = qualityoptions.getVideoQualityOptions({
currentMaxBitrate: appSettings.maxChromecastBitrate(), currentMaxBitrate: appSettings.maxChromecastBitrate(),
isAutomaticBitrateEnabled: !appSettings.maxChromecastBitrate(), isAutomaticBitrateEnabled: !appSettings.maxChromecastBitrate(),
enableAuto: true enableAuto: true,
maxVideoWidth
}); });
select.innerHTML = options.map(i => { select.innerHTML = options.map(i => {
@ -192,6 +198,9 @@ import template from './playbackSettings.template.html';
const selectChromecastVersion = context.querySelector('.selectChromecastVersion'); const selectChromecastVersion = context.querySelector('.selectChromecastVersion');
selectChromecastVersion.value = userSettings.chromecastVersion(); selectChromecastVersion.value = userSettings.chromecastVersion();
const selectLabelMaxVideoWidth = context.querySelector('.selectLabelMaxVideoWidth');
selectLabelMaxVideoWidth.value = appSettings.maxVideoWidth();
const selectSkipForwardLength = context.querySelector('.selectSkipForwardLength'); const selectSkipForwardLength = context.querySelector('.selectSkipForwardLength');
fillSkipLengths(selectSkipForwardLength); fillSkipLengths(selectSkipForwardLength);
selectSkipForwardLength.value = userSettings.skipForwardLength(); selectSkipForwardLength.value = userSettings.skipForwardLength();
@ -209,6 +218,7 @@ import template from './playbackSettings.template.html';
appSettings.enableSystemExternalPlayers(context.querySelector('.chkExternalVideoPlayer').checked); appSettings.enableSystemExternalPlayers(context.querySelector('.chkExternalVideoPlayer').checked);
appSettings.maxChromecastBitrate(context.querySelector('.selectChromecastVideoQuality').value); appSettings.maxChromecastBitrate(context.querySelector('.selectChromecastVideoQuality').value);
appSettings.maxVideoWidth(context.querySelector('.selectLabelMaxVideoWidth').value);
setMaxBitrateFromField(context.querySelector('.selectVideoInNetworkQuality'), true, 'Video'); setMaxBitrateFromField(context.querySelector('.selectVideoInNetworkQuality'), true, 'Video');
setMaxBitrateFromField(context.querySelector('.selectVideoInternetQuality'), false, 'Video'); setMaxBitrateFromField(context.querySelector('.selectVideoInternetQuality'), false, 'Video');
@ -247,6 +257,36 @@ import template from './playbackSettings.template.html';
}); });
} }
function setSelectValue(select, value, defaultValue) {
select.value = value;
if (select.selectedIndex < 0) {
select.value = defaultValue;
}
}
function onMaxVideoWidthChange(e) {
const context = this.options.element;
const selectVideoInNetworkQuality = context.querySelector('.selectVideoInNetworkQuality');
const selectVideoInternetQuality = context.querySelector('.selectVideoInternetQuality');
const selectChromecastVideoQuality = context.querySelector('.selectChromecastVideoQuality');
const selectVideoInNetworkQualityValue = selectVideoInNetworkQuality.value;
const selectVideoInternetQualityValue = selectVideoInternetQuality.value;
const selectChromecastVideoQualityValue = selectChromecastVideoQuality.value;
const maxVideoWidth = parseInt(e.target.value || '0', 10) || 0;
fillQuality(selectVideoInNetworkQuality, true, 'Video', maxVideoWidth);
fillQuality(selectVideoInternetQuality, false, 'Video', maxVideoWidth);
fillChromecastQuality(selectChromecastVideoQuality, maxVideoWidth);
setSelectValue(selectVideoInNetworkQuality, selectVideoInNetworkQualityValue, '');
setSelectValue(selectVideoInternetQuality, selectVideoInternetQualityValue, '');
setSelectValue(selectChromecastVideoQuality, selectChromecastVideoQualityValue, '');
}
function onSubmit(e) { function onSubmit(e) {
const self = this; const self = this;
const apiClient = ServerConnections.getApiClient(self.options.serverId); const apiClient = ServerConnections.getApiClient(self.options.serverId);
@ -274,6 +314,8 @@ import template from './playbackSettings.template.html';
options.element.querySelector('.btnSave').classList.remove('hide'); options.element.querySelector('.btnSave').classList.remove('hide');
} }
options.element.querySelector('.selectLabelMaxVideoWidth').addEventListener('change', onMaxVideoWidthChange.bind(self));
self.loadData(); self.loadData();
if (options.autoFocus) { if (options.autoFocus) {

View File

@ -41,6 +41,19 @@
<div class="selectContainer fldChromecastQuality hide"> <div class="selectContainer fldChromecastQuality hide">
<select is="emby-select" class="selectChromecastVideoQuality" label="${LabelMaxChromecastBitrate}"></select> <select is="emby-select" class="selectChromecastVideoQuality" label="${LabelMaxChromecastBitrate}"></select>
</div> </div>
<div class="selectContainer">
<select is="emby-select" class="selectLabelMaxVideoWidth" label="${LabelMaxVideoResolution}">
<option value="0">${Auto}</option>
<option value="-1">${ScreenResolution}</option>
<option value="640">360p</option>
<option value="852">480p</option>
<option value="1280">720p</option>
<option value="1920">1080p</option>
<option value="3840">4K</option>
<option value="7680">8K</option>
</select>
</div>
</div> </div>
<div class="verticalSection verticalSection-extrabottompadding musicQualitySection hide"> <div class="verticalSection verticalSection-extrabottompadding musicQualitySection hide">

View File

@ -1,5 +1,6 @@
import { appHost } from '../components/apphost'; import { appHost } from '../components/apphost';
import globalize from '../scripts/globalize'; import globalize from '../scripts/globalize';
import appSettings from '../scripts/settings/appSettings';
export function getVideoQualityOptions(options) { export function getVideoQualityOptions(options) {
const maxStreamingBitrate = options.currentMaxBitrate; const maxStreamingBitrate = options.currentMaxBitrate;
@ -12,7 +13,9 @@ export function getVideoQualityOptions(options) {
videoWidth = videoHeight * (16 / 9); videoWidth = videoHeight * (16 / 9);
} }
const hostScreenWidth = appHost.screen()?.maxAllowedWidth || 4096; const maxVideoWidth = options.maxVideoWidth == null ? appSettings.maxVideoWidth() : options.maxVideoWidth;
const hostScreenWidth = (maxVideoWidth < 0 ? appHost.screen()?.maxAllowedWidth : maxVideoWidth) || 4096;
const maxAllowedWidth = videoWidth || 4096; const maxAllowedWidth = videoWidth || 4096;
const qualityOptions = []; const qualityOptions = [];

View File

@ -92,6 +92,19 @@ class AppSettings {
return val ? parseInt(val) : null; return val ? parseInt(val) : null;
} }
/**
* Get or set 'Maximum video width'
* @param {number|undefined} val - Maximum video width or undefined.
* @return {number} Maximum video width.
*/
maxVideoWidth(val) {
if (val !== undefined) {
return this.set('maxVideoWidth', val.toString());
}
return parseInt(this.get('maxVideoWidth') || '0', 10) || 0;
}
set(name, value, userId) { set(name, value, userId) {
const currentValue = this.get(name, userId); const currentValue = this.get(name, userId);
AppStorage.setItem(this.#getKey(name, userId), value); AppStorage.setItem(this.#getKey(name, userId), value);

View File

@ -708,6 +708,7 @@
"LabelLibraryPageSizeHelp": "Set the amount of items to show on a library page. Set to 0 in order to disable paging.", "LabelLibraryPageSizeHelp": "Set the amount of items to show on a library page. Set to 0 in order to disable paging.",
"LabelMaxDaysForNextUp": "Max days in 'Next Up':", "LabelMaxDaysForNextUp": "Max days in 'Next Up':",
"LabelMaxDaysForNextUpHelp": "Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.", "LabelMaxDaysForNextUpHelp": "Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.",
"LabelMaxVideoResolution": "Maximum Allowed Video Transcoding Resolution",
"LabelLineup": "Lineup:", "LabelLineup": "Lineup:",
"LabelLocalCustomCss": "Custom CSS code for styling which applies to this client only. You may want to disable server custom CSS code.", "LabelLocalCustomCss": "Custom CSS code for styling which applies to this client only. You may want to disable server custom CSS code.",
"LabelLocalHttpServerPortNumber": "Local HTTP port number:", "LabelLocalHttpServerPortNumber": "Local HTTP port number:",
@ -1377,6 +1378,7 @@
"ScanForNewAndUpdatedFiles": "Scan for new and updated files", "ScanForNewAndUpdatedFiles": "Scan for new and updated files",
"ScanLibrary": "Scan library", "ScanLibrary": "Scan library",
"Schedule": "Schedule", "Schedule": "Schedule",
"ScreenResolution": "Screen Resolution",
"Screenshot": "Screenshot", "Screenshot": "Screenshot",
"Screenshots": "Screenshots", "Screenshots": "Screenshots",
"Search": "Search", "Search": "Search",