From 54db12359c34b20b305ad081bf188151c9a142cf Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Thu, 12 Nov 2020 20:03:38 +0800 Subject: [PATCH 1/5] add initial support for fMP4-HLS --- src/components/apphost.js | 1 - .../playbackSettings/playbackSettings.js | 6 +- .../playbackSettings.template.html | 18 ++ .../dashboard/encodingsettings.html | 9 + src/controllers/dashboard/encodingsettings.js | 2 + src/scripts/browserDeviceProfile.js | 217 ++++++++++++++---- src/scripts/settings/userSettings.js | 29 +++ src/strings/en-us.json | 9 +- src/strings/zh-cn.json | 9 +- 9 files changed, 255 insertions(+), 45 deletions(-) diff --git a/src/components/apphost.js b/src/components/apphost.js index df2f7c2d2c..1afe9f543f 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -33,7 +33,6 @@ function getDeviceProfile(item, options = {}) { profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder); } else { const builderOpts = getBaseProfileOptions(item); - builderOpts.enableSsaRender = (item && !options.isRetry && appSettings.get('subtitleburnin') !== 'allcomplexformats'); profile = profileBuilder(builderOpts); } diff --git a/src/components/playbackSettings/playbackSettings.js b/src/components/playbackSettings/playbackSettings.js index 782e3d38e1..44a9b607d6 100644 --- a/src/components/playbackSettings/playbackSettings.js +++ b/src/components/playbackSettings/playbackSettings.js @@ -145,6 +145,8 @@ import 'emby-checkbox'; showHideQualityFields(context, user, apiClient); + context.querySelector('#selectAllowedAudioChannels').value = userSettings.allowedAudioChannels(); + apiClient.getCultures().then(allCultures => { populateLanguages(context.querySelector('#selectAudioLanguage'), allCultures); @@ -187,6 +189,7 @@ import 'emby-checkbox'; } context.querySelector('.chkPlayDefaultAudioTrack').checked = user.Configuration.PlayDefaultAudioTrack || false; + context.querySelector('.chkPreferFmp4HlsContainer').checked = userSettings.preferFmp4HlsContainer(); context.querySelector('.chkEnableCinemaMode').checked = userSettings.enableCinemaMode(); context.querySelector('.chkEnableNextVideoOverlay').checked = userSettings.enableNextVideoInfoOverlay(); context.querySelector('.chkExternalVideoPlayer').checked = appSettings.enableSystemExternalPlayers(); @@ -222,10 +225,11 @@ import 'emby-checkbox'; setMaxBitrateFromField(context.querySelector('.selectVideoInternetQuality'), false, 'Video'); setMaxBitrateFromField(context.querySelector('.selectMusicInternetQuality'), false, 'Audio'); + userSettingsInstance.allowedAudioChannels(context.querySelector('#selectAllowedAudioChannels').value); user.Configuration.AudioLanguagePreference = context.querySelector('#selectAudioLanguage').value; user.Configuration.PlayDefaultAudioTrack = context.querySelector('.chkPlayDefaultAudioTrack').checked; user.Configuration.EnableNextEpisodeAutoPlay = context.querySelector('.chkEpisodeAutoPlay').checked; - + userSettingsInstance.preferFmp4HlsContainer(context.querySelector('.chkPreferFmp4HlsContainer').checked); userSettingsInstance.enableCinemaMode(context.querySelector('.chkEnableCinemaMode').checked); userSettingsInstance.enableNextVideoInfoOverlay(context.querySelector('.chkEnableNextVideoOverlay').checked); diff --git a/src/components/playbackSettings/playbackSettings.template.html b/src/components/playbackSettings/playbackSettings.template.html index d10b069bb2..ae6429ed95 100644 --- a/src/components/playbackSettings/playbackSettings.template.html +++ b/src/components/playbackSettings/playbackSettings.template.html @@ -4,6 +4,16 @@ ${HeaderAudioSettings} +
+ +
+
@@ -49,6 +59,14 @@ ${TabAdvanced} +
+ +
${PreferFmp4HlsContainerHelp}
+
+
+ +
+
+ +
+
diff --git a/src/controllers/dashboard/encodingsettings.js b/src/controllers/dashboard/encodingsettings.js index 6a54e8105d..48b31e4dc1 100644 --- a/src/controllers/dashboard/encodingsettings.js +++ b/src/controllers/dashboard/encodingsettings.js @@ -13,6 +13,7 @@ import libraryMenu from 'libraryMenu'; page.querySelector('#chkDecodingColorDepth10Hevc').checked = config.EnableDecodingColorDepth10Hevc; page.querySelector('#chkDecodingColorDepth10Vp9').checked = config.EnableDecodingColorDepth10Vp9; page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding; + page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding; $('#selectVideoDecoder', page).val(config.HardwareAccelerationType); $('#selectThreadCount', page).val(config.EncodingThreadCount); $('#txtDownMixAudioBoost', page).val(config.DownMixAudioBoost); @@ -98,6 +99,7 @@ import libraryMenu from 'libraryMenu'; config.EnableDecodingColorDepth10Hevc = form.querySelector('#chkDecodingColorDepth10Hevc').checked; config.EnableDecodingColorDepth10Vp9 = form.querySelector('#chkDecodingColorDepth10Vp9').checked; config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked; + config.AllowHevcEncoding = form.querySelector('#chkAllowHevcEncoding').checked; ApiClient.updateNamedConfiguration('encoding', config).then(function () { updateEncoder(form); }, function () { diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index 3ce60cfe7a..5b3ee64ac4 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -1,4 +1,4 @@ -define(['browser'], function (browser) { +define(['browser', 'userSettings', 'appSettings'], function (browser, userSettings, appSettings) { 'use strict'; browser = browser.default || browser; @@ -7,7 +7,7 @@ define(['browser'], function (browser) { return !!(videoTestElement.canPlayType && videoTestElement.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, '')); } - function canPlayH265(videoTestElement, options) { + function canPlayHevc(videoTestElement, options) { if (browser.tizen || browser.xboxOne || browser.web0s || options.supportsHevc) { return true; } @@ -16,6 +16,7 @@ define(['browser'], function (browser) { return false; } + // hevc main level 4.0 return !!videoTestElement.canPlayType && (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '') || videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '') || @@ -207,8 +208,7 @@ define(['browser'], function (browser) { // Explicitly add supported codecs to make other codecs be transcoded if (browser.tizenVersion >= 4) { videoCodecs.push('h264'); - if (canPlayH265(videoTestElement, options)) { - videoCodecs.push('h265'); + if (canPlayHevc(videoTestElement, options)) { videoCodecs.push('hevc'); } } @@ -248,8 +248,8 @@ define(['browser'], function (browser) { case 'ts': supported = testCanPlayTs(); videoCodecs.push('h264'); - if (canPlayH265(videoTestElement, options)) { - videoCodecs.push('h265'); + // safari doesn't support hevc in TS-HLS + if ((browser.tizen || browser.web0s) && canPlayHevc(videoTestElement, options)) { videoCodecs.push('hevc'); } if (supportsVc1(videoTestElement)) { @@ -297,7 +297,9 @@ define(['browser'], function (browser) { return function (options) { options = options || {}; - const physicalAudioChannels = options.audioChannels || (browser.tv || browser.ps4 || browser.xboxOne ? 6 : 2); + const isSurroundSoundSupportedBrowser = browser.safari || browser.chrome || browser.edgeChromium || browser.firefox; + const allowedAudioChannels = parseInt(userSettings.allowedAudioChannels() || '-1'); + const physicalAudioChannels = (allowedAudioChannels > 0 ? allowedAudioChannels : null) || options.audioChannels || (isSurroundSoundSupportedBrowser || browser.tv || browser.ps4 || browser.xboxOne ? 6 : 2); const bitrateSetting = getMaxBitrate(); @@ -313,12 +315,13 @@ define(['browser'], function (browser) { profile.MaxStreamingBitrate = bitrateSetting; profile.MaxStaticBitrate = 100000000; - profile.MusicStreamingTranscodingBitrate = Math.min(bitrateSetting, 192000); + profile.MusicStreamingTranscodingBitrate = Math.min(bitrateSetting, 384000); profile.DirectPlayProfiles = []; let videoAudioCodecs = []; - let hlsVideoAudioCodecs = []; + let hlsInTsVideoAudioCodecs = []; + let hlsInFmp4VideoAudioCodecs = []; const supportsMp3VideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"').replace(/no/, '') || videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"').replace(/no/, '') @@ -353,16 +356,19 @@ define(['browser'], function (browser) { // Transcoding codec is the first in hlsVideoAudioCodecs // Put ac3/eac3 first only when the audio channels > 2 and need transcoding if (canPlayAc3VideoAudioInHls && physicalAudioChannels > 2) { - hlsVideoAudioCodecs.push('ac3'); + hlsInTsVideoAudioCodecs.push('ac3'); + hlsInFmp4VideoAudioCodecs.push('ac3'); if (canPlayEac3VideoAudio) { - hlsVideoAudioCodecs.push('eac3'); + hlsInTsVideoAudioCodecs.push('eac3'); + hlsInFmp4VideoAudioCodecs.push('eac3'); } } } if (canPlayAacVideoAudio) { videoAudioCodecs.push('aac'); - hlsVideoAudioCodecs.push('aac'); + hlsInTsVideoAudioCodecs.push('aac'); + hlsInFmp4VideoAudioCodecs.push('aac'); } if (supportsMp3VideoAudio) { @@ -370,16 +376,31 @@ define(['browser'], function (browser) { // PS4 fails to load HLS with mp3 audio if (!browser.ps4) { - hlsVideoAudioCodecs.push('mp3'); + hlsInTsVideoAudioCodecs.push('mp3'); } + + hlsInFmp4VideoAudioCodecs.push('mp3'); } // For ac3/eac3 directstream if (canPlayAc3VideoAudio) { - if (canPlayAc3VideoAudioInHls && hlsVideoAudioCodecs.indexOf('ac3') === -1) { - hlsVideoAudioCodecs.push('ac3'); - if (canPlayEac3VideoAudio && hlsVideoAudioCodecs.indexOf('eac3') === -1) { - hlsVideoAudioCodecs.push('eac3'); + if (canPlayAc3VideoAudioInHls) { + if (hlsInTsVideoAudioCodecs.indexOf('ac3') === -1) { + hlsInTsVideoAudioCodecs.push('ac3'); + } + + if (hlsInFmp4VideoAudioCodecs.indexOf('ac3') === -1) { + hlsInFmp4VideoAudioCodecs.push('ac3'); + } + + if (canPlayEac3VideoAudio) { + if (hlsInTsVideoAudioCodecs.indexOf('eac3') === -1) { + hlsInTsVideoAudioCodecs.push('eac3'); + } + + if (hlsInFmp4VideoAudioCodecs.indexOf('eac3') === -1) { + hlsInFmp4VideoAudioCodecs.push('eac3'); + } } } } @@ -415,38 +436,54 @@ define(['browser'], function (browser) { if (canPlayAudioFormat('opus')) { videoAudioCodecs.push('opus'); - hlsVideoAudioCodecs.push('opus'); + hlsInTsVideoAudioCodecs.push('opus'); webmAudioCodecs.push('opus'); } if (canPlayAudioFormat('flac')) { videoAudioCodecs.push('flac'); + hlsInFmp4VideoAudioCodecs.push('flac'); + } + + if (canPlayAudioFormat('alac')) { + videoAudioCodecs.push('alac'); + hlsInFmp4VideoAudioCodecs.push('alac'); } videoAudioCodecs = videoAudioCodecs.filter(function (c) { return (options.disableVideoAudioCodecs || []).indexOf(c) === -1; }); - hlsVideoAudioCodecs = hlsVideoAudioCodecs.filter(function (c) { + hlsInTsVideoAudioCodecs = hlsInTsVideoAudioCodecs.filter(function (c) { + return (options.disableHlsVideoAudioCodecs || []).indexOf(c) === -1; + }); + + hlsInFmp4VideoAudioCodecs = hlsInFmp4VideoAudioCodecs.filter(function (c) { return (options.disableHlsVideoAudioCodecs || []).indexOf(c) === -1; }); const mp4VideoCodecs = []; const webmVideoCodecs = []; - const hlsVideoCodecs = []; + const hlsInTsVideoCodecs = []; + const hlsInFmp4VideoCodecs = []; + + if (browser.safari || browser.tizen || browser.web0s && canPlayHevc(videoTestElement, options)) { + hlsInFmp4VideoCodecs.push('hevc'); + } if (canPlayH264(videoTestElement)) { mp4VideoCodecs.push('h264'); - hlsVideoCodecs.push('h264'); + hlsInTsVideoCodecs.push('h264'); + + if (browser.safari || browser.tizen || browser.web0s) { + hlsInFmp4VideoCodecs.push('h264'); + } } - if (canPlayH265(videoTestElement, options)) { - mp4VideoCodecs.push('h265'); - mp4VideoCodecs.push('hevc'); - - if (browser.tizen || browser.web0s) { - hlsVideoCodecs.push('h265'); - hlsVideoCodecs.push('hevc'); + if (canPlayHevc(videoTestElement, options)) { + // safari is lying on HDR and 60fps videos, use fMP4 instead + if (!browser.safari) { + mp4VideoCodecs.push('hevc'); } } @@ -606,18 +643,34 @@ define(['browser'], function (browser) { }); } - if (canPlayHls() && hlsVideoAudioCodecs.length && options.enableHls !== false) { - profile.TranscodingProfiles.push({ - Container: 'ts', - Type: 'Video', - AudioCodec: hlsVideoAudioCodecs.join(','), - VideoCodec: hlsVideoCodecs.join(','), - Context: 'Streaming', - Protocol: 'hls', - MaxAudioChannels: physicalAudioChannels.toString(), - MinSegments: browser.iOS || browser.osx ? '2' : '1', - BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames - }); + if (canPlayHls() && options.enableHls !== false) { + if (hlsInFmp4VideoCodecs.length && hlsInFmp4VideoAudioCodecs.length && userSettings.preferFmp4HlsContainer() && (browser.safari || browser.tizen || browser.web0s)) { + profile.TranscodingProfiles.push({ + Container: 'mp4', + Type: 'Video', + AudioCodec: hlsInFmp4VideoAudioCodecs.join(','), + VideoCodec: hlsInFmp4VideoCodecs.join(','), + Context: 'Streaming', + Protocol: 'hls', + MaxAudioChannels: physicalAudioChannels.toString(), + MinSegments: browser.iOS || browser.osx ? '2' : '1', + BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames + }); + } + + if (hlsInTsVideoCodecs.length && hlsInTsVideoAudioCodecs.length) { + profile.TranscodingProfiles.push({ + Container: 'ts', + Type: 'Video', + AudioCodec: hlsInTsVideoAudioCodecs.join(','), + VideoCodec: hlsInTsVideoCodecs.join(','), + Context: 'Streaming', + Protocol: 'hls', + MaxAudioChannels: physicalAudioChannels.toString(), + MinSegments: browser.iOS || browser.osx ? '2' : '1', + BreakOnNonKeyFrames: hlsBreakOnNonKeyFrames + }); + } } if (canPlayVp8) { @@ -713,6 +766,36 @@ define(['browser'], function (browser) { } } + let maxHevcLevel = 120; + let hevcProfiles = 'main'; + + // hevc main level 4.1 + if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.4.L123"').replace(/no/, '') || + videoTestElement.canPlayType('video/mp4; codecs="hev1.1.4.L123"').replace(/no/, '')) { + maxHevcLevel = 123; + } + + // hevc main10 level 4.1 + if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L123"').replace(/no/, '') || + videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L123"').replace(/no/, '')) { + maxHevcLevel = 123; + hevcProfiles = 'main|main 10'; + } + + // hevc main10 level 5.1 + if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L153"').replace(/no/, '') || + videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L153"').replace(/no/, '')) { + maxHevcLevel = 153; + hevcProfiles = 'main|main 10'; + } + + // hevc main10 level 6.1 + if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '') || + videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '')) { + maxHevcLevel = 183; + hevcProfiles = 'main|main 10'; + } + const h264CodecProfileConditions = [ { Condition: 'NotEquals', @@ -734,6 +817,27 @@ define(['browser'], function (browser) { } ]; + const hevcCodecProfileConditions = [ + { + Condition: 'NotEquals', + Property: 'IsAnamorphic', + Value: 'true', + IsRequired: false + }, + { + Condition: 'EqualsAny', + Property: 'VideoProfile', + Value: hevcProfiles, + IsRequired: false + }, + { + Condition: 'LessThanEqual', + Property: 'VideoLevel', + Value: maxHevcLevel.toString(), + IsRequired: false + } + ]; + if (!browser.edgeUwp && !browser.tizen && !browser.web0s) { h264CodecProfileConditions.push({ Condition: 'NotEquals', @@ -741,6 +845,13 @@ define(['browser'], function (browser) { Value: 'true', IsRequired: false }); + + hevcCodecProfileConditions.push({ + Condition: 'NotEquals', + Property: 'IsInterlaced', + Value: 'true', + IsRequired: false + }); } if (maxVideoWidth) { @@ -750,12 +861,21 @@ define(['browser'], function (browser) { Value: maxVideoWidth.toString(), IsRequired: false }); + + hevcCodecProfileConditions.push({ + Condition: 'LessThanEqual', + Property: 'Width', + Value: maxVideoWidth.toString(), + IsRequired: false + }); } const globalMaxVideoBitrate = (getGlobalMaxVideoBitrate() || '').toString(); const h264MaxVideoBitrate = globalMaxVideoBitrate; + const hevcMaxVideoBitrate = globalMaxVideoBitrate; + if (h264MaxVideoBitrate) { h264CodecProfileConditions.push({ Condition: 'LessThanEqual', @@ -765,6 +885,15 @@ define(['browser'], function (browser) { }); } + if (hevcMaxVideoBitrate) { + hevcCodecProfileConditions.push({ + Condition: 'LessThanEqual', + Property: 'VideoBitrate', + Value: hevcMaxVideoBitrate, + IsRequired: true + }); + } + // On iOS 12.x, for TS container max h264 level is 4.2 if (browser.iOS && browser.iOSVersion < 13) { const codecProfile = { @@ -792,6 +921,12 @@ define(['browser'], function (browser) { Conditions: h264CodecProfileConditions }); + profile.CodecProfiles.push({ + Type: 'Video', + Codec: 'hevc', + Conditions: hevcCodecProfileConditions + }); + const globalVideoConditions = []; if (globalMaxVideoBitrate) { @@ -827,7 +962,7 @@ define(['browser'], function (browser) { Method: 'External' }); } - if (options.enableSsaRender) { + if (options.enableSsaRender !== false && (!options.isRetry && appSettings.get('subtitleburnin') !== 'allcomplexformats')) { profile.SubtitleProfiles.push({ Format: 'ass', Method: 'External' diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 263d74ed37..4a27d7ad9a 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -114,6 +114,33 @@ export class UserSettings { }); } + /** + * Get or set 'Allowed Audio Channels'. + * @param {string|undefined} val - 'Allowed Audio Channels'. + * @return {string} 'Allowed Audio Channels'. + */ + allowedAudioChannels(val) { + if (val !== undefined) { + return this.set('allowedAudioChannels', val, false); + } + + return this.get('allowedAudioChannels', false) || '-1'; + } + + /** + * Get or set 'Perfer fMP4-HLS Container' state. + * @param {boolean|undefined} val - Flag to enable 'Perfer fMP4-HLS Container' or undefined. + * @return {boolean} 'Prefer fMP4-HLS Container' state. + */ + preferFmp4HlsContainer(val) { + if (val !== undefined) { + return this.set('preferFmp4HlsContainer', val.toString(), false); + } + + val = this.get('preferFmp4HlsContainer', false); + return val === 'true'; + } + /** * Get or set 'Cinema Mode' state. * @param {boolean|undefined} val - Flag to enable 'Cinema Mode' or undefined. @@ -457,6 +484,8 @@ export const importFrom = currentSettings.importFrom.bind(currentSettings); export const set = currentSettings.set.bind(currentSettings); export const get = currentSettings.get.bind(currentSettings); export const serverConfig = currentSettings.serverConfig.bind(currentSettings); +export const allowedAudioChannels = currentSettings.allowedAudioChannels.bind(currentSettings); +export const preferFmp4HlsContainer = currentSettings.preferFmp4HlsContainer.bind(currentSettings); export const enableCinemaMode = currentSettings.enableCinemaMode.bind(currentSettings); export const enableNextVideoInfoOverlay = currentSettings.enableNextVideoInfoOverlay.bind(currentSettings); export const enableThemeSongs = currentSettings.enableThemeSongs.bind(currentSettings); diff --git a/src/strings/en-us.json b/src/strings/en-us.json index c2ad064922..23cead75bd 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1424,5 +1424,12 @@ "SubtitleVerticalPositionHelp": "Line number where text appears. Positive numbers indicate top down. Negative numbers indicate bottom up.", "Preview": "Preview", "LabelMaxMuxingQueueSize": "Max muxing queue size:", - "LabelMaxMuxingQueueSizeHelp": "Maximum number of packets that can be buffered while waiting for all streams to initialize. Try to increase it if you still encounter \"Too many packets buffered for output stream\" error in ffmpeg logs. The recommended value is 2048." + "LabelMaxMuxingQueueSizeHelp": "Maximum number of packets that can be buffered while waiting for all streams to initialize. Try to increase it if you still encounter \"Too many packets buffered for output stream\" error in ffmpeg logs. The recommended value is 2048.", + "PreferFmp4HlsContainer": "Prefer fMP4-HLS Media Container", + "PreferFmp4HlsContainerHelp": "Prefer to use fMP4 as the default container for HLS, making it possible to direct streaming HEVC content on supported devices.", + "AllowHevcEncoding": "Allow encoding in HEVC format", + "LabelAllowedAudioChannels": "Maximum Allowed Audio Channels", + "LabelSelectAudioChannels": "Channels", + "LabelSelectMono": "Mono", + "LabelSelectStereo": "Stereo" } diff --git a/src/strings/zh-cn.json b/src/strings/zh-cn.json index d6603c6eb9..af8d036da2 100644 --- a/src/strings/zh-cn.json +++ b/src/strings/zh-cn.json @@ -1425,5 +1425,12 @@ "OptionAllowContentDownload": "允许媒体下载", "HeaderDeleteDevices": "删除所有设备", "DeleteDevicesConfirmation": "您确定要删除所有设备吗?所有其他会话将被注销。用户下次登录时,设备会重新出现。", - "DeleteAll": "删除全部" + "DeleteAll": "删除全部", + "PreferFmp4HlsContainer": "优先使用 fMP4-HLS 媒体容器", + "PreferFmp4HlsContainerHelp": "优先使用 fMP4 作为 HLS 播放的默认容器,从而可以在支持的设备上直接串流 HEVC 格式的内容。", + "AllowHevcEncoding": "允许以 HEVC 格式编码", + "LabelAllowedAudioChannels": "允许的最大声道数量", + "LabelSelectAudioChannels": "声道", + "LabelSelectMono": "单声道", + "LabelSelectStereo": "立体声" } From aff83c93d28e8679af6beed83734408818e45d62 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Thu, 12 Nov 2020 20:35:56 +0800 Subject: [PATCH 2/5] minor changes --- src/scripts/browserDeviceProfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index 5b3ee64ac4..ea58e84aae 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -791,7 +791,7 @@ define(['browser', 'userSettings', 'appSettings'], function (browser, userSettin // hevc main10 level 6.1 if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '') || - videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '')) { + videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L183"').replace(/no/, '')) { maxHevcLevel = 183; hevcProfiles = 'main|main 10'; } From 9e9ecbd6771f78063f52df7ff12c20273df178b2 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Sat, 14 Nov 2020 03:32:25 +0800 Subject: [PATCH 3/5] expose h265 crf option --- .../dashboard/encodingsettings.html | 18 ++++++++++-------- src/controllers/dashboard/encodingsettings.js | 2 ++ src/strings/en-us.json | 5 +++-- src/strings/zh-cn.json | 5 +++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/controllers/dashboard/encodingsettings.html b/src/controllers/dashboard/encodingsettings.html index 4fdb1a0975..7be830780d 100644 --- a/src/controllers/dashboard/encodingsettings.html +++ b/src/controllers/dashboard/encodingsettings.html @@ -92,14 +92,14 @@
+ -
-
- -
+
+
+
@@ -211,11 +211,13 @@
${EncoderPresetHelp}
+
+ +
${H264CrfHelp}
-