-import { VideoFile } from '../../../../shared/models/videos'
-import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js'
-import 'videojs-hotkeys'
+import 'videojs-hotkeys/videojs.hotkeys'
import 'videojs-dock'
import 'videojs-contextmenu-ui'
import 'videojs-contrib-quality-levels'
import './videojs-components/settings-panel'
import './videojs-components/settings-panel-child'
import './videojs-components/theater-button'
-import { P2PMediaLoaderPluginOptions, UserWatching, VideoJSCaption, VideoJSPluginOptions } from './peertube-videojs-typings'
-import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig } from './utils'
-import { isDefaultLocale } from '../../../../shared/models/i18n/i18n'
-import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
-import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
+import videojs from 'video.js'
+import { VideoFile } from '@shared/models'
+import { isDefaultLocale } from '@shared/core-utils/i18n'
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
+import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
+import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
import { getStoredP2PEnabled } from './peertube-player-local-storage'
+import { P2PMediaLoaderPluginOptions, UserWatching, VideoJSCaption, VideoJSPluginOptions } from './peertube-videojs-typings'
import { TranslationsManager } from './translations-manager'
-
-// For VideoJS
-(window as any).WebVTT = require('vtt.js/lib/vtt.js').WebVTT;
+import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig, isIOS, isSafari } from './utils'
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
(videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed'
export class PeertubePlayerManager {
private static playerElementClassName: string
- private static onPlayerChange: (player: VideoJsPlayer) => void
+ private static onPlayerChange: (player: videojs.Player) => void
- static async initialize (mode: PlayerMode, options: PeertubePlayerManagerOptions, onPlayerChange: (player: VideoJsPlayer) => void) {
+ static async initialize (mode: PlayerMode, options: PeertubePlayerManagerOptions, onPlayerChange: (player: videojs.Player) => void) {
let p2pMediaLoader: any
this.onPlayerChange = onPlayerChange
const self = this
return new Promise(res => {
- videojs(options.common.playerElement, videojsOptions, function (this: VideoJsPlayer) {
+ videojs(options.common.playerElement, videojsOptions, function (this: videojs.Player) {
const player = this
let alreadyFallback = false
const videojsOptions = this.getVideojsOptions(mode, options)
const self = this
- videojs(newVideoElement, videojsOptions, function (this: VideoJsPlayer) {
+ videojs(newVideoElement, videojsOptions, function (this: videojs.Player) {
const player = this
self.addContextMenu(mode, player, options.common.embedUrl)
mode: PlayerMode,
options: PeertubePlayerManagerOptions,
p2pMediaLoaderModule?: any
- ): VideoJsPlayerOptions {
+ ): videojs.PlayerOptions {
const commonOptions = options.common
- let autoplay = commonOptions.autoplay
+ let autoplay = this.getAutoPlayValue(commonOptions.autoplay)
let html5 = {}
const plugins: VideoJSPluginOptions = {
? commonOptions.muted
: undefined, // Undefined so the player knows it has to check the local storage
- autoplay: autoplay === true
- ? 'play' // Use 'any' instead of true to get notifier by videojs if autoplay fails
- : autoplay,
+ autoplay: this.getAutoPlayValue(autoplay),
poster: commonOptions.poster,
inactivityTimeout: commonOptions.inactivityTimeout,
}
const hlsjs = {
levelLabelHandler: (level: { height: number, width: number }) => {
- const file = p2pMediaLoaderOptions.videoFiles.find(f => f.resolution.id === level.height)
+ const resolution = Math.min(level.height || 0, level.width || 0)
+
+ const file = p2pMediaLoaderOptions.videoFiles.find(f => f.resolution.id === resolution)
+ if (!file) {
+ console.error('Cannot find video file for level %d.', level.height)
+ return level.height
+ }
let label = file.resolution.label
if (file.fps >= 50) label += file.fps
return children
}
- private static addContextMenu (mode: PlayerMode, player: VideoJsPlayer, videoEmbedUrl: string) {
+ private static addContextMenu (mode: PlayerMode, player: videojs.Player, videoEmbedUrl: string) {
const content = [
{
label: player.localize('Copy the video URL'),
},
{
label: player.localize('Copy the video URL at the current time'),
- listener: function (this: VideoJsPlayer) {
+ listener: function (this: videojs.Player) {
copyToClipboard(buildVideoLink({ startTime: this.currentTime() }))
}
},
if (mode === 'webtorrent') {
content.push({
label: player.localize('Copy magnet URI'),
- listener: function (this: VideoJsPlayer) {
+ listener: function (this: videojs.Player) {
copyToClipboard(this.webtorrent().getCurrentVideoFile().magnetUri)
}
})
private static addHotkeysOptions (plugins: VideoJSPluginOptions) {
Object.assign(plugins, {
hotkeys: {
+ skipInitialFocus: true,
+ enableInactiveFocus: false,
+ captureDocumentHotkeys: true,
+ documentHotkeysFocusElementFilter: (e: HTMLElement) => {
+ const tagName = e.tagName.toLowerCase()
+ return e.id === 'content' || tagName === 'body' || tagName === 'video'
+ },
+
enableVolumeScroll: false,
enableModifiersForNumbers: false,
}
})
}
+
+ private static getAutoPlayValue (autoplay: any) {
+ if (autoplay !== true) return autoplay
+
+ // Giving up with iOS
+ if (isIOS()) return false
+
+ // We have issues with autoplay and Safari.
+ // any that tries to play using auto mute seems to work
+ if (isSafari()) return 'any'
+
+ return 'play'
+ }
}
// ############################################################################