diff options
Diffstat (limited to 'shared/extra-utils/videos/live.ts')
-rw-r--r-- | shared/extra-utils/videos/live.ts | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/shared/extra-utils/videos/live.ts b/shared/extra-utils/videos/live.ts new file mode 100644 index 000000000..f500fdc3e --- /dev/null +++ b/shared/extra-utils/videos/live.ts | |||
@@ -0,0 +1,102 @@ | |||
1 | import * as ffmpeg from 'fluent-ffmpeg' | ||
2 | import { LiveVideoCreate, LiveVideoUpdate, VideoDetails, VideoState } from '@shared/models' | ||
3 | import { buildAbsoluteFixturePath, wait } from '../miscs/miscs' | ||
4 | import { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests' | ||
5 | import { ServerInfo } from '../server/servers' | ||
6 | import { getVideo, getVideoWithToken } from './videos' | ||
7 | |||
8 | function getLive (url: string, token: string, videoId: number | string, statusCodeExpected = 200) { | ||
9 | const path = '/api/v1/videos/live' | ||
10 | |||
11 | return makeGetRequest({ | ||
12 | url, | ||
13 | token, | ||
14 | path: path + '/' + videoId, | ||
15 | statusCodeExpected | ||
16 | }) | ||
17 | } | ||
18 | |||
19 | function updateLive (url: string, token: string, videoId: number | string, fields: LiveVideoUpdate, statusCodeExpected = 204) { | ||
20 | const path = '/api/v1/videos/live' | ||
21 | |||
22 | return makePutBodyRequest({ | ||
23 | url, | ||
24 | token, | ||
25 | path: path + '/' + videoId, | ||
26 | fields, | ||
27 | statusCodeExpected | ||
28 | }) | ||
29 | } | ||
30 | |||
31 | function createLive (url: string, token: string, fields: LiveVideoCreate, statusCodeExpected = 200) { | ||
32 | const path = '/api/v1/videos/live' | ||
33 | |||
34 | let attaches: any = {} | ||
35 | if (fields.thumbnailfile) attaches = { thumbnailfile: fields.thumbnailfile } | ||
36 | if (fields.previewfile) attaches = { previewfile: fields.previewfile } | ||
37 | |||
38 | return makeUploadRequest({ | ||
39 | url, | ||
40 | path, | ||
41 | token, | ||
42 | attaches, | ||
43 | fields, | ||
44 | statusCodeExpected | ||
45 | }) | ||
46 | } | ||
47 | |||
48 | function sendRTMPStream (rtmpBaseUrl: string, streamKey: string) { | ||
49 | const fixture = buildAbsoluteFixturePath('video_short.mp4') | ||
50 | |||
51 | const command = ffmpeg(fixture) | ||
52 | command.inputOption('-stream_loop -1') | ||
53 | command.inputOption('-re') | ||
54 | |||
55 | command.outputOption('-c copy') | ||
56 | command.outputOption('-f flv') | ||
57 | |||
58 | const rtmpUrl = rtmpBaseUrl + '/' + streamKey | ||
59 | command.output(rtmpUrl) | ||
60 | |||
61 | command.on('error', err => { | ||
62 | if (err?.message?.includes('Exiting normally')) return | ||
63 | |||
64 | console.error('Cannot send RTMP stream.', { err }) | ||
65 | }) | ||
66 | |||
67 | if (process.env.DEBUG) { | ||
68 | command.on('stderr', data => console.log(data)) | ||
69 | } | ||
70 | |||
71 | command.run() | ||
72 | |||
73 | return command | ||
74 | } | ||
75 | |||
76 | async function stopFfmpeg (command: ffmpeg.FfmpegCommand) { | ||
77 | command.kill('SIGINT') | ||
78 | |||
79 | await wait(500) | ||
80 | } | ||
81 | |||
82 | async function waitUntilLiveStarts (url: string, token: string, videoId: number | string) { | ||
83 | let video: VideoDetails | ||
84 | |||
85 | do { | ||
86 | const res = await getVideoWithToken(url, token, videoId) | ||
87 | video = res.body | ||
88 | |||
89 | await wait(500) | ||
90 | } while (video.state.id === VideoState.WAITING_FOR_LIVE) | ||
91 | } | ||
92 | |||
93 | // --------------------------------------------------------------------------- | ||
94 | |||
95 | export { | ||
96 | getLive, | ||
97 | updateLive, | ||
98 | waitUntilLiveStarts, | ||
99 | createLive, | ||
100 | stopFfmpeg, | ||
101 | sendRTMPStream | ||
102 | } | ||