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

Support for faster playback rates.

The HTML5 video element already has a well-supported "playbackRate" attribute
which can be used to increase playback rate.  This change wires up that control
to be displayed in the Jellyfish web player.

The playback rates offered are between 0.5x and 2x in 0.25x increments, which
matches the YouTube player.  This change also wires up the ">" and "<" key
events to increase and decrease the playback rate, which mirrors the keyboard
shortcuts supported by YouTube.
This commit is contained in:
Jeff Sharkey 2020-05-22 22:23:18 -06:00 committed by José Olívio M. Pedrosa
parent dc682bce17
commit afa56c18af
No known key found for this signature in database
GPG key ID: 9F894BED87ABBEC8
6 changed files with 122 additions and 0 deletions

View file

@ -1112,6 +1112,52 @@ class PlaybackManager {
}
};
self.increasePlaybackRate = function (player) {
player = player || self._currentPlayer;
if (player) {
let current = self.getPlaybackRate(player);
let supported = self.getSupportedPlaybackRates(player);
let index = -1;
for (let i = 0, length = supported.length; i < length; i++) {
if (supported[i].id === current) {
index = i;
break;
}
}
index = Math.min(index + 1, supported.length - 1);
self.setPlaybackRate(supported[index].id, player);
}
};
self.decreasePlaybackRate = function (player) {
player = player || self._currentPlayer;
if (player) {
let current = self.getPlaybackRate(player);
let supported = self.getSupportedPlaybackRates(player);
let index = -1;
for (let i = 0, length = supported.length; i < length; i++) {
if (supported[i].id === current) {
index = i;
break;
}
}
index = Math.max(index - 1, 0);
self.setPlaybackRate(supported[index].id, player);
}
};
self.getSupportedPlaybackRates = function (player) {
player = player || self._currentPlayer;
if (player && player.getSupportedPlaybackRates) {
return player.getSupportedPlaybackRates();
}
return [];
};
let brightnessOsdLoaded;
self.setBrightness = function (val, player) {
player = player || self._currentPlayer;
@ -3697,6 +3743,9 @@ class PlaybackManager {
case 'SetAspectRatio':
this.setAspectRatio(cmd.Arguments.AspectRatio, player);
break;
case 'PlaybackRate':
this.setPlaybackRate(cmd.Arguments.PlaybackRate, player);
break;
case 'SetBrightness':
this.setBrightness(cmd.Arguments.Brightness, player);
break;

View file

@ -149,6 +149,28 @@ function showAspectRatioMenu(player, btn) {
});
}
function showPlaybackRateMenu(player, btn) {
// each has a name and id
const currentId = playbackManager.getPlaybackRate(player);
const menuItems = playbackManager.getSupportedPlaybackRates(player).map(i => ({
id: i.id,
name: i.name,
selected: i.id === currentId
}));
return actionsheet.show({
items: menuItems,
positionTo: btn
}).then(function (id) {
if (id) {
playbackManager.setPlaybackRate(id, player);
return Promise.resolve();
}
return Promise.reject();
});
}
function showWithUser(options, player, user) {
var supportedCommands = playbackManager.getSupportedCommands(player);
@ -166,6 +188,17 @@ function showWithUser(options, player, user) {
});
}
if (supportedCommands.indexOf('PlaybackRate') !== -1) {
const currentPlaybackRateId = playbackManager.getPlaybackRate(player);
const currentPlaybackRate = playbackManager.getSupportedPlaybackRates(player).filter(i => i.id === currentPlaybackRateId)[0];
menuItems.push({
name: globalize.translate('PlaybackRate'),
id: 'playbackrate',
asideText: currentPlaybackRate ? currentPlaybackRate.name : null
});
}
if (user && user.Policy.EnableVideoPlaybackTranscoding) {
var secondaryQualityText = getQualitySecondaryText(player);
@ -230,6 +263,8 @@ function handleSelectedOption(id, options, player) {
return showQualityMenu(player, options.positionTo);
case 'aspectratio':
return showAspectRatioMenu(player, options.positionTo);
case 'playbackrate':
return showPlaybackRateMenu(player, options.positionTo);
case 'repeatmode':
return showRepeatModeMenu(player, options.positionTo);
case 'stats':

View file

@ -1243,6 +1243,12 @@ import 'css!assets/css/videoosd';
}
break;
}
case '>':
playbackManager.increasePlaybackRate(currentPlayer);
break;
case '<':
playbackManager.decreasePlaybackRate(currentPlayer);
break;
}
}

View file

@ -1634,6 +1634,31 @@ function tryRemoveElement(elem) {
return null;
}
getSupportedPlaybackRates() {
return [{
name: '0.5x',
id: 0.5
}, {
name: '0.75x',
id: 0.75
}, {
name: '1x',
id: 1.0
}, {
name: '1.25x',
id: 1.25
}, {
name: '1.5x',
id: 1.5
}, {
name: '1.75x',
id: 1.75
}, {
name: '2x',
id: 2.0
}];
}
setVolume(val) {
const mediaElement = this.#mediaElement;
if (mediaElement) {

View file

@ -185,6 +185,12 @@ import appHost from 'apphost';
'changezoom': () => {
playbackManager.toggleAspectRatio();
},
'increaseplaybackrate': () => {
playbackManager.increasePlaybackRate();
},
'decreaseplaybackrate': () => {
playbackManager.decreasePlaybackRate();
},
'changeaudiotrack': () => {
playbackManager.changeAudioStream();
},

View file

@ -1220,6 +1220,7 @@
"Play": "Play",
"PlayAllFromHere": "Play all from here",
"PlaybackData": "Playback Data",
"PlaybackRate": "Playback Rate",
"PlayCount": "Play count",
"PlayFromBeginning": "Play from beginning",
"PlayNext": "Play next",