aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/server-commands/videos/live.ts
diff options
context:
space:
mode:
Diffstat (limited to 'shared/server-commands/videos/live.ts')
-rw-r--r--shared/server-commands/videos/live.ts100
1 files changed, 100 insertions, 0 deletions
diff --git a/shared/server-commands/videos/live.ts b/shared/server-commands/videos/live.ts
new file mode 100644
index 000000000..7a7faa911
--- /dev/null
+++ b/shared/server-commands/videos/live.ts
@@ -0,0 +1,100 @@
1import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
2import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
3import { PeerTubeServer } from '../server/server'
4
5function sendRTMPStream (options: {
6 rtmpBaseUrl: string
7 streamKey: string
8 fixtureName?: string // default video_short.mp4
9 copyCodecs?: boolean // default false
10}) {
11 const { rtmpBaseUrl, streamKey, fixtureName = 'video_short.mp4', copyCodecs = false } = options
12
13 const fixture = buildAbsoluteFixturePath(fixtureName)
14
15 const command = ffmpeg(fixture)
16 command.inputOption('-stream_loop -1')
17 command.inputOption('-re')
18
19 if (copyCodecs) {
20 command.outputOption('-c copy')
21 } else {
22 command.outputOption('-c:v libx264')
23 command.outputOption('-g 50')
24 command.outputOption('-keyint_min 2')
25 command.outputOption('-r 60')
26 }
27
28 command.outputOption('-f flv')
29
30 const rtmpUrl = rtmpBaseUrl + '/' + streamKey
31 command.output(rtmpUrl)
32
33 command.on('error', err => {
34 if (err?.message?.includes('Exiting normally')) return
35
36 if (process.env.DEBUG) console.error(err)
37 })
38
39 if (process.env.DEBUG) {
40 command.on('stderr', data => console.log(data))
41 }
42
43 command.run()
44
45 return command
46}
47
48function waitFfmpegUntilError (command: FfmpegCommand, successAfterMS = 10000) {
49 return new Promise<void>((res, rej) => {
50 command.on('error', err => {
51 return rej(err)
52 })
53
54 setTimeout(() => {
55 res()
56 }, successAfterMS)
57 })
58}
59
60async function testFfmpegStreamError (command: FfmpegCommand, shouldHaveError: boolean) {
61 let error: Error
62
63 try {
64 await waitFfmpegUntilError(command, 35000)
65 } catch (err) {
66 error = err
67 }
68
69 await stopFfmpeg(command)
70
71 if (shouldHaveError && !error) throw new Error('Ffmpeg did not have an error')
72 if (!shouldHaveError && error) throw error
73}
74
75async function stopFfmpeg (command: FfmpegCommand) {
76 command.kill('SIGINT')
77
78 await wait(500)
79}
80
81async function waitUntilLivePublishedOnAllServers (servers: PeerTubeServer[], videoId: string) {
82 for (const server of servers) {
83 await server.live.waitUntilPublished({ videoId })
84 }
85}
86
87async function waitUntilLiveSavedOnAllServers (servers: PeerTubeServer[], videoId: string) {
88 for (const server of servers) {
89 await server.live.waitUntilSaved({ videoId })
90 }
91}
92
93export {
94 sendRTMPStream,
95 waitFfmpegUntilError,
96 testFfmpegStreamError,
97 stopFfmpeg,
98 waitUntilLivePublishedOnAllServers,
99 waitUntilLiveSavedOnAllServers
100}