-import videojs, { VideoJsPlayer } from 'video.js'
-import './videojs-components/settings-menu-button'
-import {
- PeerTubePluginOptions,
- ResolutionUpdateData,
- UserWatching,
- VideoJSCaption
-} from './peertube-videojs-typings'
-import { isMobile, timeToInt } from './utils'
+import videojs from 'video.js'
+import { timeToInt } from '@shared/core-utils'
import {
getStoredLastSubtitle,
getStoredMute,
getStoredVolume,
saveLastSubtitle,
saveMuteInStore,
+ saveVideoWatchHistory,
saveVolumeInStore
} from './peertube-player-local-storage'
+import { PeerTubePluginOptions, UserWatching, VideoJSCaption } from './peertube-videojs-typings'
+import { isMobile } from './utils'
+import { SettingsButton } from './videojs-components/settings-menu-button'
+import debug from 'debug'
+
+const logger = debug('peertube:player:peertube')
const Plugin = videojs.getPlugin('plugin')
private videoViewInterval: any
private userWatchingVideoInterval: any
- private lastResolutionChange: ResolutionUpdateData
+
+ private isLive: boolean
private menuOpened = false
private mouseInControlBar = false
- private readonly savedInactivityTimeout: number
+ private mouseInSettings = false
+ private readonly initialInactivityTimeout: number
- constructor (player: VideoJsPlayer, options?: PeerTubePluginOptions) {
+ constructor (player: videojs.Player, options?: PeerTubePluginOptions) {
super(player)
this.videoViewUrl = options.videoViewUrl
this.videoDuration = options.videoDuration
this.videoCaptions = options.videoCaptions
+ this.isLive = options.isLive
+ this.initialInactivityTimeout = this.player.options_.inactivityTimeout
- this.savedInactivityTimeout = player.options_.inactivityTimeout
-
- if (options.autoplay === true) this.player.addClass('vjs-has-autoplay')
+ if (options.autoplay) this.player.addClass('vjs-has-autoplay')
this.player.on('autoplay-failure', () => {
this.player.removeClass('vjs-has-autoplay')
this.player.ready(() => {
const playerOptions = this.player.options_
- if (options.mode === 'webtorrent') {
- this.player.webtorrent().on('resolutionChange', (_: any, d: any) => this.handleResolutionChange(d))
- this.player.webtorrent().on('autoResolutionChange', (_: any, d: any) => this.trigger('autoResolutionChange', d))
- }
-
- if (options.mode === 'p2p-media-loader') {
- this.player.p2pMediaLoader().on('resolutionChange', (_: any, d: any) => this.handleResolutionChange(d))
- }
-
- this.player.tech(true).on('loadedqualitydata', () => {
- setTimeout(() => {
- // Replay a resolution change, now we loaded all quality data
- if (this.lastResolutionChange) this.handleResolutionChange(this.lastResolutionChange)
- }, 0)
- })
-
const volume = getStoredVolume()
if (volume !== undefined) this.player.volume(volume)
})
}
- this.player.textTracks().on('change', () => {
+ this.player.textTracks().addEventListener('change', () => {
const showing = this.player.textTracks().tracks_.find(t => {
return t.kind === 'captions' && t.mode === 'showing'
})
this.initializePlayer()
this.runViewAdd()
- if (options.userWatching) this.runUserWatchVideo(options.userWatching)
+ this.runUserWatchVideo(options.userWatching, options.videoUUID)
})
}
if (this.userWatchingVideoInterval) clearInterval(this.userWatchingVideoInterval)
}
- onMenuOpen () {
- this.menuOpened = false
+ onMenuOpened () {
+ this.menuOpened = true
this.alterInactivity()
}
onMenuClosed () {
- this.menuOpened = true
+ this.menuOpened = false
this.alterInactivity()
}
this.initCaptions()
this.listenControlBarMouse()
+
+ this.listenFullScreenChange()
}
private runViewAdd () {
// After 30 seconds (or 3/4 of the video), add a view to the video
let minSecondsToView = 30
- if (this.videoDuration < minSecondsToView) minSecondsToView = (this.videoDuration * 3) / 4
+ if (!this.isLive && this.videoDuration < minSecondsToView) {
+ minSecondsToView = (this.videoDuration * 3) / 4
+ }
let secondsViewed = 0
this.videoViewInterval = setInterval(() => {
secondsViewed += 1
if (secondsViewed > minSecondsToView) {
- this.clearVideoViewInterval()
+ // Restart the loop if this is a live
+ if (this.isLive) {
+ secondsViewed = 0
+ } else {
+ this.clearVideoViewInterval()
+ }
this.addViewToVideo().catch(err => console.error(err))
}
}, 1000)
}
- private runUserWatchVideo (options: UserWatching) {
+ private runUserWatchVideo (options: UserWatching, videoUUID: string) {
let lastCurrentTime = 0
this.userWatchingVideoInterval = setInterval(() => {
if (currentTime - lastCurrentTime >= 1) {
lastCurrentTime = currentTime
- this.notifyUserIsWatching(currentTime, options.url, options.authorizationHeader)
- .catch(err => console.error('Cannot notify user is watching.', err))
+ if (options) {
+ this.notifyUserIsWatching(currentTime, options.url, options.authorizationHeader)
+ .catch(err => console.error('Cannot notify user is watching.', err))
+ } else {
+ saveVideoWatchHistory(videoUUID, currentTime)
+ }
}
}, this.CONSTANTS.USER_WATCHING_VIDEO_INTERVAL)
}
const body = new URLSearchParams()
body.append('currentTime', currentTime.toString())
- const headers = new Headers({ 'Authorization': authorizationHeader })
+ const headers = new Headers({ Authorization: authorizationHeader })
return fetch(url, { method: 'PUT', body, headers })
}
- private handleResolutionChange (data: ResolutionUpdateData) {
- this.lastResolutionChange = data
-
- const qualityLevels = this.player.qualityLevels()
-
- for (let i = 0; i < qualityLevels.length; i++) {
- if (qualityLevels[i].height === data.resolutionId) {
- data.id = qualityLevels[i].id
- break
- }
- }
-
- this.trigger('resolutionChange', data)
+ private listenFullScreenChange () {
+ this.player.on('fullscreenchange', () => {
+ if (this.player.isFullscreen()) this.player.focus()
+ })
}
private listenControlBarMouse () {
- this.player.controlBar.on('mouseenter', () => {
+ const controlBar = this.player.controlBar
+ const settingsButton: SettingsButton = (controlBar as any).settingsButton
+
+ controlBar.on('mouseenter', () => {
this.mouseInControlBar = true
this.alterInactivity()
})
- this.player.controlBar.on('mouseleave', () => {
+ controlBar.on('mouseleave', () => {
this.mouseInControlBar = false
this.alterInactivity()
})
+
+ settingsButton.dialog.on('mouseenter', () => {
+ this.mouseInSettings = true
+ this.alterInactivity()
+ })
+
+ settingsButton.dialog.on('mouseleave', () => {
+ this.mouseInSettings = false
+ this.alterInactivity()
+ })
}
private alterInactivity () {
- if (this.menuOpened || this.mouseInControlBar) {
- this.player.options_.inactivityTimeout = this.savedInactivityTimeout
+ if (this.menuOpened || this.mouseInSettings || this.mouseInControlBar) {
+ this.setInactivityTimeout(0)
return
}
- this.player.options_.inactivityTimeout = 1
+ this.setInactivityTimeout(this.initialInactivityTimeout)
+ this.player.reportUserActivity(true)
+ }
+
+ private setInactivityTimeout (timeout: number) {
+ (this.player as any).cache_.inactivityTimeout = timeout
+ this.player.options_.inactivityTimeout = timeout
+
+ logger('Set player inactivity to ' + timeout)
}
private initCaptions () {