Add live autostart/messages in embed
This commit is contained in:
parent
f1a0f3b701
commit
d3f4689bde
|
@ -430,6 +430,11 @@ class WebTorrentPlugin extends Plugin {
|
||||||
private initializePlayer () {
|
private initializePlayer () {
|
||||||
this.buildQualities()
|
this.buildQualities()
|
||||||
|
|
||||||
|
if (this.videoFiles.length === 0) {
|
||||||
|
this.player.addClass('disabled')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (this.autoplay) {
|
if (this.autoplay) {
|
||||||
this.player.posterImage.hide()
|
this.player.posterImage.hide()
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,15 @@ body {
|
||||||
font-size: $font-size;
|
font-size: $font-size;
|
||||||
color: pvar(--embedForegroundColor);
|
color: pvar(--embedForegroundColor);
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
cursor: default;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
.vjs-big-play-button {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.vjs-audio-button {
|
.vjs-audio-button {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,17 @@ body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-information {
|
||||||
|
width: 100%;
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
padding: 20px 0;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 300px) {
|
@media screen and (max-width: 300px) {
|
||||||
|
|
|
@ -4,12 +4,12 @@ import '../../assets/player/shared/dock/peertube-dock-plugin'
|
||||||
import videojs from 'video.js'
|
import videojs from 'video.js'
|
||||||
import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
|
import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
|
||||||
import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models'
|
import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models'
|
||||||
|
import { PeertubePlayerManager } from '../../assets/player'
|
||||||
import { TranslationsManager } from '../../assets/player/translations-manager'
|
import { TranslationsManager } from '../../assets/player/translations-manager'
|
||||||
import { getParamString } from '../../root-helpers'
|
import { getParamString } from '../../root-helpers'
|
||||||
import { PeerTubeEmbedApi } from './embed-api'
|
import { PeerTubeEmbedApi } from './embed-api'
|
||||||
import { AuthHTTP, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared'
|
import { AuthHTTP, LiveManager, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared'
|
||||||
import { PlayerHTML } from './shared/player-html'
|
import { PlayerHTML } from './shared/player-html'
|
||||||
import { PeertubePlayerManager } from '../../assets/player'
|
|
||||||
|
|
||||||
export class PeerTubeEmbed {
|
export class PeerTubeEmbed {
|
||||||
player: videojs.Player
|
player: videojs.Player
|
||||||
|
@ -26,6 +26,7 @@ export class PeerTubeEmbed {
|
||||||
private readonly peertubePlugin: PeerTubePlugin
|
private readonly peertubePlugin: PeerTubePlugin
|
||||||
private readonly playerHTML: PlayerHTML
|
private readonly playerHTML: PlayerHTML
|
||||||
private readonly playerManagerOptions: PlayerManagerOptions
|
private readonly playerManagerOptions: PlayerManagerOptions
|
||||||
|
private readonly liveManager: LiveManager
|
||||||
|
|
||||||
private playlistTracker: PlaylistTracker
|
private playlistTracker: PlaylistTracker
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ export class PeerTubeEmbed {
|
||||||
this.peertubePlugin = new PeerTubePlugin(this.http)
|
this.peertubePlugin = new PeerTubePlugin(this.http)
|
||||||
this.playerHTML = new PlayerHTML(videoWrapperId)
|
this.playerHTML = new PlayerHTML(videoWrapperId)
|
||||||
this.playerManagerOptions = new PlayerManagerOptions(this.playerHTML, this.videoFetcher, this.peertubePlugin)
|
this.playerManagerOptions = new PlayerManagerOptions(this.playerHTML, this.videoFetcher, this.peertubePlugin)
|
||||||
|
this.liveManager = new LiveManager(this.playerHTML)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.config = JSON.parse(window['PeerTubeServerConfig'])
|
this.config = JSON.parse(window['PeerTubeServerConfig'])
|
||||||
|
@ -235,6 +237,17 @@ export class PeerTubeEmbed {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.peertubePlugin.getPluginsManager().runHook('action:embed.player.loaded', undefined, { player: this.player, videojs, video })
|
this.peertubePlugin.getPluginsManager().runHook('action:embed.player.loaded', undefined, { player: this.player, videojs, video })
|
||||||
|
|
||||||
|
if (video.isLive) {
|
||||||
|
this.liveManager.displayInfoAndListenForChanges({
|
||||||
|
video,
|
||||||
|
translations,
|
||||||
|
onPublishedVideo: () => {
|
||||||
|
this.liveManager.stopListeningForChanges(video)
|
||||||
|
this.loadVideoAndBuildPlayer(video.uuid)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetPlayerElement () {
|
private resetPlayerElement () {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './auth-http'
|
export * from './auth-http'
|
||||||
export * from './peertube-plugin'
|
export * from './peertube-plugin'
|
||||||
|
export * from './live-manager'
|
||||||
export * from './player-html'
|
export * from './player-html'
|
||||||
export * from './player-manager-options'
|
export * from './player-manager-options'
|
||||||
export * from './playlist-fetcher'
|
export * from './playlist-fetcher'
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Socket } from 'socket.io-client'
|
||||||
|
import { LiveVideoEventPayload, VideoDetails, VideoState } from '../../../../../shared/models'
|
||||||
|
import { PlayerHTML } from './player-html'
|
||||||
|
import { Translations } from './translations'
|
||||||
|
|
||||||
|
export class LiveManager {
|
||||||
|
private liveSocket: Socket
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private readonly playerHTML: PlayerHTML
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async displayInfoAndListenForChanges (options: {
|
||||||
|
video: VideoDetails
|
||||||
|
translations: Translations
|
||||||
|
onPublishedVideo: () => any
|
||||||
|
}) {
|
||||||
|
const { video, onPublishedVideo } = options
|
||||||
|
|
||||||
|
this.displayAppropriateInfo(options)
|
||||||
|
|
||||||
|
if (!this.liveSocket) {
|
||||||
|
const io = (await import('socket.io-client')).io
|
||||||
|
this.liveSocket = io(window.location.origin + '/live-videos')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.liveSocket.on('state-change', (payload: LiveVideoEventPayload) => {
|
||||||
|
if (payload.state === VideoState.PUBLISHED) {
|
||||||
|
this.playerHTML.removeInformation()
|
||||||
|
onPublishedVideo()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.liveSocket.emit('subscribe', { videoId: video.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
stopListeningForChanges (video: VideoDetails) {
|
||||||
|
this.liveSocket.emit('unsubscribe', { videoId: video.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
private displayAppropriateInfo (options: {
|
||||||
|
video: VideoDetails
|
||||||
|
translations: Translations
|
||||||
|
}) {
|
||||||
|
const { video, translations } = options
|
||||||
|
|
||||||
|
if (video.state.id === VideoState.WAITING_FOR_LIVE) {
|
||||||
|
this.displayWaitingForLiveInfo(translations)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video.state.id === VideoState.LIVE_ENDED) {
|
||||||
|
this.displayEndedLiveInfo(translations)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private displayWaitingForLiveInfo (translations: Translations) {
|
||||||
|
this.playerHTML.displayInformation('This live has not started yet.', translations)
|
||||||
|
}
|
||||||
|
|
||||||
|
private displayEndedLiveInfo (translations: Translations) {
|
||||||
|
this.playerHTML.displayInformation('This live has ended.', translations)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ export class PlayerHTML {
|
||||||
private readonly wrapperElement: HTMLElement
|
private readonly wrapperElement: HTMLElement
|
||||||
|
|
||||||
private playerElement: HTMLVideoElement
|
private playerElement: HTMLVideoElement
|
||||||
|
private informationElement: HTMLDivElement
|
||||||
|
|
||||||
constructor (private readonly videoWrapperId: string) {
|
constructor (private readonly videoWrapperId: string) {
|
||||||
this.wrapperElement = document.getElementById(this.videoWrapperId)
|
this.wrapperElement = document.getElementById(this.videoWrapperId)
|
||||||
|
@ -66,6 +67,20 @@ export class PlayerHTML {
|
||||||
placeholder.style.display = 'none'
|
placeholder.style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
displayInformation (text: string, translations: Translations) {
|
||||||
|
if (this.informationElement) this.removeInformation()
|
||||||
|
|
||||||
|
this.informationElement = document.createElement('div')
|
||||||
|
this.informationElement.className = 'player-information'
|
||||||
|
this.informationElement.innerText = peertubeTranslate(text, translations)
|
||||||
|
|
||||||
|
document.body.appendChild(this.informationElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeInformation () {
|
||||||
|
this.removeElement(this.informationElement)
|
||||||
|
}
|
||||||
|
|
||||||
private getPlaceholderElement () {
|
private getPlaceholderElement () {
|
||||||
return document.getElementById('placeholder-preview')
|
return document.getElementById('placeholder-preview')
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import { MAccountActor, MChannelActor } from '../types/models'
|
||||||
import { getActivityStreamDuration } from './activitypub/activity'
|
import { getActivityStreamDuration } from './activitypub/activity'
|
||||||
import { getBiggestActorImage } from './actor-image'
|
import { getBiggestActorImage } from './actor-image'
|
||||||
import { ServerConfigManager } from './server-config-manager'
|
import { ServerConfigManager } from './server-config-manager'
|
||||||
|
import { isTestInstance } from '@server/helpers/core-utils'
|
||||||
|
|
||||||
type Tags = {
|
type Tags = {
|
||||||
ogType: string
|
ogType: string
|
||||||
|
@ -232,7 +233,10 @@ class ClientHtml {
|
||||||
static async getEmbedHTML () {
|
static async getEmbedHTML () {
|
||||||
const path = ClientHtml.getEmbedPath()
|
const path = ClientHtml.getEmbedPath()
|
||||||
|
|
||||||
if (ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
|
// Disable HTML cache in dev mode because webpack can regenerate JS files
|
||||||
|
if (!isTestInstance() && ClientHtml.htmlCache[path]) {
|
||||||
|
return ClientHtml.htmlCache[path]
|
||||||
|
}
|
||||||
|
|
||||||
const buffer = await readFile(path)
|
const buffer = await readFile(path)
|
||||||
const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig()
|
const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig()
|
||||||
|
|
Loading…
Reference in New Issue