]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - shared/extra-utils/videos/live-command.ts
Specify if we want to fallback to the server token
[github/Chocobozzz/PeerTube.git] / shared / extra-utils / videos / live-command.ts
CommitLineData
4f219914
C
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { readdir } from 'fs-extra'
4import { omit } from 'lodash'
5import { join } from 'path'
6import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models'
7import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
8import { buildServerDirectory, wait } from '../miscs/miscs'
9import { unwrapBody } from '../requests'
10import { waitUntilLog } from '../server/servers'
11import { AbstractCommand, OverrideCommandOptions } from '../shared'
12import { sendRTMPStream, testFfmpegStreamError } from './live'
13import { getVideoWithToken } from './videos'
14
15export class LiveCommand extends AbstractCommand {
16
04aed767 17 get (options: OverrideCommandOptions & {
4f219914
C
18 videoId: number | string
19 }) {
20 const path = '/api/v1/videos/live'
21
22 return this.getRequestBody<LiveVideo>({
23 ...options,
24
25 path: path + '/' + options.videoId,
a1637fa1 26 implicitToken: true,
4f219914
C
27 defaultExpectedStatus: HttpStatusCode.OK_200
28 })
29 }
30
04aed767 31 update (options: OverrideCommandOptions & {
4f219914
C
32 videoId: number | string
33 fields: LiveVideoUpdate
34 }) {
35 const { videoId, fields } = options
36 const path = '/api/v1/videos/live'
37
38 return this.putBodyRequest({
39 ...options,
40
41 path: path + '/' + videoId,
42 fields,
a1637fa1 43 implicitToken: true,
4f219914
C
44 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
45 })
46 }
47
04aed767 48 async create (options: OverrideCommandOptions & {
4f219914
C
49 fields: LiveVideoCreate
50 }) {
51 const { fields } = options
52 const path = '/api/v1/videos/live'
53
54 const attaches: any = {}
55 if (fields.thumbnailfile) attaches.thumbnailfile = fields.thumbnailfile
56 if (fields.previewfile) attaches.previewfile = fields.previewfile
57
58 const body = await unwrapBody<{ video: VideoCreateResult }>(this.postUploadRequest({
59 ...options,
60
61 path,
62 attaches,
63 fields: omit(fields, 'thumbnailfile', 'previewfile'),
a1637fa1 64 implicitToken: true,
4f219914
C
65 defaultExpectedStatus: HttpStatusCode.OK_200
66 }))
67
68 return body.video
69 }
70
71 async sendRTMPStreamInVideo (options: OverrideCommandOptions & {
72 videoId: number | string
73 fixtureName?: string
74 }) {
75 const { videoId, fixtureName } = options
04aed767 76 const videoLive = await this.get({ videoId })
4f219914
C
77
78 return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey, fixtureName)
79 }
80
04aed767 81 async runAndTestStreamError (options: OverrideCommandOptions & {
4f219914
C
82 videoId: number | string
83 shouldHaveError: boolean
84 }) {
85 const command = await this.sendRTMPStreamInVideo(options)
86
87 return testFfmpegStreamError(command, options.shouldHaveError)
88 }
89
04aed767 90 waitUntilPublished (options: OverrideCommandOptions & {
4f219914
C
91 videoId: number | string
92 }) {
93 const { videoId } = options
04aed767 94 return this.waitUntilState({ videoId, state: VideoState.PUBLISHED })
4f219914
C
95 }
96
04aed767 97 waitUntilWaiting (options: OverrideCommandOptions & {
4f219914
C
98 videoId: number | string
99 }) {
100 const { videoId } = options
04aed767 101 return this.waitUntilState({ videoId, state: VideoState.WAITING_FOR_LIVE })
4f219914
C
102 }
103
04aed767 104 waitUntilEnded (options: OverrideCommandOptions & {
4f219914
C
105 videoId: number | string
106 }) {
107 const { videoId } = options
04aed767 108 return this.waitUntilState({ videoId, state: VideoState.LIVE_ENDED })
4f219914
C
109 }
110
04aed767 111 waitUntilSegmentGeneration (options: OverrideCommandOptions & {
4f219914
C
112 videoUUID: string
113 resolution: number
114 segment: number
115 }) {
116 const { resolution, segment, videoUUID } = options
117 const segmentName = `${resolution}-00000${segment}.ts`
118
119 return waitUntilLog(this.server, `${videoUUID}/${segmentName}`, 2, false)
120 }
121
04aed767 122 async waitUntilSaved (options: OverrideCommandOptions & {
4f219914
C
123 videoId: number | string
124 }) {
125 let video: VideoDetails
126
127 do {
128 const res = await getVideoWithToken(this.server.url, options.token ?? this.server.accessToken, options.videoId)
129 video = res.body
130
131 await wait(500)
132 } while (video.isLive === true && video.state.id !== VideoState.PUBLISHED)
133 }
134
04aed767 135 async countPlaylists (options: OverrideCommandOptions & {
4f219914
C
136 videoUUID: string
137 }) {
138 const basePath = buildServerDirectory(this.server, 'streaming-playlists')
139 const hlsPath = join(basePath, 'hls', options.videoUUID)
140
141 const files = await readdir(hlsPath)
142
143 return files.filter(f => f.endsWith('.m3u8')).length
144 }
145
04aed767 146 private async waitUntilState (options: OverrideCommandOptions & {
4f219914
C
147 videoId: number | string
148 state: VideoState
149 }) {
150 let video: VideoDetails
151
152 do {
153 const res = await getVideoWithToken(this.server.url, options.token ?? this.server.accessToken, options.videoId)
154 video = res.body
155
156 await wait(500)
157 } while (video.state.id !== options.state)
158 }
159}