]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - shared/extra-utils/videos/live.ts
Fix server run
[github/Chocobozzz/PeerTube.git] / shared / extra-utils / videos / live.ts
CommitLineData
68e70a74
C
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
77e9f859 4import * as ffmpeg from 'fluent-ffmpeg'
68e70a74 5import { pathExists, readdir } from 'fs-extra'
68e70a74 6import { join } from 'path'
6c5065a0 7import { buildAbsoluteFixturePath, wait } from '../miscs'
254d3579 8import { PeerTubeServer } from '../server/server'
97969c4e 9
ca5c612b
C
10function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, fixtureName = 'video_short.mp4') {
11 const fixture = buildAbsoluteFixturePath(fixtureName)
77e9f859
C
12
13 const command = ffmpeg(fixture)
14 command.inputOption('-stream_loop -1')
15 command.inputOption('-re')
68e70a74
C
16 command.outputOption('-c:v libx264')
17 command.outputOption('-g 50')
18 command.outputOption('-keyint_min 2')
884d2c39 19 command.outputOption('-r 60')
77e9f859
C
20 command.outputOption('-f flv')
21
22 const rtmpUrl = rtmpBaseUrl + '/' + streamKey
23 command.output(rtmpUrl)
24
25 command.on('error', err => {
26 if (err?.message?.includes('Exiting normally')) return
27
68e70a74 28 if (process.env.DEBUG) console.error(err)
77e9f859
C
29 })
30
31 if (process.env.DEBUG) {
32 command.on('stderr', data => console.log(data))
33 }
34
35 command.run()
36
37 return command
38}
39
97969c4e 40function waitFfmpegUntilError (command: ffmpeg.FfmpegCommand, successAfterMS = 10000) {
ba5a8d89 41 return new Promise<void>((res, rej) => {
97969c4e
C
42 command.on('error', err => {
43 return rej(err)
44 })
45
46 setTimeout(() => {
47 res()
48 }, successAfterMS)
49 })
50}
51
68e70a74 52async function testFfmpegStreamError (command: ffmpeg.FfmpegCommand, shouldHaveError: boolean) {
97969c4e
C
53 let error: Error
54
55 try {
5b23d4e0 56 await waitFfmpegUntilError(command, 35000)
97969c4e
C
57 } catch (err) {
58 error = err
59 }
60
61 await stopFfmpeg(command)
62
63 if (shouldHaveError && !error) throw new Error('Ffmpeg did not have an error')
64 if (!shouldHaveError && error) throw error
65}
66
77e9f859
C
67async function stopFfmpeg (command: ffmpeg.FfmpegCommand) {
68 command.kill('SIGINT')
69
70 await wait(500)
71}
72
254d3579 73async function waitUntilLivePublishedOnAllServers (servers: PeerTubeServer[], videoId: string) {
8ebf2a5d 74 for (const server of servers) {
89d241a7 75 await server.live.waitUntilPublished({ videoId })
8ebf2a5d
C
76 }
77}
78
254d3579 79async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, resolutions: number[] = []) {
89d241a7 80 const basePath = server.servers.buildDirectory('streaming-playlists')
68e70a74
C
81 const hlsPath = join(basePath, 'hls', videoUUID)
82
83 if (resolutions.length === 0) {
84 const result = await pathExists(hlsPath)
85 expect(result).to.be.false
86
87 return
88 }
89
90 const files = await readdir(hlsPath)
91
92 // fragmented file and playlist per resolution + master playlist + segments sha256 json file
93 expect(files).to.have.lengthOf(resolutions.length * 2 + 2)
94
95 for (const resolution of resolutions) {
96 expect(files).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`)
97 expect(files).to.contain(`${resolution}.m3u8`)
98 }
99
100 expect(files).to.contain('master.m3u8')
101 expect(files).to.contain('segments-sha256.json')
102}
103
77e9f859 104export {
4f219914 105 sendRTMPStream,
97969c4e 106 waitFfmpegUntilError,
4f219914
C
107 testFfmpegStreamError,
108 stopFfmpeg,
8ebf2a5d 109 waitUntilLivePublishedOnAllServers,
4f219914 110 checkLiveCleanup
77e9f859 111}