Add hook to alter player build options
authorChocobozzz <me@florianbigard.com>
Thu, 5 Dec 2019 16:06:18 +0000 (17:06 +0100)
committerChocobozzz <me@florianbigard.com>
Thu, 5 Dec 2019 16:06:18 +0000 (17:06 +0100)
client/src/app/videos/+video-watch/video-watch.component.ts
client/src/assets/player/peertube-player-manager.ts
client/src/standalone/videos/embed.ts
shared/models/plugins/client-hook.model.ts

index aacd697cff7f89b67d3712f9c2c9b47c2e914a26..523865feffc3299ea637dfa9e06f6d706c1bd85e 100644 (file)
@@ -5,7 +5,7 @@ import { RedirectService } from '@app/core/routing/redirect.service'
 import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage'
 import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component'
 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 { Hotkey, HotkeysService } from 'angular2-hotkeys'
 import { UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared'
@@ -391,10 +391,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
     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)) {
       const res = await this.confirmService.confirm(
         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')
     playerElementWrapper.appendChild(this.playerElement)
 
-    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: 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 params = {
+      video: this.video,
+      videoCaptions,
+      urlOptions,
+      user: this.user
     }
+    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.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.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)
   }
 
+  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 () {
     if (!this.player) return
 
index 7c7c9ad2a6127cb7e034f72126bd25d555df10fe..4ddbaed82f9b5abb3595a7214abcacb159b5d16d 100644 (file)
@@ -63,7 +63,7 @@ export interface CommonOptions extends CustomizationOptions {
   inactivityTimeout: number
   poster: string
 
-  theaterMode: boolean
+  theaterButton: boolean
   captions: boolean
 
   videoViewUrl: string
@@ -311,7 +311,7 @@ export class PeertubePlayerManager {
         children: this.getControlBarChildren(mode, {
           captions: commonOptions.captions,
           peertubeLink: commonOptions.peertubeLink,
-          theaterMode: commonOptions.theaterMode
+          theaterButton: commonOptions.theaterButton
         })
       }
     }
@@ -382,7 +382,7 @@ export class PeertubePlayerManager {
 
   private static getControlBarChildren (mode: PlayerMode, options: {
     peertubeLink: boolean
-    theaterMode: boolean,
+    theaterButton: boolean,
     captions: boolean
   }) {
     const settingEntries = []
@@ -432,7 +432,7 @@ export class PeertubePlayerManager {
       })
     }
 
-    if (options.theaterMode === true) {
+    if (options.theaterButton === true) {
       Object.assign(children, {
         'theaterButton': {}
       })
index 40d945824919c2f6f0fd949cfb0302a65f68936f..bd012f5065af26a28debc07049711bd1fa78c992 100644 (file)
@@ -194,7 +194,7 @@ export class PeerTubeEmbed {
         enableHotkeys: true,
         peertubeLink: true,
         poster: window.location.origin + videoInfo.previewPath,
-        theaterMode: false,
+        theaterButton: false,
 
         serverUrl: window.location.origin,
         language: navigator.language,
index 91167ff8c76a56712c94552fb538a88e029345eb..f0cdb8b1930392ae916333d18a2d7fa5dbfa3fb1 100644 (file)
@@ -1,4 +1,5 @@
 // Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target}
+// Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target}
 
 export const clientFilterHookObject = {
   // 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 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