diff options
Diffstat (limited to 'shared/server-commands/videos')
-rw-r--r-- | shared/server-commands/videos/live-command.ts | 99 | ||||
-rw-r--r-- | shared/server-commands/videos/live.ts | 2 | ||||
-rw-r--r-- | shared/server-commands/videos/streaming-playlists-command.ts | 38 |
3 files changed, 115 insertions, 24 deletions
diff --git a/shared/server-commands/videos/live-command.ts b/shared/server-commands/videos/live-command.ts index d804fd883..b163f7189 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' |
17 | import { unwrapBody } from '../requests' | 17 | import { unwrapBody } from '../requests' |
18 | import { ObjectStorageCommand, PeerTubeServer } from '../server' | ||
18 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | 19 | import { AbstractCommand, OverrideCommandOptions } from '../shared' |
19 | import { sendRTMPStream, testFfmpegStreamError } from './live' | 20 | import { 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 | }) { |
@@ -151,27 +160,77 @@ export class LiveCommand extends AbstractCommand { | |||
151 | return this.waitUntilState({ videoId, state: VideoState.LIVE_ENDED }) | 160 | return this.waitUntilState({ videoId, state: VideoState.LIVE_ENDED }) |
152 | } | 161 | } |
153 | 162 | ||
154 | waitUntilSegmentGeneration (options: OverrideCommandOptions & { | 163 | async waitUntilSegmentGeneration (options: OverrideCommandOptions & { |
164 | server: PeerTubeServer | ||
155 | videoUUID: string | 165 | videoUUID: string |
156 | playlistNumber: number | 166 | playlistNumber: number |
157 | segment: number | 167 | segment: number |
158 | totalSessions?: number | 168 | objectStorage: boolean |
159 | }) { | 169 | }) { |
160 | const { playlistNumber, segment, videoUUID, totalSessions = 1 } = options | 170 | const { server, objectStorage, playlistNumber, segment, videoUUID } = options |
171 | |||
161 | const segmentName = `${playlistNumber}-00000${segment}.ts` | 172 | const segmentName = `${playlistNumber}-00000${segment}.ts` |
173 | const baseUrl = objectStorage | ||
174 | ? ObjectStorageCommand.getPlaylistBaseUrl() + 'hls' | ||
175 | : server.url + '/static/streaming-playlists/hls' | ||
176 | |||
177 | let error = true | ||
178 | |||
179 | while (error) { | ||
180 | try { | ||
181 | await this.getRawRequest({ | ||
182 | ...options, | ||
183 | |||
184 | url: `${baseUrl}/${videoUUID}/${segmentName}`, | ||
185 | implicitToken: false, | ||
186 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
187 | }) | ||
188 | |||
189 | const video = await server.videos.get({ id: videoUUID }) | ||
190 | const hlsPlaylist = video.streamingPlaylists[0] | ||
191 | |||
192 | const shaBody = await server.streamingPlaylists.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url }) | ||
193 | |||
194 | if (!shaBody[segmentName]) { | ||
195 | throw new Error('Segment SHA does not exist') | ||
196 | } | ||
197 | |||
198 | error = false | ||
199 | } catch { | ||
200 | error = true | ||
201 | await wait(100) | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
206 | async waitUntilReplacedByReplay (options: OverrideCommandOptions & { | ||
207 | videoId: number | string | ||
208 | }) { | ||
209 | let video: VideoDetails | ||
210 | |||
211 | do { | ||
212 | video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId }) | ||
162 | 213 | ||
163 | return this.server.servers.waitUntilLog(`${videoUUID}/${segmentName}`, totalSessions * 2, false) | 214 | await wait(500) |
215 | } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED) | ||
164 | } | 216 | } |
165 | 217 | ||
166 | getSegment (options: OverrideCommandOptions & { | 218 | // --------------------------------------------------------------------------- |
219 | |||
220 | getSegmentFile (options: OverrideCommandOptions & { | ||
167 | videoUUID: string | 221 | videoUUID: string |
168 | playlistNumber: number | 222 | playlistNumber: number |
169 | segment: number | 223 | segment: number |
224 | objectStorage?: boolean // default false | ||
170 | }) { | 225 | }) { |
171 | const { playlistNumber, segment, videoUUID } = options | 226 | const { playlistNumber, segment, videoUUID, objectStorage = false } = options |
172 | 227 | ||
173 | const segmentName = `${playlistNumber}-00000${segment}.ts` | 228 | const segmentName = `${playlistNumber}-00000${segment}.ts` |
174 | const url = `${this.server.url}/static/streaming-playlists/hls/${videoUUID}/${segmentName}` | 229 | const baseUrl = objectStorage |
230 | ? ObjectStorageCommand.getPlaylistBaseUrl() | ||
231 | : `${this.server.url}/static/streaming-playlists/hls` | ||
232 | |||
233 | const url = `${baseUrl}/${videoUUID}/${segmentName}` | ||
175 | 234 | ||
176 | return this.getRawRequest({ | 235 | return this.getRawRequest({ |
177 | ...options, | 236 | ...options, |
@@ -182,18 +241,30 @@ export class LiveCommand extends AbstractCommand { | |||
182 | }) | 241 | }) |
183 | } | 242 | } |
184 | 243 | ||
185 | async waitUntilReplacedByReplay (options: OverrideCommandOptions & { | 244 | getPlaylistFile (options: OverrideCommandOptions & { |
186 | videoId: number | string | 245 | videoUUID: string |
246 | playlistName: string | ||
247 | objectStorage?: boolean // default false | ||
187 | }) { | 248 | }) { |
188 | let video: VideoDetails | 249 | const { playlistName, videoUUID, objectStorage = false } = options |
189 | 250 | ||
190 | do { | 251 | const baseUrl = objectStorage |
191 | video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId }) | 252 | ? ObjectStorageCommand.getPlaylistBaseUrl() |
253 | : `${this.server.url}/static/streaming-playlists/hls` | ||
192 | 254 | ||
193 | await wait(500) | 255 | const url = `${baseUrl}/${videoUUID}/${playlistName}` |
194 | } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED) | 256 | |
257 | return this.getRawRequest({ | ||
258 | ...options, | ||
259 | |||
260 | url, | ||
261 | implicitToken: false, | ||
262 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
263 | }) | ||
195 | } | 264 | } |
196 | 265 | ||
266 | // --------------------------------------------------------------------------- | ||
267 | |||
197 | async countPlaylists (options: OverrideCommandOptions & { | 268 | async countPlaylists (options: OverrideCommandOptions & { |
198 | videoUUID: string | 269 | videoUUID: string |
199 | }) { | 270 | }) { |
diff --git a/shared/server-commands/videos/live.ts b/shared/server-commands/videos/live.ts index 6f180b05f..0d9c32aab 100644 --- a/shared/server-commands/videos/live.ts +++ b/shared/server-commands/videos/live.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg' | 1 | import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg' |
2 | import { buildAbsoluteFixturePath, wait } from '@shared/core-utils' | 2 | import { buildAbsoluteFixturePath, wait } from '@shared/core-utils' |
3 | import { PeerTubeServer } from '../server/server' | ||
4 | import { VideoDetails, VideoInclude } from '@shared/models' | 3 | import { VideoDetails, VideoInclude } from '@shared/models' |
4 | import { PeerTubeServer } from '../server/server' | ||
5 | 5 | ||
6 | function sendRTMPStream (options: { | 6 | function sendRTMPStream (options: { |
7 | rtmpBaseUrl: string | 7 | rtmpBaseUrl: string |
diff --git a/shared/server-commands/videos/streaming-playlists-command.ts b/shared/server-commands/videos/streaming-playlists-command.ts index 5d40d35cb..25e446e72 100644 --- a/shared/server-commands/videos/streaming-playlists-command.ts +++ b/shared/server-commands/videos/streaming-playlists-command.ts | |||
@@ -1,22 +1,42 @@ | |||
1 | import { wait } from '@shared/core-utils' | ||
1 | import { HttpStatusCode } from '@shared/models' | 2 | import { HttpStatusCode } from '@shared/models' |
2 | import { unwrapBody, unwrapTextOrDecode, unwrapBodyOrDecodeToJSON } from '../requests' | 3 | import { unwrapBody, unwrapBodyOrDecodeToJSON, unwrapTextOrDecode } from '../requests' |
3 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | 4 | import { AbstractCommand, OverrideCommandOptions } from '../shared' |
4 | 5 | ||
5 | export class StreamingPlaylistsCommand extends AbstractCommand { | 6 | export class StreamingPlaylistsCommand extends AbstractCommand { |
6 | 7 | ||
7 | get (options: OverrideCommandOptions & { | 8 | async get (options: OverrideCommandOptions & { |
8 | url: string | 9 | url: string |
10 | withRetry?: boolean // default false | ||
11 | currentRetry?: number | ||
9 | }) { | 12 | }) { |
10 | return unwrapTextOrDecode(this.getRawRequest({ | 13 | const { withRetry, currentRetry = 1 } = options |
11 | ...options, | ||
12 | 14 | ||
13 | url: options.url, | 15 | try { |
14 | implicitToken: false, | 16 | const result = await unwrapTextOrDecode(this.getRawRequest({ |
15 | defaultExpectedStatus: HttpStatusCode.OK_200 | 17 | ...options, |
16 | })) | 18 | |
19 | url: options.url, | ||
20 | implicitToken: false, | ||
21 | defaultExpectedStatus: HttpStatusCode.OK_200 | ||
22 | })) | ||
23 | |||
24 | return result | ||
25 | } catch (err) { | ||
26 | if (!withRetry || currentRetry > 5) throw err | ||
27 | |||
28 | await wait(100) | ||
29 | |||
30 | return this.get({ | ||
31 | ...options, | ||
32 | |||
33 | withRetry, | ||
34 | currentRetry: currentRetry + 1 | ||
35 | }) | ||
36 | } | ||
17 | } | 37 | } |
18 | 38 | ||
19 | getSegment (options: OverrideCommandOptions & { | 39 | getFragmentedSegment (options: OverrideCommandOptions & { |
20 | url: string | 40 | url: string |
21 | range?: string | 41 | range?: string |
22 | }) { | 42 | }) { |