Automatically adapt player ratio

pull/5917/head
Chocobozzz 2023-08-18 09:48:45 +02:00
parent 276f5fa24f
commit 8e4fba97b2
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
12 changed files with 88 additions and 34 deletions

View File

@ -6,6 +6,7 @@
.playlist {
position: relative;
min-width: 200px;
width: 25vw;
max-width: 470px;
height: 66vh;
background-color: pvar(--mainBackgroundColor);

View File

@ -4,15 +4,8 @@
@use '_bootstrap-variables';
@use '_miniature' as *;
$video-height: 66vh;
@function getPlayerHeight ($width) {
@return calc(#{$width} / #{$video-watch-player-factor});
}
@function getPlayerWidth ($height) {
@return calc(#{$height} * #{$video-watch-player-factor});
}
$video-default-height: 66vh;
$video-theater-height: calc(100vh - #{$header-height} - #{$theater-bottom-space});
@mixin playlist-below-player {
width: 100% !important;
@ -38,20 +31,16 @@ $video-height: 66vh;
.root {
&.theater-enabled #video-wrapper {
$height: calc(100vh - #{$header-height} - #{$theater-bottom-space});
flex-direction: column;
justify-content: center;
#videojs-wrapper {
width: 100%;
height: $height;
height: $video-theater-height;
}
::ng-deep .video-js {
height: $height;
width: 100%;
max-width: initial;
--player-height: #{$video-theater-height};
}
my-video-watch-playlist ::ng-deep .playlist {
@ -65,10 +54,24 @@ $video-height: 66vh;
display: flex;
justify-content: center;
#videojs-wrapper {
display: flex;
justify-content: center;
flex-grow: 1;
height: $video-default-height;
}
::ng-deep .video-js {
--player-height: #{$video-default-height};
--player-portrait-mode: 0;
// Default player ratio, redefined by the player to automatically adapt player size
--player-ratio: #{math.div(16, 9)};
width: 100%;
max-width: getPlayerWidth($video-height);
height: $video-height;
height: var(--player-height);
// Can be recalculated by the player depending on video ratio
max-width: calc(var(--player-height) * var(--player-ratio));
// VideoJS create an inner video player
video {
@ -78,13 +81,6 @@ $video-height: 66vh;
}
}
#videojs-wrapper {
display: flex;
justify-content: center;
flex-grow: 1;
height: $video-height;
}
.remote-server-down {
color: #fff;
display: flex;
@ -253,12 +249,16 @@ my-video-comments {
@media screen and (max-width: 600px) {
#videojs-wrapper {
height: getPlayerHeight(100vw) !important;
// Reset height
height: initial !important;
.remote-server-down,
::ng-deep .video-js {
width: 100vw;
height: getPlayerHeight(100vw) !important;
--player-portrait-mode: 1;
// Can be recalculated by the player depending on video ratio
height: calc(100vw / var(--player-ratio)) !important;
max-height: $video-theater-height;
}
}

View File

@ -623,7 +623,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
peertubeLink: () => false,
pluginsManager: this.pluginService.getPluginsManager()
pluginsManager: this.pluginService.getPluginsManager(),
autoPlayerRatio: {
cssRatioVariable: '--player-ratio',
cssPlayerPortraitModeVariable: '--player-portrait-mode'
}
}
}

View File

@ -364,7 +364,9 @@ export class PeerTubePlayer {
videoUUID: () => this.currentLoadOptions.videoUUID,
subtitle: () => this.currentLoadOptions.subtitle,
poster: () => this.currentLoadOptions.poster
poster: () => this.currentLoadOptions.poster,
autoPlayerRatio: this.options.autoPlayerRatio
},
metrics: {
mode: () => this.currentLoadOptions.mode,

View File

@ -140,10 +140,10 @@ class MetricsPlugin extends Plugin {
private trackBytes () {
this.player.on('network-info', (_event, data: PlayerNetworkInfo) => {
this.downloadedBytesHTTP += Math.round(data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0))
this.downloadedBytesP2P += Math.round((data.p2p?.downloaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.downloaded || 0))
this.downloadedBytesHTTP += Math.max(Math.round(data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0)), 0)
this.downloadedBytesP2P += Math.max(Math.round((data.p2p?.downloaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.downloaded || 0)), 0)
this.uploadedBytesP2P += Math.round((data.p2p?.uploaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.uploaded || 0))
this.uploadedBytesP2P += Math.max(Math.round((data.p2p?.uploaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.uploaded || 0)), 0)
this.p2pPeers = data.p2p?.peersP2POnly
this.p2pEnabled = !!data.p2p

View File

@ -119,6 +119,14 @@ class P2pMediaLoaderPlugin extends Plugin {
this.runStats()
this.hlsjs.on(Hlsjs.Events.LEVEL_SWITCHED, () => this.player.trigger('engine-resolution-change'))
this.hlsjs.on(Hlsjs.Events.MANIFEST_PARSED, (_event, data) => {
if (Array.isArray(data.levels) && data.levels.length > 1) {
const level = data.levels[0]
this.player.trigger('video-ratio-changed', { ratio: level.width / level.height })
}
})
}
private runStats () {

View File

@ -115,6 +115,8 @@ class PeerTubePlugin extends Plugin {
this.hideFatalError()
})
})
this.initOnRatioChange()
}
dispose () {
@ -210,6 +212,25 @@ class PeerTubePlugin extends Plugin {
this.runUserViewing()
}
private initOnRatioChange () {
if (!this.options.autoPlayerRatio) return
const defaultRatio = getComputedStyle(this.player.el()).getPropertyValue(this.options.autoPlayerRatio.cssRatioVariable)
this.player.on('video-ratio-changed', (_event, data: { ratio: number }) => {
const el = this.player.el() as HTMLElement
// In portrait screen mode, we allow player with bigger height size than width
const portraitMode = getComputedStyle(el).getPropertyValue(this.options.autoPlayerRatio.cssPlayerPortraitModeVariable) === '1'
const currentRatio = !portraitMode && data.ratio < 1
? defaultRatio
: data.ratio
el.style.setProperty('--player-ratio', currentRatio + '')
})
}
// ---------------------------------------------------------------------------
private runUserViewing () {

View File

@ -19,6 +19,7 @@ class WebVideoPlugin extends Plugin {
private onErrorHandler: () => void
private onPlayHandler: () => void
private onLoadedMetadata: () => void
constructor (player: videojs.Player, options?: WebVideoPluginOptions) {
super(player, options)
@ -28,6 +29,12 @@ class WebVideoPlugin extends Plugin {
this.updateVideoFile({ videoFile: this.pickAverageVideoFile(), isUserResolutionChange: false })
this.onLoadedMetadata = () => {
player.trigger('video-ratio-changed', { ratio: this.player.videoWidth() / this.player.videoHeight() })
}
player.on('loadedmetadata', this.onLoadedMetadata)
player.ready(() => {
this.buildQualities()
@ -43,6 +50,7 @@ class WebVideoPlugin extends Plugin {
dispose () {
clearInterval(this.networkInfoInterval)
if (this.onLoadedMetadata) this.player.off('loadedmetadata', this.onLoadedMetadata)
if (this.onErrorHandler) this.player.off('error', this.onErrorHandler)
if (this.onPlayHandler) this.player.off('canplay', this.onPlayHandler)

View File

@ -38,6 +38,11 @@ export type PeerTubePlayerContructorOptions = {
language: string
pluginsManager: PluginsManager
autoPlayerRatio?: {
cssRatioVariable: string
cssPlayerPortraitModeVariable: string
}
}
export type PeerTubePlayerLoadOptions = {

View File

@ -104,6 +104,11 @@ type VideoJSStoryboard = {
}
type PeerTubePluginOptions = {
autoPlayerRatio: {
cssRatioVariable: string
cssPlayerPortraitModeVariable: string
}
hasAutoplay: () => videojs.Autoplay
videoViewUrl: () => string

View File

@ -97,7 +97,6 @@ $activated-action-button-color: #212529;
$focus-box-shadow-form: 0 0 0 .2rem;
$form-input-font-size: 15px;
$video-watch-player-factor: math.div(16, 9);
$video-watch-info-margin-left: 44px;
$primeng-breakpoint: 960px;

View File

@ -18,7 +18,7 @@ describe('Test notifications API', function () {
let emails: object[] = []
before(async function () {
this.timeout(120000)
this.timeout(240000)
const res = await prepareNotificationsTest(1)
emails = res.emails