aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/standalone/player/player.ts21
-rw-r--r--client/src/standalone/videos/embed-api.ts4
-rw-r--r--client/src/standalone/videos/embed.ts54
-rw-r--r--client/src/standalone/videos/test-embed.html7
-rw-r--r--client/src/standalone/videos/test-embed.ts14
-rw-r--r--server/controllers/client.ts9
-rw-r--r--support/doc/api/embeds.md12
7 files changed, 90 insertions, 31 deletions
diff --git a/client/src/standalone/player/player.ts b/client/src/standalone/player/player.ts
index 119f5e035..9776fda12 100644
--- a/client/src/standalone/player/player.ts
+++ b/client/src/standalone/player/player.ts
@@ -170,6 +170,27 @@ export class PeerTubePlayer {
170 await this.sendMessage('setPlaybackRate', rate) 170 await this.sendMessage('setPlaybackRate', rate)
171 } 171 }
172 172
173 /**
174 * Play next video in playlist
175 */
176 async playNextVideo () {
177 await this.sendMessage('playNextVideo')
178 }
179
180 /**
181 * Play previous video in playlist
182 */
183 async playPreviousVideo () {
184 await this.sendMessage('playPreviousVideo')
185 }
186
187 /**
188 * Get video position currently played (starts from 1)
189 */
190 async getCurrentPosition () {
191 return this.sendMessage<void, number>('getCurrentPosition')
192 }
193
173 private constructChannel () { 194 private constructChannel () {
174 this.channel = Channel.build({ 195 this.channel = Channel.build({
175 window: this.embedElement.contentWindow, 196 window: this.embedElement.contentWindow,
diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts
index efc23a1fc..94e39ec29 100644
--- a/client/src/standalone/videos/embed-api.ts
+++ b/client/src/standalone/videos/embed-api.ts
@@ -50,6 +50,10 @@ export class PeerTubeEmbedApi {
50 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate)) 50 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate))
51 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate()) 51 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate())
52 channel.bind('getPlaybackRates', (txn, params) => this.embed.player.options_.playbackRates) 52 channel.bind('getPlaybackRates', (txn, params) => this.embed.player.options_.playbackRates)
53
54 channel.bind('playNextVideo', (txn, params) => this.embed.playNextVideo())
55 channel.bind('playPreviousVideo', (txn, params) => this.embed.playPreviousVideo())
56 channel.bind('getCurrentPosition', (txn, params) => this.embed.getCurrentPosition())
53 this.channel = channel 57 this.channel = channel
54 } 58 }
55 59
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index 7372c80c6..a7fb087b1 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -211,6 +211,36 @@ export class PeerTubeEmbed {
211 return params.has(name) ? params.get(name) : defaultValue 211 return params.has(name) ? params.get(name) : defaultValue
212 } 212 }
213 213
214 async playNextVideo () {
215 const next = this.getNextPlaylistElement()
216 if (!next) {
217 console.log('Next element not found in playlist.')
218 return
219 }
220
221 this.currentPlaylistElement = next
222
223 return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
224 }
225
226 async playPreviousVideo () {
227 const previous = this.getPreviousPlaylistElement()
228 if (!previous) {
229 console.log('Previous element not found in playlist.')
230 return
231 }
232
233 this.currentPlaylistElement = previous
234
235 await this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
236 }
237
238 getCurrentPosition () {
239 if (!this.currentPlaylistElement) return -1
240
241 return this.currentPlaylistElement.position
242 }
243
214 async init () { 244 async init () {
215 try { 245 try {
216 this.userTokens = Tokens.load() 246 this.userTokens = Tokens.load()
@@ -342,30 +372,6 @@ export class PeerTubeEmbed {
342 }) 372 })
343 } 373 }
344 374
345 private async playNextVideo () {
346 const next = this.getNextPlaylistElement()
347 if (!next) {
348 console.log('Next element not found in playlist.')
349 return
350 }
351
352 this.currentPlaylistElement = next
353
354 return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
355 }
356
357 private async playPreviousVideo () {
358 const previous = this.getPreviousPlaylistElement()
359 if (!previous) {
360 console.log('Previous element not found in playlist.')
361 return
362 }
363
364 this.currentPlaylistElement = previous
365
366 return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
367 }
368
369 private async loadVideoAndBuildPlayer (uuid: string) { 375 private async loadVideoAndBuildPlayer (uuid: string) {
370 const res = await this.loadVideo(uuid) 376 const res = await this.loadVideo(uuid)
371 if (res === undefined) return 377 if (res === undefined) return
diff --git a/client/src/standalone/videos/test-embed.html b/client/src/standalone/videos/test-embed.html
index 9e1d6fc61..2b4918681 100644
--- a/client/src/standalone/videos/test-embed.html
+++ b/client/src/standalone/videos/test-embed.html
@@ -27,6 +27,8 @@
27 <button onclick="player.seek(parseInt(prompt('Enter position to seek to (in seconds)')))">Seek</button> 27 <button onclick="player.seek(parseInt(prompt('Enter position to seek to (in seconds)')))">Seek</button>
28 <button onclick="player.setVolume(0)">Mute</button> 28 <button onclick="player.setVolume(0)">Mute</button>
29 <button onclick="player.setVolume(1)">Unmute</button> 29 <button onclick="player.setVolume(1)">Unmute</button>
30 <button onclick="player.playNextVideo()">Next video</button>
31 <button onclick="player.playPreviousVideo()">Previous video</button>
30 </div> 32 </div>
31 <br/> 33 <br/>
32 34
@@ -52,6 +54,11 @@
52 <legend>Volume</legend> 54 <legend>Volume</legend>
53 <div id="volume"></div> 55 <div id="volume"></div>
54 </fieldset> 56 </fieldset>
57
58 <fieldset>
59 <legend>Playlist position</legend>
60 <div id="playlist-position"></div>
61 </fieldset>
55 </div> 62 </div>
56 63
57 </div> 64 </div>
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts
index 24cb62230..5f8e97562 100644
--- a/client/src/standalone/videos/test-embed.ts
+++ b/client/src/standalone/videos/test-embed.ts
@@ -1,14 +1,19 @@
1import './test-embed.scss' 1import './test-embed.scss'
2import { PeerTubeResolution, PlayerEventType } from '../player/definitions'
2import { PeerTubePlayer } from '../player/player' 3import { PeerTubePlayer } from '../player/player'
3import { PeerTubeResolution, PlayerEventType, PeerTubeTextTrack } from '../player/definitions'
4 4
5window.addEventListener('load', async () => { 5window.addEventListener('load', async () => {
6 const urlParts = window.location.href.split('/') 6 const urlParts = window.location.href.split('/')
7 const lastPart = urlParts[ urlParts.length - 1 ] 7 const lastPart = urlParts[ urlParts.length - 1 ]
8 const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ] 8
9 const isPlaylist = window.location.pathname.startsWith('/video-playlists/')
10
11 const elementId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
9 12
10 const iframe = document.createElement('iframe') 13 const iframe = document.createElement('iframe')
11 iframe.src = `/videos/embed/${videoId}?api=1` 14 iframe.src = isPlaylist
15 ? `/videos/embed/${elementId}?api=1`
16 : `/video-playlists/embed/${elementId}?api=1`
12 17
13 const mainElement = document.querySelector('#host') 18 const mainElement = document.querySelector('#host')
14 mainElement.appendChild(iframe) 19 mainElement.appendChild(iframe)
@@ -32,6 +37,9 @@ window.addEventListener('load', async () => {
32 monitoredEvents.forEach(e => { 37 monitoredEvents.forEach(e => {
33 player.addEventListener(e as PlayerEventType, (param) => console.log(`PLAYER: event '${e}' received`, param)) 38 player.addEventListener(e as PlayerEventType, (param) => console.log(`PLAYER: event '${e}' received`, param))
34 console.log(`PLAYER: now listening for event '${e}'`) 39 console.log(`PLAYER: now listening for event '${e}'`)
40
41 player.getCurrentPosition()
42 .then(position => document.getElementById('playlist-position').innerHTML = position + '')
35 }) 43 })
36 44
37 let playbackRates: number[] = [] 45 let playbackRates: number[] = []
diff --git a/server/controllers/client.ts b/server/controllers/client.ts
index b97c935a5..39a198b59 100644
--- a/server/controllers/client.ts
+++ b/server/controllers/client.ts
@@ -36,10 +36,11 @@ const embedMiddlewares = [
36 36
37clientsRouter.use('/videos/embed', ...embedMiddlewares) 37clientsRouter.use('/videos/embed', ...embedMiddlewares)
38clientsRouter.use('/video-playlists/embed', ...embedMiddlewares) 38clientsRouter.use('/video-playlists/embed', ...embedMiddlewares)
39clientsRouter.use( 39
40 '/videos/test-embed', 40const testEmbedController = (req: express.Request, res: express.Response) => res.sendFile(testEmbedPath)
41 (req: express.Request, res: express.Response) => res.sendFile(testEmbedPath) 41
42) 42clientsRouter.use('/videos/test-embed', testEmbedController)
43clientsRouter.use('/video-playlists/test-embed', testEmbedController)
43 44
44// Static HTML/CSS/JS client files 45// Static HTML/CSS/JS client files
45const staticClientFiles = [ 46const staticClientFiles = [
diff --git a/support/doc/api/embeds.md b/support/doc/api/embeds.md
index e3df35efc..d64615764 100644
--- a/support/doc/api/embeds.md
+++ b/support/doc/api/embeds.md
@@ -115,6 +115,18 @@ Update current caption using the caption id.
115 115
116Get video captions. 116Get video captions.
117 117
118## `playNextVideo(): Promise<void>`
119
120Play next video in playlist.
121
122## `playPreviousVideo(): Promise<void>`
123
124Play previous video in playlist.
125
126## `getCurrentPosition(): Promise<void>`
127
128Get current position in playlist (starts from 1).
129
118# Events 130# Events
119 131
120You can subscribe to events by using `addEventListener()`. See above for details. 132You can subscribe to events by using `addEventListener()`. See above for details.