Add hook to alter player build options

pull/2302/head
Chocobozzz 2019-12-05 17:06:18 +01:00
parent 0d3a9be9f1
commit 3d9a63d3d8
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
4 changed files with 113 additions and 86 deletions

View File

@ -5,7 +5,7 @@ import { RedirectService } from '@app/core/routing/redirect.service'
import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage'
import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component' import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component'
import { MetaService } from '@ngx-meta/core' import { MetaService } from '@ngx-meta/core'
import { Notifier, ServerService } from '@app/core' import { AuthUser, Notifier, ServerService } from '@app/core'
import { forkJoin, Observable, Subscription } from 'rxjs' import { forkJoin, Observable, Subscription } from 'rxjs'
import { Hotkey, HotkeysService } from 'angular2-hotkeys' import { Hotkey, HotkeysService } from 'angular2-hotkeys'
import { UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared' import { UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared'
@ -391,10 +391,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.videoWatchPlaylist.updatePlaylistIndex(video) this.videoWatchPlaylist.updatePlaylistIndex(video)
let startTime = timeToInt(urlOptions.startTime) || (this.video.userHistory ? this.video.userHistory.currentTime : 0)
// If we are at the end of the video, reset the timer
if (this.video.duration - startTime <= 1) startTime = 0
if (this.isVideoBlur(this.video)) { if (this.isVideoBlur(this.video)) {
const res = await this.confirmService.confirm( const res = await this.confirmService.confirm(
this.i18n('This video contains mature or explicit content. Are you sure you want to watch it?'), this.i18n('This video contains mature or explicit content. Are you sure you want to watch it?'),
@ -413,84 +409,20 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.playerElement.setAttribute('playsinline', 'true') this.playerElement.setAttribute('playsinline', 'true')
playerElementWrapper.appendChild(this.playerElement) playerElementWrapper.appendChild(this.playerElement)
const playerCaptions = videoCaptions.map(c => ({ const params = {
label: c.language.label, video: this.video,
language: c.language.id, videoCaptions,
src: environment.apiUrl + c.captionPath urlOptions,
})) user: this.user
const options: PeertubePlayerManagerOptions = {
common: {
autoplay: this.isAutoplay(),
playerElement: this.playerElement,
onPlayerElementChange: (element: HTMLVideoElement) => this.playerElement = element,
videoDuration: this.video.duration,
enableHotkeys: true,
inactivityTimeout: 2500,
poster: this.video.previewUrl,
startTime,
stopTime: urlOptions.stopTime,
controls: urlOptions.controls,
muted: urlOptions.muted,
loop: urlOptions.loop,
subtitle: urlOptions.subtitle,
peertubeLink: urlOptions.peertubeLink,
theaterMode: true,
captions: videoCaptions.length !== 0,
videoViewUrl: this.video.privacy.id !== VideoPrivacy.PRIVATE
? this.videoService.getVideoViewUrl(this.video.uuid)
: null,
embedUrl: this.video.embedUrl,
language: this.localeId,
userWatching: this.user && this.user.videosHistoryEnabled === true ? {
url: this.videoService.getUserWatchingVideoUrl(this.video.uuid),
authorizationHeader: this.authService.getRequestHeaderValue()
} : undefined,
serverUrl: environment.apiUrl,
videoCaptions: playerCaptions
},
webtorrent: {
videoFiles: this.video.files
}
}
let mode: PlayerMode
if (urlOptions.playerMode) {
if (urlOptions.playerMode === 'p2p-media-loader') mode = 'p2p-media-loader'
else mode = 'webtorrent'
} else {
if (this.video.hasHlsPlaylist()) mode = 'p2p-media-loader'
else mode = 'webtorrent'
}
if (mode === 'p2p-media-loader') {
const hlsPlaylist = this.video.getHlsPlaylist()
const p2pMediaLoader = {
playlistUrl: hlsPlaylist.playlistUrl,
segmentsSha256Url: hlsPlaylist.segmentsSha256Url,
redundancyBaseUrls: hlsPlaylist.redundancies.map(r => r.baseUrl),
trackerAnnounce: this.video.trackerUrls,
videoFiles: hlsPlaylist.files
} as P2PMediaLoaderOptions
Object.assign(options, { p2pMediaLoader })
} }
const { playerMode, playerOptions } = await this.hooks.wrapFun(
this.buildPlayerManagerOptions.bind(this),
params,
'filter:internal.video-watch.player.build-options.result'
)
this.zone.runOutsideAngular(async () => { this.zone.runOutsideAngular(async () => {
this.player = await PeertubePlayerManager.initialize(mode, options, player => this.player = player) this.player = await PeertubePlayerManager.initialize(playerMode, playerOptions, player => this.player = player)
this.player.focus() this.player.focus()
this.player.on('customError', ({ err }: { err: any }) => this.handleError(err)) this.player.on('customError', ({ err }: { err: any }) => this.handleError(err))
@ -637,6 +569,97 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
if (this.isUserLoggedIn()) this.hotkeysService.add(this.hotkeys) if (this.isUserLoggedIn()) this.hotkeysService.add(this.hotkeys)
} }
private buildPlayerManagerOptions (params: {
video: VideoDetails,
videoCaptions: VideoCaption[],
urlOptions: CustomizationOptions & { playerMode: PlayerMode },
user?: AuthUser
}) {
const { video, videoCaptions, urlOptions, user } = params
let startTime = timeToInt(urlOptions.startTime) || (video.userHistory ? video.userHistory.currentTime : 0)
// If we are at the end of the video, reset the timer
if (video.duration - startTime <= 1) startTime = 0
const playerCaptions = videoCaptions.map(c => ({
label: c.language.label,
language: c.language.id,
src: environment.apiUrl + c.captionPath
}))
const options: PeertubePlayerManagerOptions = {
common: {
autoplay: this.isAutoplay(),
playerElement: this.playerElement,
onPlayerElementChange: (element: HTMLVideoElement) => this.playerElement = element,
videoDuration: video.duration,
enableHotkeys: true,
inactivityTimeout: 2500,
poster: video.previewUrl,
startTime,
stopTime: urlOptions.stopTime,
controls: urlOptions.controls,
muted: urlOptions.muted,
loop: urlOptions.loop,
subtitle: urlOptions.subtitle,
peertubeLink: urlOptions.peertubeLink,
theaterButton: true,
captions: videoCaptions.length !== 0,
videoViewUrl: video.privacy.id !== VideoPrivacy.PRIVATE
? this.videoService.getVideoViewUrl(video.uuid)
: null,
embedUrl: video.embedUrl,
language: this.localeId,
userWatching: user && user.videosHistoryEnabled === true ? {
url: this.videoService.getUserWatchingVideoUrl(video.uuid),
authorizationHeader: this.authService.getRequestHeaderValue()
} : undefined,
serverUrl: environment.apiUrl,
videoCaptions: playerCaptions
},
webtorrent: {
videoFiles: video.files
}
}
let mode: PlayerMode
if (urlOptions.playerMode) {
if (urlOptions.playerMode === 'p2p-media-loader') mode = 'p2p-media-loader'
else mode = 'webtorrent'
} else {
if (video.hasHlsPlaylist()) mode = 'p2p-media-loader'
else mode = 'webtorrent'
}
if (mode === 'p2p-media-loader') {
const hlsPlaylist = video.getHlsPlaylist()
const p2pMediaLoader = {
playlistUrl: hlsPlaylist.playlistUrl,
segmentsSha256Url: hlsPlaylist.segmentsSha256Url,
redundancyBaseUrls: hlsPlaylist.redundancies.map(r => r.baseUrl),
trackerAnnounce: video.trackerUrls,
videoFiles: hlsPlaylist.files
} as P2PMediaLoaderOptions
Object.assign(options, { p2pMediaLoader })
}
return { playerMode: mode, playerOptions: options }
}
private pausePlayer () { private pausePlayer () {
if (!this.player) return if (!this.player) return

View File

@ -63,7 +63,7 @@ export interface CommonOptions extends CustomizationOptions {
inactivityTimeout: number inactivityTimeout: number
poster: string poster: string
theaterMode: boolean theaterButton: boolean
captions: boolean captions: boolean
videoViewUrl: string videoViewUrl: string
@ -311,7 +311,7 @@ export class PeertubePlayerManager {
children: this.getControlBarChildren(mode, { children: this.getControlBarChildren(mode, {
captions: commonOptions.captions, captions: commonOptions.captions,
peertubeLink: commonOptions.peertubeLink, peertubeLink: commonOptions.peertubeLink,
theaterMode: commonOptions.theaterMode theaterButton: commonOptions.theaterButton
}) })
} }
} }
@ -382,7 +382,7 @@ export class PeertubePlayerManager {
private static getControlBarChildren (mode: PlayerMode, options: { private static getControlBarChildren (mode: PlayerMode, options: {
peertubeLink: boolean peertubeLink: boolean
theaterMode: boolean, theaterButton: boolean,
captions: boolean captions: boolean
}) { }) {
const settingEntries = [] const settingEntries = []
@ -432,7 +432,7 @@ export class PeertubePlayerManager {
}) })
} }
if (options.theaterMode === true) { if (options.theaterButton === true) {
Object.assign(children, { Object.assign(children, {
'theaterButton': {} 'theaterButton': {}
}) })

View File

@ -194,7 +194,7 @@ export class PeerTubeEmbed {
enableHotkeys: true, enableHotkeys: true,
peertubeLink: true, peertubeLink: true,
poster: window.location.origin + videoInfo.previewPath, poster: window.location.origin + videoInfo.previewPath,
theaterMode: false, theaterButton: false,
serverUrl: window.location.origin, serverUrl: window.location.origin,
language: navigator.language, language: navigator.language,

View File

@ -1,4 +1,5 @@
// Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target} // Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target}
// Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target}
export const clientFilterHookObject = { export const clientFilterHookObject = {
// Filter params/result of the function that fetch videos of the trending page // Filter params/result of the function that fetch videos of the trending page
@ -41,7 +42,10 @@ export const clientFilterHookObject = {
'filter:api.search.video-channels.list.result': true, 'filter:api.search.video-channels.list.result': true,
// Filter form // Filter form
'filter:api.signup.registration.create.params': true 'filter:api.signup.registration.create.params': true,
// Filter the options to create our player
'filter:internal.video-watch.player.build-options.result': true
} }
export type ClientFilterHookName = keyof typeof clientFilterHookObject export type ClientFilterHookName = keyof typeof clientFilterHookObject