diff --git a/package-lock.json b/package-lock.json index a2ca04bbd9..02e521e4fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "flv.js": "1.6.2", "headroom.js": "0.12.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", "jassub": "1.7.1", "jellyfin-apiclient": "1.10.0", @@ -9460,9 +9460,8 @@ } }, "node_modules/hls.js": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.4.tgz", - "integrity": "sha512-Yix3i1klHtTWIj8Fa/yoN5mFreY3eLKGrmVldpkQ+2Bb1PmEok9Ah/VfAzlJnwtInCo4rs5l6/W2tUh76DaSNA==" + "resolved": "git+ssh://git@github.com/nyanmisaka/hls.js.git#2ca771e97a15d8078a3850c4c4cf225f497dcaa7", + "license": "Apache-2.0" }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", @@ -27345,9 +27344,8 @@ } }, "hls.js": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.4.tgz", - "integrity": "sha512-Yix3i1klHtTWIj8Fa/yoN5mFreY3eLKGrmVldpkQ+2Bb1PmEok9Ah/VfAzlJnwtInCo4rs5l6/W2tUh76DaSNA==" + "version": "git+ssh://git@github.com/nyanmisaka/hls.js.git#2ca771e97a15d8078a3850c4c4cf225f497dcaa7", + "from": "hls.js@github:nyanmisaka/hls.js#v1.5.0-fix-firefox-av1" }, "hoist-non-react-statics": { "version": "3.3.2", diff --git a/package.json b/package.json index b192e0df56..5c9fd988a9 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "flv.js": "1.6.2", "headroom.js": "0.12.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", "jassub": "1.7.1", "jellyfin-apiclient": "1.10.0", diff --git a/src/components/alert.js b/src/components/alert.js index 6e654e9f3c..ebeed3d8fd 100644 --- a/src/components/alert.js +++ b/src/components/alert.js @@ -3,41 +3,32 @@ import browser from '../scripts/browser'; import dialog from './dialog/dialog'; import globalize from '../scripts/globalize'; -function useNativeAlert() { - // webOS seems to block modals - // Tizen 2.x seems to block modals - return !browser.web0s - && !(browser.tizenVersion && browser.tizenVersion < 3) - && browser.tv - && window.alert; -} - export default async function (text, title) { - let options; - if (typeof text === 'string') { - options = { - title: title, - text: text - }; - } else { - options = text; - } + // Modals seem to be blocked on Web OS and Tizen 2.x + const canUseNativeAlert = !!( + !browser.web0s + && !(browser.tizenVersion && browser.tizenVersion < 3) + && browser.tv + && window.alert + ); + + const options = typeof text === 'string' ? { title, text } : text; await appRouter.ready(); - if (useNativeAlert()) { + if (canUseNativeAlert) { alert((options.text || '').replaceAll('
', '\n')); - return Promise.resolve(); - } else { - const items = []; - items.push({ + return Promise.resolve(); + } + + options.buttons = [ + { name: globalize.translate('ButtonGotIt'), id: 'ok', type: 'submit' - }); + } + ]; - options.buttons = items; - return dialog.show(options); - } + return dialog.show(options); } diff --git a/src/components/apphost.js b/src/components/apphost.js index 2cb709e112..2360a8f233 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -16,10 +16,13 @@ function getBaseProfileOptions(item) { if (browser.edge) { disableHlsVideoAudioCodecs.push('mp3'); } - - disableHlsVideoAudioCodecs.push('ac3'); - disableHlsVideoAudioCodecs.push('eac3'); - disableHlsVideoAudioCodecs.push('opus'); + if (!browser.edgeChromium) { + disableHlsVideoAudioCodecs.push('ac3'); + disableHlsVideoAudioCodecs.push('eac3'); + } + if (!(browser.chrome || browser.edgeChromium || browser.firefox)) { + disableHlsVideoAudioCodecs.push('opus'); + } } return { diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index f46885c79d..5db0428cda 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -43,8 +43,8 @@ export function enableHlsJsPlayer(runTimeTicks, mediaType) { } if (canPlayNativeHls()) { - // Having trouble with chrome's native support and transcoded music - if (browser.android && mediaType === 'Audio') { + // Android Webview's native HLS has performance and compatiblity issues + if (browser.android && (mediaType === 'Audio' || mediaType === 'Video')) { return true; } diff --git a/src/controllers/dashboard/encodingsettings.html b/src/controllers/dashboard/encodingsettings.html index 59aae89d1e..278d95dba9 100644 --- a/src/controllers/dashboard/encodingsettings.html +++ b/src/controllers/dashboard/encodingsettings.html @@ -124,6 +124,12 @@ ${AllowHevcEncoding} +
+ +
diff --git a/src/controllers/dashboard/encodingsettings.js b/src/controllers/dashboard/encodingsettings.js index a769a65d00..9c268c0866 100644 --- a/src/controllers/dashboard/encodingsettings.js +++ b/src/controllers/dashboard/encodingsettings.js @@ -18,6 +18,7 @@ function loadPage(page, config, systemInfo) { page.querySelector('#chkIntelLpHevcHwEncoder').checked = config.EnableIntelLowPowerHevcHwEncoder; page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding; page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding; + page.querySelector('#chkAllowAv1Encoding').checked = config.AllowAv1Encoding; $('#selectVideoDecoder', page).val(config.HardwareAccelerationType); $('#selectThreadCount', page).val(config.EncodingThreadCount); page.querySelector('#chkEnableAudioVbr').checked = config.EnableAudioVbr; @@ -123,6 +124,7 @@ function onSubmit() { config.EnableIntelLowPowerHevcHwEncoder = form.querySelector('#chkIntelLpHevcHwEncoder').checked; config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked; config.AllowHevcEncoding = form.querySelector('#chkAllowHevcEncoding').checked; + config.AllowAv1Encoding = form.querySelector('#chkAllowAv1Encoding').checked; ApiClient.updateNamedConfiguration('encoding', config).then(function () { updateEncoder(form); }, function () { diff --git a/src/plugins/bookPlayer/template.html b/src/plugins/bookPlayer/template.html index 55fd02c8a1..255b8283a2 100644 --- a/src/plugins/bookPlayer/template.html +++ b/src/plugins/bookPlayer/template.html @@ -2,12 +2,6 @@ - diff --git a/src/scripts/autocast.js b/src/scripts/autocast.js index 9ed7de5df7..2633587ba5 100644 --- a/src/scripts/autocast.js +++ b/src/scripts/autocast.js @@ -26,7 +26,7 @@ export function isEnabled() { const playerId = localStorage.getItem('autocastPlayerId'); const currentPlayerInfo = playbackManager.getPlayerInfo(); - return (currentPlayerInfo && playerId && currentPlayerInfo.id === playerId); + return playerId && currentPlayerInfo?.id === playerId; } function onOpen() { diff --git a/src/scripts/browser.js b/src/scripts/browser.js index 47b0635d52..15898f03b1 100644 --- a/src/scripts/browser.js +++ b/src/scripts/browser.js @@ -148,14 +148,11 @@ let _supportsCssAnimation; let _supportsCssAnimationWithPrefix; function supportsCssAnimation(allowPrefix) { // TODO: Assess if this is still needed, as all of our targets should natively support CSS animations. - if (allowPrefix) { - if (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false) { - return _supportsCssAnimationWithPrefix; - } - } else { - if (_supportsCssAnimation === true || _supportsCssAnimation === false) { - return _supportsCssAnimation; - } + if (allowPrefix && (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false)) { + return _supportsCssAnimationWithPrefix; + } + if (_supportsCssAnimation === true || _supportsCssAnimation === false) { + return _supportsCssAnimation; } let animation = false; @@ -187,13 +184,13 @@ function supportsCssAnimation(allowPrefix) { const uaMatch = function (ua) { ua = ua.toLowerCase(); - const match = /(edg)[ /]([\w.]+)/.exec(ua) + const match = /(chrome)[ /]([\w.]+)/.exec(ua) + || /(edg)[ /]([\w.]+)/.exec(ua) || /(edga)[ /]([\w.]+)/.exec(ua) || /(edgios)[ /]([\w.]+)/.exec(ua) || /(edge)[ /]([\w.]+)/.exec(ua) || /(opera)[ /]([\w.]+)/.exec(ua) || /(opr)[ /]([\w.]+)/.exec(ua) - || /(chrome)[ /]([\w.]+)/.exec(ua) || /(safari)[ /]([\w.]+)/.exec(ua) || /(firefox)[ /]([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index 98be70a9b1..ff8bcfcca2 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -23,6 +23,17 @@ function canPlayHevc(videoTestElement, options) { || 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; function supportsTextTracks() { if (browser.tizen) { @@ -56,6 +67,14 @@ function canPlayNativeHls() { || 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() { // text tracks don’t work with this in firefox return window.MediaSource != null; /* eslint-disable-line compat/compat */ @@ -157,14 +176,6 @@ function testCanPlayMkv(videoTestElement) { 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() { 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. if (canPlayAc3VideoAudio) { videoAudioCodecs.push('ac3'); + if (browser.edgeChromium) { + hlsInFmp4VideoAudioCodecs.push('ac3'); + } + if (canPlayEac3VideoAudio) { videoAudioCodecs.push('eac3'); + if (browser.edgeChromium) { + hlsInFmp4VideoAudioCodecs.push('eac3'); + } } if (canPlayAc3VideoAudioInHls) { @@ -492,6 +510,9 @@ export default function (options) { if (browser.tizen) { hlsInTsVideoAudioCodecs.push('opus'); } + if (!browser.safari) { + hlsInFmp4VideoAudioCodecs.push('opus'); + } } if (canPlayAudioFormat('flac')) { @@ -521,17 +542,22 @@ export default function (options) { const hlsInTsVideoCodecs = []; 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'); } if (canPlayH264(videoTestElement)) { mp4VideoCodecs.push('h264'); hlsInTsVideoCodecs.push('h264'); - - if (browser.safari || browser.tizen || browser.web0s) { - hlsInFmp4VideoCodecs.push('h264'); - } + hlsInFmp4VideoCodecs.push('h264'); } if (canPlayHevc(videoTestElement, options)) { @@ -566,7 +592,7 @@ export default function (options) { webmVideoCodecs.push('vp9'); } - if (testCanPlayAv1(videoTestElement)) { + if (canPlayAv1(videoTestElement)) { mp4VideoCodecs.push('av1'); webmVideoCodecs.push('av1'); } @@ -687,7 +713,11 @@ export default function (options) { }); 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({ Container: 'mp4', Type: 'Video', @@ -817,6 +847,33 @@ export default function (options) { 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'; let hevcVideoRangeTypes = 'SDR'; let vp9VideoRangeTypes = 'SDR'; @@ -830,12 +887,15 @@ export default function (options) { } if (browser.tizen || browser.web0s) { - hevcVideoRangeTypes += '|HDR10|HLG|DOVI'; + hevcVideoRangeTypes += '|HDR10|HLG'; vp9VideoRangeTypes += '|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'; av1VideoRangeTypes += '|HDR10|HLG'; } @@ -904,11 +964,29 @@ export default function (options) { ]; const av1CodecProfileConditions = [ + { + Condition: 'NotEquals', + Property: 'IsAnamorphic', + Value: 'true', + IsRequired: false + }, + { + Condition: 'EqualsAny', + Property: 'VideoProfile', + Value: av1Profiles, + IsRequired: false + }, { Condition: 'EqualsAny', Property: 'VideoRangeType', Value: av1VideoRangeTypes, IsRequired: false + }, + { + Condition: 'LessThanEqual', + Property: 'VideoLevel', + Value: maxAv1Level.toString(), + IsRequired: false } ]; @@ -942,6 +1020,13 @@ export default function (options) { Value: maxVideoWidth.toString(), IsRequired: false }); + + av1CodecProfileConditions.push({ + Condition: 'LessThanEqual', + Property: 'Width', + Value: maxVideoWidth.toString(), + IsRequired: false + }); } const globalMaxVideoBitrate = (getGlobalMaxVideoBitrate() || '').toString(); @@ -950,6 +1035,8 @@ export default function (options) { const hevcMaxVideoBitrate = globalMaxVideoBitrate; + const av1MaxVideoBitrate = globalMaxVideoBitrate; + if (h264MaxVideoBitrate) { h264CodecProfileConditions.push({ 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 if (browser.iOS && browser.iOSVersion < 13) { const codecProfile = { diff --git a/src/scripts/datetime.js b/src/scripts/datetime.js index 3903b58638..f1243a5076 100644 --- a/src/scripts/datetime.js +++ b/src/scripts/datetime.js @@ -230,7 +230,6 @@ export function getDisplayTime(date) { const timeLower = time.toLowerCase(); if (timeLower.indexOf('am') !== -1 || timeLower.indexOf('pm') !== -1) { - time = timeLower; let hour = date.getHours() % 12; const suffix = date.getHours() > 11 ? 'pm' : 'am'; if (!hour) { diff --git a/src/strings/cs.json b/src/strings/cs.json index 359bf7d812..4cd89478cb 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -1763,5 +1763,6 @@ "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í.", "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" } diff --git a/src/strings/da.json b/src/strings/da.json index b6a39c19e5..5bed42a5c8 100644 --- a/src/strings/da.json +++ b/src/strings/da.json @@ -1700,5 +1700,7 @@ "EnableCardLayout": "Vis visuel CardBox", "ResolutionMatchSource": "Match kilde", "SubtitleCyan": "Cyan", - "SubtitleMagenta": "Magenta" + "SubtitleMagenta": "Magenta", + "AllowCollectionManagement": "Tillad denne bruger at administrere samlinger", + "AllowSegmentDeletion": "Slet segmenter" } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 7a1fbe832b..bc6dc0da08 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1715,5 +1715,6 @@ "Unreleased": "Not yet released", "LabelTonemappingMode": "Tone mapping 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" } diff --git a/src/strings/fi.json b/src/strings/fi.json index 3d2b0a7e18..4c69d67800 100644 --- a/src/strings/fi.json +++ b/src/strings/fi.json @@ -1232,7 +1232,7 @@ "EnableTonemapping": "Käytä sävykartoitusta", "EnableBlurHashHelp": "Kuvat, joita ladataan vielä, näytetään yksilöllisellä paikkamerkillä.", "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.", "LabelKodiMetadataEnablePathSubstitutionHelp": "Mahdollistaa kuvien tiedostosijaintien korvauksen palvelimen korvausasetuksien perusteella.", "ThumbCard": "Pienoiskortti", @@ -1761,5 +1761,6 @@ "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ä.", "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" } diff --git a/src/strings/nl.json b/src/strings/nl.json index a69adfcf0b..ba9031fc88 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -169,7 +169,7 @@ "EnableThemeSongsHelp": "Speel titelmuziek af tijdens het bladeren door de bibliotheek.", "EnableThemeVideosHelp": "Speel titelfilms af op de achtergrond tijdens het bladeren door de bibliotheek.", "Ended": "Gestopt", - "EndsAtValue": "Eindigt om {0}", + "EndsAtValue": "Afgelopen om {0}", "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.", "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.", "LabelSegmentKeepSeconds": "Bewaartijd segmenten", "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" } diff --git a/src/strings/pl.json b/src/strings/pl.json index 34ffe775f5..37fb936015 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -1763,5 +1763,6 @@ "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.", "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" } diff --git a/src/strings/uk.json b/src/strings/uk.json index d74f61e673..c0bc6c9087 100644 --- a/src/strings/uk.json +++ b/src/strings/uk.json @@ -1760,5 +1760,6 @@ "LabelSegmentKeepSecondsHelp": "Час у секундах, протягом якого сегменти мають зберігатися перед перезаписом. Має бути більшим за \"Обмежити після\". Працює тільки якщо увімкнено видалення сегментів.", "LabelSegmentKeepSeconds": "Час збереження сегментів", "LabelBackdropScreensaverIntervalHelp": "Час у секундах між різними фонами при використанні фонової заставки.", - "LabelBackdropScreensaverInterval": "Інтервал між фоновими заставками" + "LabelBackdropScreensaverInterval": "Інтервал між фоновими заставками", + "AllowAv1Encoding": "Дозволити кодування у форматі AV1" }