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

Merge pull request #683 from dkanada/codec

Minor playback improvements and a few icon and string fixes
This commit is contained in:
dkanada 2020-01-17 13:24:30 +09:00 committed by GitHub
commit 4a5088f35e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 91 deletions

View file

@ -20,24 +20,21 @@ jobs:
steps: steps:
- task: NodeTool@0 - task: NodeTool@0
displayName: 'Install Node.js' displayName: 'Install Node'
inputs: inputs:
versionSpec: '10.x' versionSpec: '10.x'
- script: | - script: 'yarn install'
yarn install displayName: 'Install Dependencies'
displayName: 'Install dependencies'
- script: | - script: 'test -d dist'
test -d dist displayName: 'Check Build'
displayName: 'Check dist directory'
- script: | - script: 'yarn pack --filename jellyfin-web.tgz'
yarn pack --filename jellyfin-web.tgz displayName: 'Bundle Release'
displayName: 'Build package'
- task: PublishPipelineArtifact@1 - task: PublishPipelineArtifact@1
displayName: 'Publish package' displayName: 'Publish Release'
condition: succeeded() condition: succeeded()
inputs: inputs:
targetPath: '$(Build.SourcesDirectory)/jellyfin-web.tgz' targetPath: '$(Build.SourcesDirectory)/jellyfin-web.tgz'
@ -51,14 +48,12 @@ jobs:
steps: steps:
- task: NodeTool@0 - task: NodeTool@0
displayName: 'Install Node.js' displayName: 'Install Node'
inputs: inputs:
versionSpec: '10.x' versionSpec: '10.x'
- script: | - script: 'yarn install'
yarn install displayName: 'Install Dependencies'
displayName: 'Install dependencies'
- script: | - script: 'yarn run lint'
yarn run lint
displayName: 'Run ESLint' displayName: 'Run ESLint'

View file

@ -95,23 +95,19 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
} }
function getMediaStreamAudioTracks(mediaSource) { function getMediaStreamAudioTracks(mediaSource) {
return mediaSource.MediaStreams.filter(function (s) { return mediaSource.MediaStreams.filter(function (s) {
return s.Type === 'Audio'; return s.Type === 'Audio';
}); });
} }
function getMediaStreamTextTracks(mediaSource) { function getMediaStreamTextTracks(mediaSource) {
return mediaSource.MediaStreams.filter(function (s) { return mediaSource.MediaStreams.filter(function (s) {
return s.Type === 'Subtitle'; return s.Type === 'Subtitle';
}); });
} }
function zoomIn(elem) { function zoomIn(elem) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var duration = 240; var duration = 240;
elem.style.animation = 'htmlvideoplayer-zoomin ' + duration + 'ms ease-in normal'; elem.style.animation = 'htmlvideoplayer-zoomin ' + duration + 'ms ease-in normal';
dom.addEventListener(elem, dom.whichAnimationEvent(), resolve, { dom.addEventListener(elem, dom.whichAnimationEvent(), resolve, {
@ -1429,7 +1425,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (!appHost.supports('htmlvideoautoplay')) { if (!appHost.supports('htmlvideoautoplay')) {
html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" controls="controls" webkit-playsinline playsinline>'; html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" controls="controls" webkit-playsinline playsinline>';
} else { } else {
// Chrome 35 won't play with preload none // Chrome 35 won't play with preload none
html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" webkit-playsinline playsinline>'; html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" webkit-playsinline playsinline>';
} }
@ -1805,7 +1800,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}; };
HtmlVideoPlayer.prototype.getAspectRatio = function () { HtmlVideoPlayer.prototype.getAspectRatio = function () {
return this._currentAspectRatio; return this._currentAspectRatio || "auto";
}; };
HtmlVideoPlayer.prototype.getSupportedAspectRatios = function () { HtmlVideoPlayer.prototype.getSupportedAspectRatios = function () {

View file

@ -70,7 +70,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
commands.push({ commands.push({
name: globalize.translate("InstantMix"), name: globalize.translate("InstantMix"),
id: "instantmix", id: "instantmix",
icon: "shuffle" icon: "explore"
}); });
} }
} }
@ -178,7 +178,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
commands.push({ commands.push({
name: globalize.translate("EditImages"), name: globalize.translate("EditImages"),
id: "editimages", id: "editimages",
icon: "edit" icon: "image"
}); });
} }
} }

View file

@ -35,6 +35,8 @@
} }
.listItem-indexnumberleft { .listItem-indexnumberleft {
min-width: 2%;
text-align: center;
margin-right: 1em; margin-right: 1em;
} }

View file

@ -45,7 +45,7 @@
<button is="emby-button" type="button" class="button-flat btnInstantMix hide detailButton-mobile"> <button is="emby-button" type="button" class="button-flat btnInstantMix hide detailButton-mobile">
<div class="detailButton-mobile-content"> <div class="detailButton-mobile-content">
<i class="md-icon detailButton-mobile-icon">shuffle</i> <i class="md-icon detailButton-mobile-icon">explore</i>
<div class="detailButton-mobile-text">${HeaderInstantMix}</div> <div class="detailButton-mobile-text">${HeaderInstantMix}</div>
</div> </div>
</button> </button>

View file

@ -6,15 +6,12 @@ define(['browser'], function (browser) {
} }
function canPlayH265(videoTestElement, options) { function canPlayH265(videoTestElement, options) {
if (browser.tizen || browser.orsay || browser.xboxOne || browser.web0s || options.supportsHevc) { if (browser.tizen || browser.orsay || browser.xboxOne || browser.web0s || options.supportsHevc) {
return true; return true;
} }
var userAgent = navigator.userAgent.toLowerCase(); var userAgent = navigator.userAgent.toLowerCase();
if (browser.chromecast) { if (browser.chromecast) {
var isChromecastUltra = userAgent.indexOf('aarch64') !== -1; var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
if (isChromecastUltra) { if (isChromecastUltra) {
return true; return true;
@ -31,7 +28,6 @@ define(['browser'], function (browser) {
var _supportsTextTracks; var _supportsTextTracks;
function supportsTextTracks() { function supportsTextTracks() {
if (browser.tizen || browser.orsay) { if (browser.tizen || browser.orsay) {
return true; return true;
} }
@ -46,15 +42,14 @@ define(['browser'], function (browser) {
var _canPlayHls; var _canPlayHls;
function canPlayHls(src) { function canPlayHls(src) {
if (_canPlayHls == null) { if (_canPlayHls == null) {
_canPlayHls = canPlayNativeHls() || canPlayHlsWithMSE(); _canPlayHls = canPlayNativeHls() || canPlayHlsWithMSE();
} }
return _canPlayHls; return _canPlayHls;
} }
function canPlayNativeHls() { function canPlayNativeHls() {
if (browser.tizen || browser.orsay) { if (browser.tizen || browser.orsay) {
return true; return true;
} }
@ -77,8 +72,27 @@ define(['browser'], function (browser) {
return false; return false;
} }
function canPlayAudioFormat(format) { function supportsAc3(videoTestElement) {
if (browser.edgeUwp || browser.tizen || browser.orsay || browser.web0s) {
return true;
}
if (browser.osx || browser.iOS) {
return false;
}
return videoTestElement.canPlayType('audio/mp4; codecs="ac-3"').replace(/no/, '');
}
function supportsEac3(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
return true;
}
return videoTestElement.canPlayType('audio/mp4; codecs="ec-3"').replace(/no/, '');
}
function canPlayAudioFormat(format) {
var typeString; var typeString;
if (format === 'flac') { if (format === 'flac') {
@ -97,14 +111,12 @@ define(['browser'], function (browser) {
} }
} else if (format === 'opus') { } else if (format === 'opus') {
typeString = 'audio/ogg; codecs="opus"'; typeString = 'audio/ogg; codecs="opus"';
if (document.createElement('audio').canPlayType(typeString).replace(/no/, '')) { if (document.createElement('audio').canPlayType(typeString).replace(/no/, '')) {
return true; return true;
} }
return false; return false;
} else if (format === 'mp2') { } else if (format === 'mp2') {
// For now // For now
return false; return false;
} }
@ -113,14 +125,6 @@ define(['browser'], function (browser) {
typeString = 'audio/webm'; typeString = 'audio/webm';
} else if (format === 'mp2') { } else if (format === 'mp2') {
typeString = 'audio/mpeg'; typeString = 'audio/mpeg';
} else if (format === 'ogg' || format === 'oga') {
// chrome says probably, but seeing failures
if (browser.chrome) {
return false;
}
typeString = 'audio/' + format;
} else { } else {
typeString = 'audio/' + format; typeString = 'audio/' + format;
} }
@ -133,7 +137,6 @@ define(['browser'], function (browser) {
} }
function testCanPlayMkv(videoTestElement) { function testCanPlayMkv(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) { if (browser.tizen || browser.orsay || browser.web0s) {
return true; return true;
} }
@ -147,7 +150,6 @@ define(['browser'], function (browser) {
// Unfortunately there's no real way to detect mkv support // Unfortunately there's no real way to detect mkv support
if (browser.chrome) { if (browser.chrome) {
// Not supported on opera tv // Not supported on opera tv
if (browser.operaTv) { if (browser.operaTv) {
return false; return false;
@ -162,7 +164,6 @@ define(['browser'], function (browser) {
} }
if (browser.edgeUwp) { if (browser.edgeUwp) {
return true; return true;
} }
@ -174,17 +175,15 @@ define(['browser'], function (browser) {
} }
function supportsMpeg2Video() { function supportsMpeg2Video() {
return browser.orsay || browser.tizen || browser.edgeUwp || browser.web0s; return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
} }
function supportsVc1() { function supportsVc1() {
return browser.orsay || browser.tizen || browser.edgeUwp || browser.web0s; return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
} }
function getFlvMseDirectPlayProfile() { function getFlvMseDirectPlayProfile() {
var videoAudioCodecs = ['aac']; var videoAudioCodecs = ['aac'];
if (!browser.edge && !browser.msie) { if (!browser.edge && !browser.msie) {
videoAudioCodecs.push('mp3'); videoAudioCodecs.push('mp3');
} }
@ -198,13 +197,11 @@ define(['browser'], function (browser) {
} }
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options) { function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options) {
var supported = false; var supported = false;
var profileContainer = container; var profileContainer = container;
var videoCodecs = []; var videoCodecs = [];
switch (container) { switch (container) {
case 'asf': case 'asf':
supported = browser.tizen || browser.orsay || browser.edgeUwp; supported = browser.tizen || browser.orsay || browser.edgeUwp;
videoAudioCodecs = []; videoAudioCodecs = [];
@ -279,16 +276,12 @@ define(['browser'], function (browser) {
} }
function getMaxBitrate() { function getMaxBitrate() {
return 120000000; return 120000000;
} }
function getGlobalMaxVideoBitrate() { function getGlobalMaxVideoBitrate() {
var userAgent = navigator.userAgent.toLowerCase(); var userAgent = navigator.userAgent.toLowerCase();
if (browser.chromecast) { if (browser.chromecast) {
var isChromecastUltra = userAgent.indexOf('aarch64') !== -1; var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
if (isChromecastUltra) { if (isChromecastUltra) {
return null; return null;
@ -319,27 +312,9 @@ define(['browser'], function (browser) {
(browser.tizen && isTizenFhd ? 20000000 : null))); (browser.tizen && isTizenFhd ? 20000000 : null)));
} }
function supportsAc3(videoTestElement) {
if (browser.edgeUwp || browser.tizen || browser.orsay || browser.web0s) {
return true;
}
return (videoTestElement.canPlayType('audio/mp4; codecs="ac-3"').replace(/no/, '') && !browser.osx && !browser.iOS);
}
function supportsEac3(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
return true;
}
return videoTestElement.canPlayType('audio/mp4; codecs="ec-3"').replace(/no/, '');
}
return function (options) { return function (options) {
options = options || {}; options = options || {};
var physicalAudioChannels = options.audioChannels || (browser.tv || browser.ps4 || browser.xboxOne ? 6 : 2); var physicalAudioChannels = options.audioChannels || (browser.tv || browser.ps4 || browser.xboxOne ? 6 : 2);
var bitrateSetting = getMaxBitrate(); var bitrateSetting = getMaxBitrate();
@ -417,7 +392,6 @@ define(['browser'], function (browser) {
// PS4 fails to load HLS with mp3 audio // PS4 fails to load HLS with mp3 audio
if (!browser.ps4) { if (!browser.ps4) {
// mp3 encoder only supports 2 channels, so only make that preferred if we're only requesting 2 channels // mp3 encoder only supports 2 channels, so only make that preferred if we're only requesting 2 channels
// Also apply it for chromecast because it no longer supports AAC 5.1 // Also apply it for chromecast because it no longer supports AAC 5.1
if (physicalAudioChannels <= 2) { if (physicalAudioChannels <= 2) {
@ -425,14 +399,15 @@ define(['browser'], function (browser) {
} }
} }
} }
if (canPlayAacVideoAudio) {
if (canPlayAacVideoAudio) {
if (videoAudioCodecs.indexOf('aac') === -1) { if (videoAudioCodecs.indexOf('aac') === -1) {
videoAudioCodecs.push('aac'); videoAudioCodecs.push('aac');
} }
hlsVideoAudioCodecs.push('aac'); hlsVideoAudioCodecs.push('aac');
} }
if (supportsMp3VideoAudio) { if (supportsMp3VideoAudio) {
// PS4 fails to load HLS with mp3 audio // PS4 fails to load HLS with mp3 audio
if (!browser.ps4) { if (!browser.ps4) {
@ -525,6 +500,7 @@ define(['browser'], function (browser) {
if (canPlayVp8) { if (canPlayVp8) {
mp4VideoCodecs.push('vp8'); mp4VideoCodecs.push('vp8');
} }
if (canPlayVp9) { if (canPlayVp9) {
mp4VideoCodecs.push('vp9'); mp4VideoCodecs.push('vp9');
} }
@ -563,20 +539,17 @@ define(['browser'], function (browser) {
['opus', 'mp3', 'mp2', 'aac', 'flac', 'alac', 'webma', 'wma', 'wav', 'ogg', 'oga'].filter(canPlayAudioFormat).forEach(function (audioFormat) { ['opus', 'mp3', 'mp2', 'aac', 'flac', 'alac', 'webma', 'wma', 'wav', 'ogg', 'oga'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
if (audioFormat === 'mp2') { if (audioFormat === 'mp2') {
profile.DirectPlayProfiles.push({ profile.DirectPlayProfiles.push({
Container: 'mp2,mp3', Container: 'mp2,mp3',
Type: 'Audio', Type: 'Audio',
AudioCodec: audioFormat AudioCodec: audioFormat
}); });
} else if (audioFormat === 'mp3') { } else if (audioFormat === 'mp3') {
profile.DirectPlayProfiles.push({ profile.DirectPlayProfiles.push({
Container: audioFormat, Container: audioFormat,
Type: 'Audio', Type: 'Audio',
AudioCodec: audioFormat AudioCodec: audioFormat
}); });
} else { } else {
profile.DirectPlayProfiles.push({ profile.DirectPlayProfiles.push({
Container: audioFormat === 'webma' ? 'webma,webm' : audioFormat, Container: audioFormat === 'webma' ? 'webma,webm' : audioFormat,
@ -586,7 +559,6 @@ define(['browser'], function (browser) {
// aac also appears in the m4a container // aac also appears in the m4a container
if (audioFormat === 'aac' || audioFormat === 'alac') { if (audioFormat === 'aac' || audioFormat === 'alac') {
profile.DirectPlayProfiles.push({ profile.DirectPlayProfiles.push({
Container: 'm4a', Container: 'm4a',
AudioCodec: audioFormat, AudioCodec: audioFormat,
@ -619,7 +591,6 @@ define(['browser'], function (browser) {
if (canPlayHls() && browser.enableHlsAudio !== false) { if (canPlayHls() && browser.enableHlsAudio !== false) {
profile.TranscodingProfiles.push({ profile.TranscodingProfiles.push({
// hlsjs, edge, and android all seem to require ts container // hlsjs, edge, and android all seem to require ts container
Container: !canPlayNativeHls() || browser.edge || browser.android ? 'ts' : 'aac', Container: !canPlayNativeHls() || browser.edge || browser.android ? 'ts' : 'aac',
Type: 'Audio', Type: 'Audio',
@ -636,7 +607,6 @@ define(['browser'], function (browser) {
// But for static (offline sync), it will be just fine. // But for static (offline sync), it will be just fine.
// Prioritize aac higher because the encoder can accept more channels than mp3 // Prioritize aac higher because the encoder can accept more channels than mp3
['aac', 'mp3', 'opus', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) { ['aac', 'mp3', 'opus', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
profile.TranscodingProfiles.push({ profile.TranscodingProfiles.push({
Container: audioFormat, Container: audioFormat,
Type: 'Audio', Type: 'Audio',
@ -648,7 +618,6 @@ define(['browser'], function (browser) {
}); });
['opus', 'mp3', 'aac', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) { ['opus', 'mp3', 'aac', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
profile.TranscodingProfiles.push({ profile.TranscodingProfiles.push({
Container: audioFormat, Container: audioFormat,
Type: 'Audio', Type: 'Audio',
@ -804,7 +773,8 @@ define(['browser'], function (browser) {
Condition: 'LessThanEqual', Condition: 'LessThanEqual',
Property: 'VideoLevel', Property: 'VideoLevel',
Value: maxH264Level.toString() Value: maxH264Level.toString()
}] }
]
}); });
if (!browser.edgeUwp && !browser.tizen && !browser.orsay && !browser.web0s) { if (!browser.edgeUwp && !browser.tizen && !browser.orsay && !browser.web0s) {
@ -888,7 +858,6 @@ define(['browser'], function (browser) {
// External vtt or burn in // External vtt or burn in
profile.SubtitleProfiles = []; profile.SubtitleProfiles = [];
if (supportsTextTracks()) { if (supportsTextTracks()) {
profile.SubtitleProfiles.push({ profile.SubtitleProfiles.push({
Format: 'vtt', Format: 'vtt',
Method: 'External' Method: 'External'
@ -896,7 +865,6 @@ define(['browser'], function (browser) {
} }
profile.ResponseProfiles = []; profile.ResponseProfiles = [];
profile.ResponseProfiles.push({ profile.ResponseProfiles.push({
Type: 'Video', Type: 'Video',
Container: 'm4v', Container: 'm4v',

View file

@ -83,7 +83,7 @@
"Art": "Art", "Art": "Art",
"AsManyAsPossible": "As many as possible", "AsManyAsPossible": "As many as possible",
"Ascending": "Ascending", "Ascending": "Ascending",
"AspectRatio": "Aspect ratio", "AspectRatio": "Aspect Ratio",
"AttributeNew": "New", "AttributeNew": "New",
"Audio": "Audio", "Audio": "Audio",
"AuthProviderHelp": "Select an Authentication Provider to be used to authenticate this user's password.", "AuthProviderHelp": "Select an Authentication Provider to be used to authenticate this user's password.",
@ -565,7 +565,7 @@
"ReplaceExistingImages": "Replace existing images", "ReplaceExistingImages": "Replace existing images",
"ReplaceAllMetadata": "Replace all metadata", "ReplaceAllMetadata": "Replace all metadata",
"RepeatOne": "Repeat one", "RepeatOne": "Repeat one",
"RepeatMode": "Repeat mode", "RepeatMode": "Repeat Mode",
"RepeatEpisodes": "Repeat episodes", "RepeatEpisodes": "Repeat episodes",
"RepeatAll": "Repeat all", "RepeatAll": "Repeat all",
"Repeat": "Repeat", "Repeat": "Repeat",

View file

@ -36,7 +36,7 @@
"Artists": "Artists", "Artists": "Artists",
"AsManyAsPossible": "As many as possible", "AsManyAsPossible": "As many as possible",
"Ascending": "Ascending", "Ascending": "Ascending",
"AspectRatio": "Aspect ratio", "AspectRatio": "Aspect Ratio",
"AttributeNew": "New", "AttributeNew": "New",
"Audio": "Audio", "Audio": "Audio",
"AuthProviderHelp": "Select an Authentication Provider to be used to authenticate this user's password.", "AuthProviderHelp": "Select an Authentication Provider to be used to authenticate this user's password.",
@ -1258,7 +1258,7 @@
"Repeat": "Repeat", "Repeat": "Repeat",
"RepeatAll": "Repeat all", "RepeatAll": "Repeat all",
"RepeatEpisodes": "Repeat episodes", "RepeatEpisodes": "Repeat episodes",
"RepeatMode": "Repeat mode", "RepeatMode": "Repeat Mode",
"RepeatOne": "Repeat one", "RepeatOne": "Repeat one",
"ReplaceAllMetadata": "Replace all metadata", "ReplaceAllMetadata": "Replace all metadata",
"ReplaceExistingImages": "Replace existing images", "ReplaceExistingImages": "Replace existing images",