Support storyboards in embed

pull/5870/head
Chocobozzz 2023-06-05 11:13:38 +02:00
parent 52807a075f
commit 638a295021
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
3 changed files with 53 additions and 8 deletions

View File

@ -1,6 +1,7 @@
import './embed.scss' import './embed.scss'
import '../../assets/player/shared/dock/peertube-dock-component' import '../../assets/player/shared/dock/peertube-dock-component'
import '../../assets/player/shared/dock/peertube-dock-plugin' import '../../assets/player/shared/dock/peertube-dock-plugin'
import { PeerTubeServerError } from 'src/types'
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 { import {
@ -27,7 +28,6 @@ import {
VideoFetcher VideoFetcher
} from './shared' } from './shared'
import { PlayerHTML } from './shared/player-html' import { PlayerHTML } from './shared/player-html'
import { PeerTubeServerError } from 'src/types'
export class PeerTubeEmbed { export class PeerTubeEmbed {
player: videojs.Player player: videojs.Player
@ -188,9 +188,13 @@ export class PeerTubeEmbed {
const { uuid, autoplayFromPreviousVideo, forceAutoplay } = options const { uuid, autoplayFromPreviousVideo, forceAutoplay } = options
try { try {
const { videoResponse, captionsPromise } = await this.videoFetcher.loadVideo({ videoId: uuid, videoPassword: this.videoPassword }) const {
videoResponse,
captionsPromise,
storyboardsPromise
} = await this.videoFetcher.loadVideo({ videoId: uuid, videoPassword: this.videoPassword })
return this.buildVideoPlayer({ videoResponse, captionsPromise, autoplayFromPreviousVideo, forceAutoplay }) return this.buildVideoPlayer({ videoResponse, captionsPromise, storyboardsPromise, autoplayFromPreviousVideo, forceAutoplay })
} catch (err) { } catch (err) {
if (await this.handlePasswordError(err)) this.loadVideoAndBuildPlayer({ ...options }) if (await this.handlePasswordError(err)) this.loadVideoAndBuildPlayer({ ...options })
@ -200,11 +204,12 @@ export class PeerTubeEmbed {
private async buildVideoPlayer (options: { private async buildVideoPlayer (options: {
videoResponse: Response videoResponse: Response
storyboardsPromise: Promise<Response>
captionsPromise: Promise<Response> captionsPromise: Promise<Response>
autoplayFromPreviousVideo: boolean autoplayFromPreviousVideo: boolean
forceAutoplay: boolean forceAutoplay: boolean
}) { }) {
const { videoResponse, captionsPromise, autoplayFromPreviousVideo, forceAutoplay } = options const { videoResponse, captionsPromise, storyboardsPromise, autoplayFromPreviousVideo, forceAutoplay } = options
this.resetPlayerElement() this.resetPlayerElement()
@ -226,10 +231,17 @@ export class PeerTubeEmbed {
return { live, video: videoInfo, videoFileToken } return { live, video: videoInfo, videoFileToken }
}) })
const [ { video, live, videoFileToken }, translations, captionsResponse, PeertubePlayerManagerModule ] = await Promise.all([ const [
{ video, live, videoFileToken },
translations,
captionsResponse,
storyboardsResponse,
PeertubePlayerManagerModule
] = await Promise.all([
videoInfoPromise, videoInfoPromise,
this.translationsPromise, this.translationsPromise,
captionsPromise, captionsPromise,
storyboardsPromise,
this.PeertubePlayerManagerModulePromise this.PeertubePlayerManagerModulePromise
]) ])
@ -244,6 +256,8 @@ export class PeerTubeEmbed {
translations, translations,
serverConfig: this.config, serverConfig: this.config,
storyboardsResponse,
authorizationHeader: () => this.http.getHeaderTokenValue(), authorizationHeader: () => this.http.getHeaderTokenValue(),
videoFileToken: () => videoFileToken, videoFileToken: () => videoFileToken,
videoPassword: () => this.videoPassword, videoPassword: () => this.videoPassword,

View File

@ -2,6 +2,7 @@ import { peertubeTranslate } from '../../../../../shared/core-utils/i18n'
import { import {
HTMLServerConfig, HTMLServerConfig,
LiveVideo, LiveVideo,
Storyboard,
Video, Video,
VideoCaption, VideoCaption,
VideoDetails, VideoDetails,
@ -155,6 +156,9 @@ export class PlayerManagerOptions {
async getPlayerOptions (options: { async getPlayerOptions (options: {
video: VideoDetails video: VideoDetails
captionsResponse: Response captionsResponse: Response
storyboardsResponse: Response
live?: LiveVideo live?: LiveVideo
forceAutoplay: boolean forceAutoplay: boolean
@ -187,11 +191,15 @@ export class PlayerManagerOptions {
forceAutoplay, forceAutoplay,
playlistTracker, playlistTracker,
live, live,
storyboardsResponse,
authorizationHeader, authorizationHeader,
serverConfig serverConfig
} = options } = options
const videoCaptions = await this.buildCaptions(captionsResponse, translations) const [ videoCaptions, storyboard ] = await Promise.all([
this.buildCaptions(captionsResponse, translations),
this.buildStoryboard(storyboardsResponse)
])
const playerOptions: PeertubePlayerManagerOptions = { const playerOptions: PeertubePlayerManagerOptions = {
common: { common: {
@ -210,6 +218,8 @@ export class PlayerManagerOptions {
captions: videoCaptions.length !== 0, captions: videoCaptions.length !== 0,
subtitle: this.subtitle, subtitle: this.subtitle,
storyboard,
startTime: playlistTracker startTime: playlistTracker
? playlistTracker.getCurrentElement().startTimestamp ? playlistTracker.getCurrentElement().startTimestamp
: this.startTime, : this.startTime,
@ -286,6 +296,18 @@ export class PlayerManagerOptions {
} }
} }
private async buildStoryboard (storyboardsResponse: Response) {
const { storyboards } = await storyboardsResponse.json() as { storyboards: Storyboard[] }
if (!storyboards || storyboards.length === 0) return undefined
return {
url: window.location.origin + storyboards[0].storyboardPath,
height: storyboards[0].spriteHeight,
width: storyboards[0].spriteWidth,
interval: storyboards[0].spriteDuration
}
}
private buildPlaylistOptions (options: { private buildPlaylistOptions (options: {
playlistTracker?: PlaylistTracker playlistTracker?: PlaylistTracker
playNextPlaylistVideo?: () => any playNextPlaylistVideo?: () => any

View File

@ -1,5 +1,5 @@
import { PeerTubeServerError } from '../../../types' import { PeerTubeServerError } from '../../../types'
import { HttpStatusCode, LiveVideo, VideoDetails, VideoToken } from '../../../../../shared/models' import { HttpStatusCode, LiveVideo, Storyboard, VideoDetails, VideoToken } from '../../../../../shared/models'
import { logger } from '../../../root-helpers' import { logger } from '../../../root-helpers'
import { AuthHTTP } from './auth-http' import { AuthHTTP } from './auth-http'
@ -36,8 +36,9 @@ export class VideoFetcher {
} }
const captionsPromise = this.loadVideoCaptions({ videoId, videoPassword }) const captionsPromise = this.loadVideoCaptions({ videoId, videoPassword })
const storyboardsPromise = this.loadStoryboards(videoId)
return { captionsPromise, videoResponse } return { captionsPromise, storyboardsPromise, videoResponse }
} }
loadLive (video: VideoDetails) { loadLive (video: VideoDetails) {
@ -71,6 +72,14 @@ export class VideoFetcher {
return window.location.origin + '/api/v1/videos/live/' + videoId return window.location.origin + '/api/v1/videos/live/' + videoId
} }
private loadStoryboards (videoUUID: string): Promise<Response> {
return this.http.fetch(this.getStoryboardsUrl(videoUUID), { optionalAuth: true })
}
private getStoryboardsUrl (videoId: string) {
return window.location.origin + '/api/v1/videos/' + videoId + '/storyboards'
}
private getVideoTokenUrl (id: string) { private getVideoTokenUrl (id: string) {
return this.getVideoUrl(id) + '/token' return this.getVideoUrl(id) + '/token'
} }