From 1151f5210c0e7665ec6714e73261f299e6fe757b Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 6 May 2020 11:54:33 +0200 Subject: [PATCH] Add ability to update embed captions --- .../assets/player/peertube-videojs-typings.ts | 2 +- client/src/standalone/player/definitions.ts | 7 ++++ client/src/standalone/player/player.ts | 17 +++++++++- client/src/standalone/videos/embed-api.ts | 25 ++++++++++++++- client/src/standalone/videos/test-embed.html | 6 ++++ client/src/standalone/videos/test-embed.ts | 32 ++++++++++++++++++- support/doc/api/embeds.md | 18 ++++++++--- 7 files changed, 98 insertions(+), 9 deletions(-) diff --git a/client/src/assets/player/peertube-videojs-typings.ts b/client/src/assets/player/peertube-videojs-typings.ts index a4e4c580c..cb7d6f6b4 100644 --- a/client/src/assets/player/peertube-videojs-typings.ts +++ b/client/src/assets/player/peertube-videojs-typings.ts @@ -38,7 +38,7 @@ declare module 'video.js' { textTracks (): TextTrackList & { on: Function - tracks_: { kind: string, mode: string, language: string }[] + tracks_: (TextTrack & { id: string, label: string, src: string })[] } audioTracks (): AudioTrackList diff --git a/client/src/standalone/player/definitions.ts b/client/src/standalone/player/definitions.ts index 9fe903260..cc5203ed5 100644 --- a/client/src/standalone/player/definitions.ts +++ b/client/src/standalone/player/definitions.ts @@ -16,3 +16,10 @@ export interface PeerTubeResolution { src?: string width?: number } + +export type PeerTubeTextTrack = { + id: string + label: string + src: string + mode: 'showing' | 'disabled' +} diff --git a/client/src/standalone/player/player.ts b/client/src/standalone/player/player.ts index 71c412950..119f5e035 100644 --- a/client/src/standalone/player/player.ts +++ b/client/src/standalone/player/player.ts @@ -1,6 +1,6 @@ import * as Channel from 'jschannel' +import { EventHandler, PeerTubeResolution, PeerTubeTextTrack, PlayerEventType } from './definitions' import { EventRegistrar } from './events' -import { EventHandler, PlayerEventType, PeerTubeResolution } from './definitions' const PASSTHROUGH_EVENTS = [ 'pause', @@ -104,6 +104,21 @@ export class PeerTubePlayer { return this.sendMessage('getVolume') } + /** + * Tell the embed to change the current caption + * @param value Caption id + */ + async setCaption (value: string) { + await this.sendMessage('setCaption', value) + } + + /** + * Get video captions + */ + async getCaptions (): Promise { + return this.sendMessage('getCaptions') + } + /** * Tell the embed to seek to a specific position (in seconds) * @param seconds diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts index 194465d4a..a9263555d 100644 --- a/client/src/standalone/videos/embed-api.ts +++ b/client/src/standalone/videos/embed-api.ts @@ -1,7 +1,7 @@ import './embed.scss' import * as Channel from 'jschannel' -import { PeerTubeResolution } from '../player/definitions' +import { PeerTubeResolution, PeerTubeTextTrack } from '../player/definitions' import { PeerTubeEmbed } from './embed' /** @@ -44,6 +44,9 @@ export class PeerTubeEmbedApi { channel.bind('setResolution', (txn, resolutionId) => this.setResolution(resolutionId)) channel.bind('getResolutions', (txn, params) => this.resolutions) + channel.bind('getCaptions', (txn, params) => this.getCaptions()) + channel.bind('setCaption', (txn, id) => this.setCaption(id)), + channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate)) channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate()) channel.bind('getPlaybackRates', (txn, params) => this.embed.player.options_.playbackRates) @@ -71,6 +74,26 @@ export class PeerTubeEmbedApi { this.embed.player.p2pMediaLoader().getHLSJS().nextLevel = resolutionId } + private getCaptions (): PeerTubeTextTrack[] { + return this.embed.player.textTracks().tracks_.map(t => { + return { + id: t.id, + src: t.src, + label: t.label, + mode: t.mode as any + } + }) + } + + private setCaption (id: string) { + const tracks = this.embed.player.textTracks().tracks_ + + for (const track of tracks) { + if (track.id === id) track.mode = 'showing' + else track.mode = 'disabled' + } + } + /** * Let the host know that we're ready to go! */ diff --git a/client/src/standalone/videos/test-embed.html b/client/src/standalone/videos/test-embed.html index 20cdbdc5f..9e1d6fc61 100644 --- a/client/src/standalone/videos/test-embed.html +++ b/client/src/standalone/videos/test-embed.html @@ -37,6 +37,12 @@
+
+ Captions: +
+
+
+
Rates:
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts index a4b54782c..24cb62230 100644 --- a/client/src/standalone/videos/test-embed.ts +++ b/client/src/standalone/videos/test-embed.ts @@ -1,6 +1,6 @@ import './test-embed.scss' import { PeerTubePlayer } from '../player/player' -import { PeerTubeResolution, PlayerEventType } from '../player/definitions' +import { PeerTubeResolution, PlayerEventType, PeerTubeTextTrack } from '../player/definitions' window.addEventListener('load', async () => { const urlParts = window.location.href.split('/') @@ -67,6 +67,36 @@ window.addEventListener('load', async () => { updateRates() }) + const updateCaptions = async () => { + const captions = await player.getCaptions() + + const captionEl = document.querySelector('#caption-list') + captionEl.innerHTML = '' + + captions.forEach(c => { + console.log(c) + + if (c.mode === 'showing') { + const itemEl = document.createElement('strong') + itemEl.innerText = `${c.label} (active)` + itemEl.style.display = 'block' + captionEl.appendChild(itemEl) + } else { + const itemEl = document.createElement('a') + itemEl.href = 'javascript:;' + itemEl.innerText = c.label + itemEl.addEventListener('click', () => { + player.setCaption(c.id) + updateCaptions() + }) + itemEl.style.display = 'block' + captionEl.appendChild(itemEl) + } + }) + } + + updateCaptions() + const updateResolutions = ((resolutions: PeerTubeResolution[]) => { const resolutionListEl = document.querySelector('#resolution-list') resolutionListEl.innerHTML = '' diff --git a/support/doc/api/embeds.md b/support/doc/api/embeds.md index 7085b4b0a..e3df35efc 100644 --- a/support/doc/api/embeds.md +++ b/support/doc/api/embeds.md @@ -4,8 +4,8 @@ PeerTube lets you embed videos and programmatically control their playback. This ## Playground -Any PeerTube embed URL (ie `https://my-instance.example.com/videos/embed/52a10666-3a18-4e73-93da-e8d3c12c305a`) can be viewed as an embedding playground which -allows you to test various aspects of PeerTube embeds. Simply replace `/embed` with `/test-embed` and visit the URL in a browser. +Any PeerTube embed URL (ie `https://my-instance.example.com/videos/embed/52a10666-3a18-4e73-93da-e8d3c12c305a`) can be viewed as an embedding playground which +allows you to test various aspects of PeerTube embeds. Simply replace `/embed` with `/test-embed` and visit the URL in a browser. For instance, the playground URL for the above embed URL is `https://my-instance.example.com/videos/test-embed/52a10666-3a18-4e73-93da-e8d3c12c305a`. ## Quick Start @@ -95,11 +95,11 @@ Get the available playback rates, where `1` represents normal speed, `0.5` is ha Get the current playback rate. See `getPlaybackRates()` for more information. -## `setPlaybackRate(rate : number) : Promise` +## `setPlaybackRate(rate: number) : Promise` Set the current playback rate. The passed rate should be a value as returned by `getPlaybackRates()`. -## `setVolume(factor : number) : Promise` +## `setVolume(factor: number) : Promise` Set the playback volume. Value should be between `0` and `1`. @@ -107,13 +107,21 @@ Set the playback volume. Value should be between `0` and `1`. Get the playback volume. Returns a value between `0` and `1`. +## `setCaption(id: string) : Promise` + +Update current caption using the caption id. + +## `getCaptions(): Promise<{ id: string, label: string, src: string, mode: 'disabled' | 'showing' }>` + +Get video captions. + # Events You can subscribe to events by using `addEventListener()`. See above for details. ## Event `playbackStatusUpdate` -Fired every half second to provide the current status of playback. +Fired every half second to provide the current status of playback. The parameter of the callback will resemble: ```json