]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame_incremental - shared/server-commands/videos/live.ts
feat: show contained playlists under My videos (#5125)
[github/Chocobozzz/PeerTube.git] / shared / server-commands / videos / live.ts
... / ...
CommitLineData
1import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
2import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
3import { VideoDetails, VideoInclude } from '@shared/models'
4import { PeerTubeServer } from '../server/server'
5
6function sendRTMPStream (options: {
7 rtmpBaseUrl: string
8 streamKey: string
9 fixtureName?: string // default video_short.mp4
10 copyCodecs?: boolean // default false
11}) {
12 const { rtmpBaseUrl, streamKey, fixtureName = 'video_short.mp4', copyCodecs = false } = options
13
14 const fixture = buildAbsoluteFixturePath(fixtureName)
15
16 const command = ffmpeg(fixture)
17 command.inputOption('-stream_loop -1')
18 command.inputOption('-re')
19
20 if (copyCodecs) {
21 command.outputOption('-c copy')
22 } else {
23 command.outputOption('-c:v libx264')
24 command.outputOption('-g 50')
25 command.outputOption('-keyint_min 2')
26 command.outputOption('-r 60')
27 }
28
29 command.outputOption('-f flv')
30
31 const rtmpUrl = rtmpBaseUrl + '/' + streamKey
32 command.output(rtmpUrl)
33
34 command.on('error', err => {
35 if (err?.message?.includes('Exiting normally')) return
36
37 if (process.env.DEBUG) console.error(err)
38 })
39
40 if (process.env.DEBUG) {
41 command.on('stderr', data => console.log(data))
42 }
43
44 command.run()
45
46 return command
47}
48
49function waitFfmpegUntilError (command: FfmpegCommand, successAfterMS = 10000) {
50 return new Promise<void>((res, rej) => {
51 command.on('error', err => {
52 return rej(err)
53 })
54
55 setTimeout(() => {
56 res()
57 }, successAfterMS)
58 })
59}
60
61async function testFfmpegStreamError (command: FfmpegCommand, shouldHaveError: boolean) {
62 let error: Error
63
64 try {
65 await waitFfmpegUntilError(command, 35000)
66 } catch (err) {
67 error = err
68 }
69
70 await stopFfmpeg(command)
71
72 if (shouldHaveError && !error) throw new Error('Ffmpeg did not have an error')
73 if (!shouldHaveError && error) throw error
74}
75
76async function stopFfmpeg (command: FfmpegCommand) {
77 command.kill('SIGINT')
78
79 await wait(500)
80}
81
82async function waitUntilLivePublishedOnAllServers (servers: PeerTubeServer[], videoId: string) {
83 for (const server of servers) {
84 await server.live.waitUntilPublished({ videoId })
85 }
86}
87
88async function waitUntilLiveWaitingOnAllServers (servers: PeerTubeServer[], videoId: string) {
89 for (const server of servers) {
90 await server.live.waitUntilWaiting({ videoId })
91 }
92}
93
94async function waitUntilLiveReplacedByReplayOnAllServers (servers: PeerTubeServer[], videoId: string) {
95 for (const server of servers) {
96 await server.live.waitUntilReplacedByReplay({ videoId })
97 }
98}
99
100async function findExternalSavedVideo (server: PeerTubeServer, liveDetails: VideoDetails) {
101 const { data } = await server.videos.list({ token: server.accessToken, sort: '-publishedAt', include: VideoInclude.BLACKLISTED })
102
103 return data.find(v => v.name === liveDetails.name + ' - ' + new Date(liveDetails.publishedAt).toLocaleString())
104}
105
106export {
107 sendRTMPStream,
108 waitFfmpegUntilError,
109 testFfmpegStreamError,
110 stopFfmpeg,
111
112 waitUntilLivePublishedOnAllServers,
113 waitUntilLiveReplacedByReplayOnAllServers,
114 waitUntilLiveWaitingOnAllServers,
115
116 findExternalSavedVideo
117}