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