1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge branch 'jellyfin:master' into cast-with-localhost-server

This commit is contained in:
Sky High 2023-09-12 23:20:02 +02:00 committed by GitHub
commit 8d3e8eb5b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 179 additions and 85 deletions

12
package-lock.json generated
View file

@ -38,7 +38,7 @@
"flv.js": "1.6.2", "flv.js": "1.6.2",
"headroom.js": "0.12.0", "headroom.js": "0.12.0",
"history": "5.3.0", "history": "5.3.0",
"hls.js": "1.4.4", "hls.js": "github:nyanmisaka/hls.js#v1.5.0-fix-firefox-av1",
"intersection-observer": "0.12.2", "intersection-observer": "0.12.2",
"jassub": "1.7.1", "jassub": "1.7.1",
"jellyfin-apiclient": "1.10.0", "jellyfin-apiclient": "1.10.0",
@ -9460,9 +9460,8 @@
} }
}, },
"node_modules/hls.js": { "node_modules/hls.js": {
"version": "1.4.4", "resolved": "git+ssh://git@github.com/nyanmisaka/hls.js.git#2ca771e97a15d8078a3850c4c4cf225f497dcaa7",
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.4.tgz", "license": "Apache-2.0"
"integrity": "sha512-Yix3i1klHtTWIj8Fa/yoN5mFreY3eLKGrmVldpkQ+2Bb1PmEok9Ah/VfAzlJnwtInCo4rs5l6/W2tUh76DaSNA=="
}, },
"node_modules/hoist-non-react-statics": { "node_modules/hoist-non-react-statics": {
"version": "3.3.2", "version": "3.3.2",
@ -27345,9 +27344,8 @@
} }
}, },
"hls.js": { "hls.js": {
"version": "1.4.4", "version": "git+ssh://git@github.com/nyanmisaka/hls.js.git#2ca771e97a15d8078a3850c4c4cf225f497dcaa7",
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.4.tgz", "from": "hls.js@github:nyanmisaka/hls.js#v1.5.0-fix-firefox-av1"
"integrity": "sha512-Yix3i1klHtTWIj8Fa/yoN5mFreY3eLKGrmVldpkQ+2Bb1PmEok9Ah/VfAzlJnwtInCo4rs5l6/W2tUh76DaSNA=="
}, },
"hoist-non-react-statics": { "hoist-non-react-statics": {
"version": "3.3.2", "version": "3.3.2",

View file

@ -93,7 +93,7 @@
"flv.js": "1.6.2", "flv.js": "1.6.2",
"headroom.js": "0.12.0", "headroom.js": "0.12.0",
"history": "5.3.0", "history": "5.3.0",
"hls.js": "1.4.4", "hls.js": "github:nyanmisaka/hls.js#v1.5.0-fix-firefox-av1",
"intersection-observer": "0.12.2", "intersection-observer": "0.12.2",
"jassub": "1.7.1", "jassub": "1.7.1",
"jellyfin-apiclient": "1.10.0", "jellyfin-apiclient": "1.10.0",

View file

@ -3,41 +3,32 @@ import browser from '../scripts/browser';
import dialog from './dialog/dialog'; import dialog from './dialog/dialog';
import globalize from '../scripts/globalize'; import globalize from '../scripts/globalize';
function useNativeAlert() { export default async function (text, title) {
// webOS seems to block modals // Modals seem to be blocked on Web OS and Tizen 2.x
// Tizen 2.x seems to block modals const canUseNativeAlert = !!(
return !browser.web0s !browser.web0s
&& !(browser.tizenVersion && browser.tizenVersion < 3) && !(browser.tizenVersion && browser.tizenVersion < 3)
&& browser.tv && browser.tv
&& window.alert; && window.alert
} );
export default async function (text, title) { const options = typeof text === 'string' ? { title, text } : text;
let options;
if (typeof text === 'string') {
options = {
title: title,
text: text
};
} else {
options = text;
}
await appRouter.ready(); await appRouter.ready();
if (useNativeAlert()) { if (canUseNativeAlert) {
alert((options.text || '').replaceAll('<br/>', '\n')); alert((options.text || '').replaceAll('<br/>', '\n'));
return Promise.resolve();
} else {
const items = [];
items.push({ return Promise.resolve();
}
options.buttons = [
{
name: globalize.translate('ButtonGotIt'), name: globalize.translate('ButtonGotIt'),
id: 'ok', id: 'ok',
type: 'submit' type: 'submit'
}); }
];
options.buttons = items;
return dialog.show(options); return dialog.show(options);
} }
}

View file

@ -16,11 +16,14 @@ function getBaseProfileOptions(item) {
if (browser.edge) { if (browser.edge) {
disableHlsVideoAudioCodecs.push('mp3'); disableHlsVideoAudioCodecs.push('mp3');
} }
if (!browser.edgeChromium) {
disableHlsVideoAudioCodecs.push('ac3'); disableHlsVideoAudioCodecs.push('ac3');
disableHlsVideoAudioCodecs.push('eac3'); disableHlsVideoAudioCodecs.push('eac3');
}
if (!(browser.chrome || browser.edgeChromium || browser.firefox)) {
disableHlsVideoAudioCodecs.push('opus'); disableHlsVideoAudioCodecs.push('opus');
} }
}
return { return {
enableMkvProgressive: false, enableMkvProgressive: false,

View file

@ -43,8 +43,8 @@ export function enableHlsJsPlayer(runTimeTicks, mediaType) {
} }
if (canPlayNativeHls()) { if (canPlayNativeHls()) {
// Having trouble with chrome's native support and transcoded music // Android Webview's native HLS has performance and compatiblity issues
if (browser.android && mediaType === 'Audio') { if (browser.android && (mediaType === 'Audio' || mediaType === 'Video')) {
return true; return true;
} }

View file

@ -124,6 +124,12 @@
<span>${AllowHevcEncoding}</span> <span>${AllowHevcEncoding}</span>
</label> </label>
</div> </div>
<div class="checkboxList">
<label>
<input type="checkbox" is="emby-checkbox" id="chkAllowAv1Encoding" />
<span>${AllowAv1Encoding}</span>
</label>
</div>
</div> </div>
<div class="vppTonemappingOptions hide"> <div class="vppTonemappingOptions hide">

View file

@ -18,6 +18,7 @@ function loadPage(page, config, systemInfo) {
page.querySelector('#chkIntelLpHevcHwEncoder').checked = config.EnableIntelLowPowerHevcHwEncoder; page.querySelector('#chkIntelLpHevcHwEncoder').checked = config.EnableIntelLowPowerHevcHwEncoder;
page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding; page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding;
page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding; page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding;
page.querySelector('#chkAllowAv1Encoding').checked = config.AllowAv1Encoding;
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType); $('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
$('#selectThreadCount', page).val(config.EncodingThreadCount); $('#selectThreadCount', page).val(config.EncodingThreadCount);
page.querySelector('#chkEnableAudioVbr').checked = config.EnableAudioVbr; page.querySelector('#chkEnableAudioVbr').checked = config.EnableAudioVbr;
@ -123,6 +124,7 @@ function onSubmit() {
config.EnableIntelLowPowerHevcHwEncoder = form.querySelector('#chkIntelLpHevcHwEncoder').checked; config.EnableIntelLowPowerHevcHwEncoder = form.querySelector('#chkIntelLpHevcHwEncoder').checked;
config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked; config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked;
config.AllowHevcEncoding = form.querySelector('#chkAllowHevcEncoding').checked; config.AllowHevcEncoding = form.querySelector('#chkAllowHevcEncoding').checked;
config.AllowAv1Encoding = form.querySelector('#chkAllowAv1Encoding').checked;
ApiClient.updateNamedConfiguration('encoding', config).then(function () { ApiClient.updateNamedConfiguration('encoding', config).then(function () {
updateEncoder(form); updateEncoder(form);
}, function () { }, function () {

View file

@ -2,12 +2,6 @@
<button is="paper-icon-button-light" id="btnBookplayerToc" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1"> <button is="paper-icon-button-light" id="btnBookplayerToc" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon toc" aria-hidden="true"></span> <span class="material-icons bookplayerButtonIcon toc" aria-hidden="true"></span>
</button> </button>
<!-- <button is="paper-icon-button-light" id="btnBookplayerPrev" class="autoSize bookplayerButton pageButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon navigate_before" aria-hidden="true"></span> ${Previous}
</button>
<button is="paper-icon-button-light" id="btnBookplayerNext" class="autoSize bookplayerButton pageButton hide-mouse-idle-tv" tabindex="-1">
${Next} <span class="material-icons bookplayerButtonIcon navigate_next" aria-hidden="true"></span>
</button> -->
<button is="paper-icon-button-light" id="btnBookplayerExit" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1"> <button is="paper-icon-button-light" id="btnBookplayerExit" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon close" aria-hidden="true"></span> <span class="material-icons bookplayerButtonIcon close" aria-hidden="true"></span>
</button> </button>

View file

@ -26,7 +26,7 @@ export function isEnabled() {
const playerId = localStorage.getItem('autocastPlayerId'); const playerId = localStorage.getItem('autocastPlayerId');
const currentPlayerInfo = playbackManager.getPlayerInfo(); const currentPlayerInfo = playbackManager.getPlayerInfo();
return (currentPlayerInfo && playerId && currentPlayerInfo.id === playerId); return playerId && currentPlayerInfo?.id === playerId;
} }
function onOpen() { function onOpen() {

View file

@ -148,15 +148,12 @@ let _supportsCssAnimation;
let _supportsCssAnimationWithPrefix; let _supportsCssAnimationWithPrefix;
function supportsCssAnimation(allowPrefix) { function supportsCssAnimation(allowPrefix) {
// TODO: Assess if this is still needed, as all of our targets should natively support CSS animations. // TODO: Assess if this is still needed, as all of our targets should natively support CSS animations.
if (allowPrefix) { if (allowPrefix && (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false)) {
if (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false) {
return _supportsCssAnimationWithPrefix; return _supportsCssAnimationWithPrefix;
} }
} else {
if (_supportsCssAnimation === true || _supportsCssAnimation === false) { if (_supportsCssAnimation === true || _supportsCssAnimation === false) {
return _supportsCssAnimation; return _supportsCssAnimation;
} }
}
let animation = false; let animation = false;
const domPrefixes = ['Webkit', 'O', 'Moz']; const domPrefixes = ['Webkit', 'O', 'Moz'];
@ -187,13 +184,13 @@ function supportsCssAnimation(allowPrefix) {
const uaMatch = function (ua) { const uaMatch = function (ua) {
ua = ua.toLowerCase(); ua = ua.toLowerCase();
const match = /(edg)[ /]([\w.]+)/.exec(ua) const match = /(chrome)[ /]([\w.]+)/.exec(ua)
|| /(edg)[ /]([\w.]+)/.exec(ua)
|| /(edga)[ /]([\w.]+)/.exec(ua) || /(edga)[ /]([\w.]+)/.exec(ua)
|| /(edgios)[ /]([\w.]+)/.exec(ua) || /(edgios)[ /]([\w.]+)/.exec(ua)
|| /(edge)[ /]([\w.]+)/.exec(ua) || /(edge)[ /]([\w.]+)/.exec(ua)
|| /(opera)[ /]([\w.]+)/.exec(ua) || /(opera)[ /]([\w.]+)/.exec(ua)
|| /(opr)[ /]([\w.]+)/.exec(ua) || /(opr)[ /]([\w.]+)/.exec(ua)
|| /(chrome)[ /]([\w.]+)/.exec(ua)
|| /(safari)[ /]([\w.]+)/.exec(ua) || /(safari)[ /]([\w.]+)/.exec(ua)
|| /(firefox)[ /]([\w.]+)/.exec(ua) || /(firefox)[ /]([\w.]+)/.exec(ua)
|| ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)

View file

@ -23,6 +23,17 @@ function canPlayHevc(videoTestElement, options) {
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, '')); || videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, ''));
} }
function canPlayAv1(videoTestElement) {
if (browser.tizenVersion >= 5.5 || browser.web0sVersion >= 5) {
return true;
}
// av1 main level 5.3
return !!videoTestElement.canPlayType
&& (videoTestElement.canPlayType('video/mp4; codecs="av01.0.15M.08"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="av01.0.15M.10"').replace(/no/, ''));
}
let _supportsTextTracks; let _supportsTextTracks;
function supportsTextTracks() { function supportsTextTracks() {
if (browser.tizen) { if (browser.tizen) {
@ -56,6 +67,14 @@ function canPlayNativeHls() {
|| media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, '')); || media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
} }
function canPlayNativeHlsInFmp4() {
if (browser.tizenVersion >= 3 || browser.web0sVersion >= 3.5) {
return true;
}
return (browser.iOS && browser.iOSVersion >= 11) || browser.osx;
}
function canPlayHlsWithMSE() { function canPlayHlsWithMSE() {
// text tracks dont work with this in firefox // text tracks dont work with this in firefox
return window.MediaSource != null; /* eslint-disable-line compat/compat */ return window.MediaSource != null; /* eslint-disable-line compat/compat */
@ -157,14 +176,6 @@ function testCanPlayMkv(videoTestElement) {
return !!browser.edgeUwp; return !!browser.edgeUwp;
} }
function testCanPlayAv1(videoTestElement) {
if (browser.tizenVersion >= 5.5 || browser.web0sVersion >= 5) {
return true;
}
return videoTestElement.canPlayType('video/webm; codecs="av01.0.15M.10"').replace(/no/, '');
}
function testCanPlayTs() { function testCanPlayTs() {
return browser.tizen || browser.web0s || browser.edgeUwp; return browser.tizen || browser.web0s || browser.edgeUwp;
} }
@ -437,8 +448,15 @@ export default function (options) {
// Do not use AC3 for audio transcoding unless AAC and MP3 are not supported. // Do not use AC3 for audio transcoding unless AAC and MP3 are not supported.
if (canPlayAc3VideoAudio) { if (canPlayAc3VideoAudio) {
videoAudioCodecs.push('ac3'); videoAudioCodecs.push('ac3');
if (browser.edgeChromium) {
hlsInFmp4VideoAudioCodecs.push('ac3');
}
if (canPlayEac3VideoAudio) { if (canPlayEac3VideoAudio) {
videoAudioCodecs.push('eac3'); videoAudioCodecs.push('eac3');
if (browser.edgeChromium) {
hlsInFmp4VideoAudioCodecs.push('eac3');
}
} }
if (canPlayAc3VideoAudioInHls) { if (canPlayAc3VideoAudioInHls) {
@ -492,6 +510,9 @@ export default function (options) {
if (browser.tizen) { if (browser.tizen) {
hlsInTsVideoAudioCodecs.push('opus'); hlsInTsVideoAudioCodecs.push('opus');
} }
if (!browser.safari) {
hlsInFmp4VideoAudioCodecs.push('opus');
}
} }
if (canPlayAudioFormat('flac')) { if (canPlayAudioFormat('flac')) {
@ -521,18 +542,23 @@ export default function (options) {
const hlsInTsVideoCodecs = []; const hlsInTsVideoCodecs = [];
const hlsInFmp4VideoCodecs = []; const hlsInFmp4VideoCodecs = [];
if ((browser.safari || browser.tizen || browser.web0s) && canPlayHevc(videoTestElement, options)) { if (canPlayAv1(videoTestElement)
&& !browser.mobile && (browser.edgeChromium || browser.firefox || browser.chrome)) {
// disable av1 on mobile since it can be very slow software decoding
hlsInFmp4VideoCodecs.push('av1');
}
if (canPlayHevc(videoTestElement, options)
&& (browser.edgeChromium || browser.safari || browser.tizen || browser.web0s || (browser.chrome && (!browser.android || browser.chrome.versionMajor >= 105)))) {
// Chromium used to support HEVC on Android but not via MSE
hlsInFmp4VideoCodecs.push('hevc'); hlsInFmp4VideoCodecs.push('hevc');
} }
if (canPlayH264(videoTestElement)) { if (canPlayH264(videoTestElement)) {
mp4VideoCodecs.push('h264'); mp4VideoCodecs.push('h264');
hlsInTsVideoCodecs.push('h264'); hlsInTsVideoCodecs.push('h264');
if (browser.safari || browser.tizen || browser.web0s) {
hlsInFmp4VideoCodecs.push('h264'); hlsInFmp4VideoCodecs.push('h264');
} }
}
if (canPlayHevc(videoTestElement, options)) { if (canPlayHevc(videoTestElement, options)) {
// safari is lying on HDR and 60fps videos, use fMP4 instead // safari is lying on HDR and 60fps videos, use fMP4 instead
@ -566,7 +592,7 @@ export default function (options) {
webmVideoCodecs.push('vp9'); webmVideoCodecs.push('vp9');
} }
if (testCanPlayAv1(videoTestElement)) { if (canPlayAv1(videoTestElement)) {
mp4VideoCodecs.push('av1'); mp4VideoCodecs.push('av1');
webmVideoCodecs.push('av1'); webmVideoCodecs.push('av1');
} }
@ -687,7 +713,11 @@ export default function (options) {
}); });
if (canPlayHls() && options.enableHls !== false) { if (canPlayHls() && options.enableHls !== false) {
if (hlsInFmp4VideoCodecs.length && hlsInFmp4VideoAudioCodecs.length && userSettings.preferFmp4HlsContainer() && (browser.safari || browser.tizen || browser.web0s)) { let enableFmp4Hls = userSettings.preferFmp4HlsContainer();
if ((browser.safari || browser.tizen || browser.web0s) && !canPlayNativeHlsInFmp4()) {
enableFmp4Hls = false;
}
if (hlsInFmp4VideoCodecs.length && hlsInFmp4VideoAudioCodecs.length && enableFmp4Hls) {
profile.TranscodingProfiles.push({ profile.TranscodingProfiles.push({
Container: 'mp4', Container: 'mp4',
Type: 'Video', Type: 'Video',
@ -817,6 +847,33 @@ export default function (options) {
hevcProfiles = 'main|main 10'; hevcProfiles = 'main|main 10';
} }
let maxAv1Level = 15; // level 5.3
const av1Profiles = 'main'; // av1 main covers 4:2:0 8 & 10 bits
// av1 main level 6.0
if (videoTestElement.canPlayType('video/mp4; codecs="av01.0.16M.08"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="av01.0.16M.10"').replace(/no/, '')) {
maxAv1Level = 16;
}
// av1 main level 6.1
if (videoTestElement.canPlayType('video/mp4; codecs="av01.0.17M.08"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="av01.0.17M.10"').replace(/no/, '')) {
maxAv1Level = 17;
}
// av1 main level 6.2
if (videoTestElement.canPlayType('video/mp4; codecs="av01.0.18M.08"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="av01.0.18M.10"').replace(/no/, '')) {
maxAv1Level = 18;
}
// av1 main level 6.3
if (videoTestElement.canPlayType('video/mp4; codecs="av01.0.19M.08"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="av01.0.19M.10"').replace(/no/, '')) {
maxAv1Level = 19;
}
const h264VideoRangeTypes = 'SDR'; const h264VideoRangeTypes = 'SDR';
let hevcVideoRangeTypes = 'SDR'; let hevcVideoRangeTypes = 'SDR';
let vp9VideoRangeTypes = 'SDR'; let vp9VideoRangeTypes = 'SDR';
@ -830,12 +887,15 @@ export default function (options) {
} }
if (browser.tizen || browser.web0s) { if (browser.tizen || browser.web0s) {
hevcVideoRangeTypes += '|HDR10|HLG|DOVI'; hevcVideoRangeTypes += '|HDR10|HLG';
vp9VideoRangeTypes += '|HDR10|HLG'; vp9VideoRangeTypes += '|HDR10|HLG';
av1VideoRangeTypes += '|HDR10|HLG'; av1VideoRangeTypes += '|HDR10|HLG';
} }
if (browser.edgeChromium || browser.chrome || browser.firefox) { // Chrome mobile and Firefox have no client side tone-mapping
// Edge Chromium on Nvidia is known to have color issues on 10-bit video
if (browser.chrome && !browser.mobile) {
hevcVideoRangeTypes += '|HDR10|HLG';
vp9VideoRangeTypes += '|HDR10|HLG'; vp9VideoRangeTypes += '|HDR10|HLG';
av1VideoRangeTypes += '|HDR10|HLG'; av1VideoRangeTypes += '|HDR10|HLG';
} }
@ -904,11 +964,29 @@ export default function (options) {
]; ];
const av1CodecProfileConditions = [ const av1CodecProfileConditions = [
{
Condition: 'NotEquals',
Property: 'IsAnamorphic',
Value: 'true',
IsRequired: false
},
{
Condition: 'EqualsAny',
Property: 'VideoProfile',
Value: av1Profiles,
IsRequired: false
},
{ {
Condition: 'EqualsAny', Condition: 'EqualsAny',
Property: 'VideoRangeType', Property: 'VideoRangeType',
Value: av1VideoRangeTypes, Value: av1VideoRangeTypes,
IsRequired: false IsRequired: false
},
{
Condition: 'LessThanEqual',
Property: 'VideoLevel',
Value: maxAv1Level.toString(),
IsRequired: false
} }
]; ];
@ -942,6 +1020,13 @@ export default function (options) {
Value: maxVideoWidth.toString(), Value: maxVideoWidth.toString(),
IsRequired: false IsRequired: false
}); });
av1CodecProfileConditions.push({
Condition: 'LessThanEqual',
Property: 'Width',
Value: maxVideoWidth.toString(),
IsRequired: false
});
} }
const globalMaxVideoBitrate = (getGlobalMaxVideoBitrate() || '').toString(); const globalMaxVideoBitrate = (getGlobalMaxVideoBitrate() || '').toString();
@ -950,6 +1035,8 @@ export default function (options) {
const hevcMaxVideoBitrate = globalMaxVideoBitrate; const hevcMaxVideoBitrate = globalMaxVideoBitrate;
const av1MaxVideoBitrate = globalMaxVideoBitrate;
if (h264MaxVideoBitrate) { if (h264MaxVideoBitrate) {
h264CodecProfileConditions.push({ h264CodecProfileConditions.push({
Condition: 'LessThanEqual', Condition: 'LessThanEqual',
@ -968,6 +1055,15 @@ export default function (options) {
}); });
} }
if (av1MaxVideoBitrate) {
av1CodecProfileConditions.push({
Condition: 'LessThanEqual',
Property: 'VideoBitrate',
Value: av1MaxVideoBitrate,
IsRequired: true
});
}
// On iOS 12.x, for TS container max h264 level is 4.2 // On iOS 12.x, for TS container max h264 level is 4.2
if (browser.iOS && browser.iOSVersion < 13) { if (browser.iOS && browser.iOSVersion < 13) {
const codecProfile = { const codecProfile = {

View file

@ -230,7 +230,6 @@ export function getDisplayTime(date) {
const timeLower = time.toLowerCase(); const timeLower = time.toLowerCase();
if (timeLower.indexOf('am') !== -1 || timeLower.indexOf('pm') !== -1) { if (timeLower.indexOf('am') !== -1 || timeLower.indexOf('pm') !== -1) {
time = timeLower;
let hour = date.getHours() % 12; let hour = date.getHours() % 12;
const suffix = date.getHours() > 11 ? 'pm' : 'am'; const suffix = date.getHours() > 11 ? 'pm' : 'am';
if (!hour) { if (!hour) {

View file

@ -1763,5 +1763,6 @@
"LabelSegmentKeepSeconds": "Doba ponechání částí", "LabelSegmentKeepSeconds": "Doba ponechání částí",
"LabelSegmentKeepSecondsHelp": "Čas v sekundách, po který budou části překódovaného souboru uloženy. Musí být delší než čas určený v \"Omezit po\". Funguje pouze při zapnuté funkci Odstranění částí.", "LabelSegmentKeepSecondsHelp": "Čas v sekundách, po který budou části překódovaného souboru uloženy. Musí být delší než čas určený v \"Omezit po\". Funguje pouze při zapnuté funkci Odstranění částí.",
"LabelBackdropScreensaverInterval": "Interval šetřiče \"Pozadí\"", "LabelBackdropScreensaverInterval": "Interval šetřiče \"Pozadí\"",
"LabelBackdropScreensaverIntervalHelp": "Čas v sekundách mezi změnou pozadí při použití šetřiče \"Pozadí\"." "LabelBackdropScreensaverIntervalHelp": "Čas v sekundách mezi změnou pozadí při použití šetřiče \"Pozadí\".",
"AllowAv1Encoding": "Povolit kódování do formátu AV1"
} }

View file

@ -1700,5 +1700,7 @@
"EnableCardLayout": "Vis visuel CardBox", "EnableCardLayout": "Vis visuel CardBox",
"ResolutionMatchSource": "Match kilde", "ResolutionMatchSource": "Match kilde",
"SubtitleCyan": "Cyan", "SubtitleCyan": "Cyan",
"SubtitleMagenta": "Magenta" "SubtitleMagenta": "Magenta",
"AllowCollectionManagement": "Tillad denne bruger at administrere samlinger",
"AllowSegmentDeletion": "Slet segmenter"
} }

View file

@ -1715,5 +1715,6 @@
"Unreleased": "Not yet released", "Unreleased": "Not yet released",
"LabelTonemappingMode": "Tone mapping mode", "LabelTonemappingMode": "Tone mapping mode",
"TonemappingModeHelp": "Select the tone mapping mode. If you experience blown out highlights try switching to the RGB mode.", "TonemappingModeHelp": "Select the tone mapping mode. If you experience blown out highlights try switching to the RGB mode.",
"Unknown": "Unknown" "Unknown": "Unknown",
"AllowAv1Encoding": "Allow encoding in AV1 format"
} }

View file

@ -1232,7 +1232,7 @@
"EnableTonemapping": "Käytä sävykartoitusta", "EnableTonemapping": "Käytä sävykartoitusta",
"EnableBlurHashHelp": "Kuvat, joita ladataan vielä, näytetään yksilöllisellä paikkamerkillä.", "EnableBlurHashHelp": "Kuvat, joita ladataan vielä, näytetään yksilöllisellä paikkamerkillä.",
"EnableBlurHash": "Ota sumennetut paikkamerkit käyttöön kuville", "EnableBlurHash": "Ota sumennetut paikkamerkit käyttöön kuville",
"AllowTonemappingHelp": "Sävykartoitus voi muuttaa videon dynaamisen alueen HDR:stä SDR:ksi säilyttäen samalla kuvan yksityiskohdat ja värit, jotka ovat kohtauksen alkuperäisen ilmeen kannalta erittäin tärkeitä. Toimii tällä hetkellä vain 10bit HDR10, HLG ja Dovi -videoiden kanssa ja edellyttää soveltuvaa OpenCL- tai CUDA-suoritusalustaa.", "AllowTonemappingHelp": "Sävykartoitus voi muuttaa videon dynaamisen alueen HDR:stä SDR:ksi säilyttäen samalla kuvan yksityiskohdat ja värit, jotka ovat kohtauksen alkuperäisen ilmeen kannalta erittäin tärkeitä. Toimii tällä hetkellä vain 10-bit HDR10-, HLG- ja DoVi-videoiden kanssa ja edellyttää soveltuvaa OpenCL- tai CUDA-suoritusalustaa.",
"LabelffmpegPathHelp": "FFmpeg-sovellustiedoston tai -kansion tiedostosijainti.", "LabelffmpegPathHelp": "FFmpeg-sovellustiedoston tai -kansion tiedostosijainti.",
"LabelKodiMetadataEnablePathSubstitutionHelp": "Mahdollistaa kuvien tiedostosijaintien korvauksen palvelimen korvausasetuksien perusteella.", "LabelKodiMetadataEnablePathSubstitutionHelp": "Mahdollistaa kuvien tiedostosijaintien korvauksen palvelimen korvausasetuksien perusteella.",
"ThumbCard": "Pienoiskortti", "ThumbCard": "Pienoiskortti",
@ -1761,5 +1761,6 @@
"LabelSegmentKeepSeconds": "Osioiden säilytysaika", "LabelSegmentKeepSeconds": "Osioiden säilytysaika",
"LabelSegmentKeepSecondsHelp": "Aika sekunteina, jonka osiot säilytetään ennen päällekirjoitusta. Oltava \"Rahoita kun on kulunut\" -aikaa suurempi. Toimii vain osioiden poiston ollessa käytössä.", "LabelSegmentKeepSecondsHelp": "Aika sekunteina, jonka osiot säilytetään ennen päällekirjoitusta. Oltava \"Rahoita kun on kulunut\" -aikaa suurempi. Toimii vain osioiden poiston ollessa käytössä.",
"LabelBackdropScreensaverInterval": "Taustanäytönsäästäjän ajoitus", "LabelBackdropScreensaverInterval": "Taustanäytönsäästäjän ajoitus",
"LabelBackdropScreensaverIntervalHelp": "Aika sekuntteina, jonka kuluttua kuva vaihtuu taustanäytönsäästäjää käytettäessä." "LabelBackdropScreensaverIntervalHelp": "Aika sekuntteina, jonka kuluttua kuva vaihtuu taustanäytönsäästäjää käytettäessä.",
"AllowAv1Encoding": "Salli enkoodaus AV1-muodossa"
} }

View file

@ -169,7 +169,7 @@
"EnableThemeSongsHelp": "Speel titelmuziek af tijdens het bladeren door de bibliotheek.", "EnableThemeSongsHelp": "Speel titelmuziek af tijdens het bladeren door de bibliotheek.",
"EnableThemeVideosHelp": "Speel titelfilms af op de achtergrond tijdens het bladeren door de bibliotheek.", "EnableThemeVideosHelp": "Speel titelfilms af op de achtergrond tijdens het bladeren door de bibliotheek.",
"Ended": "Gestopt", "Ended": "Gestopt",
"EndsAtValue": "Eindigt om {0}", "EndsAtValue": "Afgelopen om {0}",
"Episodes": "Afleveringen", "Episodes": "Afleveringen",
"ErrorAddingListingsToSchedulesDirect": "Er ging iets mis bij het toevoegen van de lineup aan uw Schedules Direct account. Schedules Direct staat maar een beperkt aantal lineups per account toe. Het kan nodig zijn dat u zich aan moet melden op de Schedules Direct-website en andere lineups moet verwijderen voordat u verder kunt.", "ErrorAddingListingsToSchedulesDirect": "Er ging iets mis bij het toevoegen van de lineup aan uw Schedules Direct account. Schedules Direct staat maar een beperkt aantal lineups per account toe. Het kan nodig zijn dat u zich aan moet melden op de Schedules Direct-website en andere lineups moet verwijderen voordat u verder kunt.",
"ErrorAddingMediaPathToVirtualFolder": "Er ging iets mis bij het toevoegen van het mediapad. Controleer of het pad klopt en of Jellyfin toegang heeft tot de locatie.", "ErrorAddingMediaPathToVirtualFolder": "Er ging iets mis bij het toevoegen van het mediapad. Controleer of het pad klopt en of Jellyfin toegang heeft tot de locatie.",
@ -1762,5 +1762,6 @@
"LabelThrottleDelaySecondsHelp": "Tijd in seconden waarna de transcoder wordt afgeknepen. Deze tijd moet voldoende lang zijn zodat de cliënt een gezonde buffer in stand kan houden. Werkt alleen als afknijpen is ingeschakeld.", "LabelThrottleDelaySecondsHelp": "Tijd in seconden waarna de transcoder wordt afgeknepen. Deze tijd moet voldoende lang zijn zodat de cliënt een gezonde buffer in stand kan houden. Werkt alleen als afknijpen is ingeschakeld.",
"LabelSegmentKeepSeconds": "Bewaartijd segmenten", "LabelSegmentKeepSeconds": "Bewaartijd segmenten",
"LabelBackdropScreensaverIntervalHelp": "Het aantal seconden dat een achtergrondafbeelding wordt getoond als onderdeel van de schermbeveiliging.", "LabelBackdropScreensaverIntervalHelp": "Het aantal seconden dat een achtergrondafbeelding wordt getoond als onderdeel van de schermbeveiliging.",
"LabelBackdropScreensaverInterval": "Interval schermbeveiliging" "LabelBackdropScreensaverInterval": "Interval schermbeveiliging",
"AllowAv1Encoding": "Coderen in AV1-formaat toestaan"
} }

View file

@ -1763,5 +1763,6 @@
"LabelThrottleDelaySeconds": "Ograniczaj po", "LabelThrottleDelaySeconds": "Ograniczaj po",
"LabelThrottleDelaySecondsHelp": "Czas w sekundach, po którym transkoder zostanie ograniczony. Musi być wystarczająco duży, aby klient mógł utrzymać właściwy bufor. Działa tylko wtedy, gdy włączone jest ograniczanie.", "LabelThrottleDelaySecondsHelp": "Czas w sekundach, po którym transkoder zostanie ograniczony. Musi być wystarczająco duży, aby klient mógł utrzymać właściwy bufor. Działa tylko wtedy, gdy włączone jest ograniczanie.",
"LabelBackdropScreensaverIntervalHelp": "Czas w sekundach między różnymi fototapetami podczas korzystania z wygaszacza ekranu z fototapetami.", "LabelBackdropScreensaverIntervalHelp": "Czas w sekundach między różnymi fototapetami podczas korzystania z wygaszacza ekranu z fototapetami.",
"LabelBackdropScreensaverInterval": "Interwał fototapet wygaszacza ekranu" "LabelBackdropScreensaverInterval": "Interwał fototapet wygaszacza ekranu",
"AllowAv1Encoding": "Zezwalaj na kodowanie w formacie AV1"
} }

View file

@ -1760,5 +1760,6 @@
"LabelSegmentKeepSecondsHelp": "Час у секундах, протягом якого сегменти мають зберігатися перед перезаписом. Має бути більшим за \"Обмежити після\". Працює тільки якщо увімкнено видалення сегментів.", "LabelSegmentKeepSecondsHelp": "Час у секундах, протягом якого сегменти мають зберігатися перед перезаписом. Має бути більшим за \"Обмежити після\". Працює тільки якщо увімкнено видалення сегментів.",
"LabelSegmentKeepSeconds": "Час збереження сегментів", "LabelSegmentKeepSeconds": "Час збереження сегментів",
"LabelBackdropScreensaverIntervalHelp": "Час у секундах між різними фонами при використанні фонової заставки.", "LabelBackdropScreensaverIntervalHelp": "Час у секундах між різними фонами при використанні фонової заставки.",
"LabelBackdropScreensaverInterval": "Інтервал між фоновими заставками" "LabelBackdropScreensaverInterval": "Інтервал між фоновими заставками",
"AllowAv1Encoding": "Дозволити кодування у форматі AV1"
} }