aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/server-commands/videos/live-command.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-10-04 10:03:17 +0200
committerChocobozzz <me@florianbigard.com>2022-10-04 10:03:17 +0200
commitcfd57d2ca0bb058087f7dc90fcc3e8442b0288e1 (patch)
treedc899a1504ecac588e5580553e02571e0f5d7e4b /shared/server-commands/videos/live-command.ts
parent9c0cdc5047918b959ebd5e075ddad81eb7fb93f0 (diff)
downloadPeerTube-cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1.tar.gz
PeerTube-cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1.tar.zst
PeerTube-cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1.zip
Live supports object storage
* Sync live files (segments, master playlist, resolution playlist, segment sha file) into object storage * Automatically delete them when the live ends * Segment sha file is now a file on disk, and not stored in memory anymore
Diffstat (limited to 'shared/server-commands/videos/live-command.ts')
-rw-r--r--shared/server-commands/videos/live-command.ts60
1 files changed, 50 insertions, 10 deletions
diff --git a/shared/server-commands/videos/live-command.ts b/shared/server-commands/videos/live-command.ts
index d804fd883..defae95fb 100644
--- a/shared/server-commands/videos/live-command.ts
+++ b/shared/server-commands/videos/live-command.ts
@@ -15,6 +15,7 @@ import {
15 VideoState 15 VideoState
16} from '@shared/models' 16} from '@shared/models'
17import { unwrapBody } from '../requests' 17import { unwrapBody } from '../requests'
18import { ObjectStorageCommand } from '../server'
18import { AbstractCommand, OverrideCommandOptions } from '../shared' 19import { AbstractCommand, OverrideCommandOptions } from '../shared'
19import { sendRTMPStream, testFfmpegStreamError } from './live' 20import { sendRTMPStream, testFfmpegStreamError } from './live'
20 21
@@ -34,6 +35,8 @@ export class LiveCommand extends AbstractCommand {
34 }) 35 })
35 } 36 }
36 37
38 // ---------------------------------------------------------------------------
39
37 listSessions (options: OverrideCommandOptions & { 40 listSessions (options: OverrideCommandOptions & {
38 videoId: number | string 41 videoId: number | string
39 }) { 42 }) {
@@ -70,6 +73,8 @@ export class LiveCommand extends AbstractCommand {
70 }) 73 })
71 } 74 }
72 75
76 // ---------------------------------------------------------------------------
77
73 update (options: OverrideCommandOptions & { 78 update (options: OverrideCommandOptions & {
74 videoId: number | string 79 videoId: number | string
75 fields: LiveVideoUpdate 80 fields: LiveVideoUpdate
@@ -110,6 +115,8 @@ export class LiveCommand extends AbstractCommand {
110 return body.video 115 return body.video
111 } 116 }
112 117
118 // ---------------------------------------------------------------------------
119
113 async sendRTMPStreamInVideo (options: OverrideCommandOptions & { 120 async sendRTMPStreamInVideo (options: OverrideCommandOptions & {
114 videoId: number | string 121 videoId: number | string
115 fixtureName?: string 122 fixtureName?: string
@@ -130,6 +137,8 @@ export class LiveCommand extends AbstractCommand {
130 return testFfmpegStreamError(command, options.shouldHaveError) 137 return testFfmpegStreamError(command, options.shouldHaveError)
131 } 138 }
132 139
140 // ---------------------------------------------------------------------------
141
133 waitUntilPublished (options: OverrideCommandOptions & { 142 waitUntilPublished (options: OverrideCommandOptions & {
134 videoId: number | string 143 videoId: number | string
135 }) { 144 }) {
@@ -163,15 +172,34 @@ export class LiveCommand extends AbstractCommand {
163 return this.server.servers.waitUntilLog(`${videoUUID}/${segmentName}`, totalSessions * 2, false) 172 return this.server.servers.waitUntilLog(`${videoUUID}/${segmentName}`, totalSessions * 2, false)
164 } 173 }
165 174
166 getSegment (options: OverrideCommandOptions & { 175 async waitUntilReplacedByReplay (options: OverrideCommandOptions & {
176 videoId: number | string
177 }) {
178 let video: VideoDetails
179
180 do {
181 video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
182
183 await wait(500)
184 } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED)
185 }
186
187 // ---------------------------------------------------------------------------
188
189 getSegmentFile (options: OverrideCommandOptions & {
167 videoUUID: string 190 videoUUID: string
168 playlistNumber: number 191 playlistNumber: number
169 segment: number 192 segment: number
193 objectStorage?: boolean // default false
170 }) { 194 }) {
171 const { playlistNumber, segment, videoUUID } = options 195 const { playlistNumber, segment, videoUUID, objectStorage = false } = options
172 196
173 const segmentName = `${playlistNumber}-00000${segment}.ts` 197 const segmentName = `${playlistNumber}-00000${segment}.ts`
174 const url = `${this.server.url}/static/streaming-playlists/hls/${videoUUID}/${segmentName}` 198 const baseUrl = objectStorage
199 ? ObjectStorageCommand.getPlaylistBaseUrl()
200 : `${this.server.url}/static/streaming-playlists/hls`
201
202 const url = `${baseUrl}/${videoUUID}/${segmentName}`
175 203
176 return this.getRawRequest({ 204 return this.getRawRequest({
177 ...options, 205 ...options,
@@ -182,18 +210,30 @@ export class LiveCommand extends AbstractCommand {
182 }) 210 })
183 } 211 }
184 212
185 async waitUntilReplacedByReplay (options: OverrideCommandOptions & { 213 getPlaylistFile (options: OverrideCommandOptions & {
186 videoId: number | string 214 videoUUID: string
215 playlistName: string
216 objectStorage?: boolean // default false
187 }) { 217 }) {
188 let video: VideoDetails 218 const { playlistName, videoUUID, objectStorage = false } = options
189 219
190 do { 220 const baseUrl = objectStorage
191 video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId }) 221 ? ObjectStorageCommand.getPlaylistBaseUrl()
222 : `${this.server.url}/static/streaming-playlists/hls`
192 223
193 await wait(500) 224 const url = `${baseUrl}/${videoUUID}/${playlistName}`
194 } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED) 225
226 return this.getRawRequest({
227 ...options,
228
229 url,
230 implicitToken: false,
231 defaultExpectedStatus: HttpStatusCode.OK_200
232 })
195 } 233 }
196 234
235 // ---------------------------------------------------------------------------
236
197 async countPlaylists (options: OverrideCommandOptions & { 237 async countPlaylists (options: OverrideCommandOptions & {
198 videoUUID: string 238 videoUUID: string
199 }) { 239 }) {