diff options
Diffstat (limited to 'shared/extra-utils/videos/live.ts')
-rw-r--r-- | shared/extra-utils/videos/live.ts | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/shared/extra-utils/videos/live.ts b/shared/extra-utils/videos/live.ts index a391565a4..f90dd420d 100644 --- a/shared/extra-utils/videos/live.ts +++ b/shared/extra-utils/videos/live.ts | |||
@@ -1,8 +1,14 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
1 | import * as ffmpeg from 'fluent-ffmpeg' | 4 | import * as ffmpeg from 'fluent-ffmpeg' |
5 | import { pathExists, readdir } from 'fs-extra' | ||
2 | import { omit } from 'lodash' | 6 | import { omit } from 'lodash' |
7 | import { join } from 'path' | ||
3 | import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoDetails, VideoState } from '@shared/models' | 8 | import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoDetails, VideoState } from '@shared/models' |
4 | import { buildAbsoluteFixturePath, wait } from '../miscs/miscs' | 9 | import { buildAbsoluteFixturePath, buildServerDirectory, wait } from '../miscs/miscs' |
5 | import { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests' | 10 | import { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests' |
11 | import { ServerInfo } from '../server/servers' | ||
6 | import { getVideoWithToken } from './videos' | 12 | import { getVideoWithToken } from './videos' |
7 | 13 | ||
8 | function getLive (url: string, token: string, videoId: number | string, statusCodeExpected = 200) { | 14 | function getLive (url: string, token: string, videoId: number | string, statusCodeExpected = 200) { |
@@ -47,21 +53,22 @@ function createLive (url: string, token: string, fields: LiveVideoCreate, status | |||
47 | }) | 53 | }) |
48 | } | 54 | } |
49 | 55 | ||
50 | async function sendRTMPStreamInVideo (url: string, token: string, videoId: number | string, onErrorCb?: Function) { | 56 | async function sendRTMPStreamInVideo (url: string, token: string, videoId: number | string) { |
51 | const res = await getLive(url, token, videoId) | 57 | const res = await getLive(url, token, videoId) |
52 | const videoLive = res.body as LiveVideo | 58 | const videoLive = res.body as LiveVideo |
53 | 59 | ||
54 | return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey, onErrorCb) | 60 | return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey) |
55 | } | 61 | } |
56 | 62 | ||
57 | function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, onErrorCb?: Function) { | 63 | function sendRTMPStream (rtmpBaseUrl: string, streamKey: string) { |
58 | const fixture = buildAbsoluteFixturePath('video_short.mp4') | 64 | const fixture = buildAbsoluteFixturePath('video_short.mp4') |
59 | 65 | ||
60 | const command = ffmpeg(fixture) | 66 | const command = ffmpeg(fixture) |
61 | command.inputOption('-stream_loop -1') | 67 | command.inputOption('-stream_loop -1') |
62 | command.inputOption('-re') | 68 | command.inputOption('-re') |
63 | 69 | command.outputOption('-c:v libx264') | |
64 | command.outputOption('-c copy') | 70 | command.outputOption('-g 50') |
71 | command.outputOption('-keyint_min 2') | ||
65 | command.outputOption('-f flv') | 72 | command.outputOption('-f flv') |
66 | 73 | ||
67 | const rtmpUrl = rtmpBaseUrl + '/' + streamKey | 74 | const rtmpUrl = rtmpBaseUrl + '/' + streamKey |
@@ -70,7 +77,7 @@ function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, onErrorCb?: Fun | |||
70 | command.on('error', err => { | 77 | command.on('error', err => { |
71 | if (err?.message?.includes('Exiting normally')) return | 78 | if (err?.message?.includes('Exiting normally')) return |
72 | 79 | ||
73 | if (onErrorCb) onErrorCb(err) | 80 | if (process.env.DEBUG) console.error(err) |
74 | }) | 81 | }) |
75 | 82 | ||
76 | if (process.env.DEBUG) { | 83 | if (process.env.DEBUG) { |
@@ -94,8 +101,13 @@ function waitFfmpegUntilError (command: ffmpeg.FfmpegCommand, successAfterMS = 1 | |||
94 | }) | 101 | }) |
95 | } | 102 | } |
96 | 103 | ||
97 | async function testFfmpegStreamError (url: string, token: string, videoId: number | string, shouldHaveError: boolean) { | 104 | async function runAndTestFfmpegStreamError (url: string, token: string, videoId: number | string, shouldHaveError: boolean) { |
98 | const command = await sendRTMPStreamInVideo(url, token, videoId) | 105 | const command = await sendRTMPStreamInVideo(url, token, videoId) |
106 | |||
107 | return testFfmpegStreamError(command, shouldHaveError) | ||
108 | } | ||
109 | |||
110 | async function testFfmpegStreamError (command: ffmpeg.FfmpegCommand, shouldHaveError: boolean) { | ||
99 | let error: Error | 111 | let error: Error |
100 | 112 | ||
101 | try { | 113 | try { |
@@ -127,6 +139,31 @@ async function waitUntilLiveStarts (url: string, token: string, videoId: number | |||
127 | } while (video.state.id === VideoState.WAITING_FOR_LIVE) | 139 | } while (video.state.id === VideoState.WAITING_FOR_LIVE) |
128 | } | 140 | } |
129 | 141 | ||
142 | async function checkLiveCleanup (server: ServerInfo, videoUUID: string, resolutions: number[] = []) { | ||
143 | const basePath = buildServerDirectory(server.internalServerNumber, 'streaming-playlists') | ||
144 | const hlsPath = join(basePath, 'hls', videoUUID) | ||
145 | |||
146 | if (resolutions.length === 0) { | ||
147 | const result = await pathExists(hlsPath) | ||
148 | expect(result).to.be.false | ||
149 | |||
150 | return | ||
151 | } | ||
152 | |||
153 | const files = await readdir(hlsPath) | ||
154 | |||
155 | // fragmented file and playlist per resolution + master playlist + segments sha256 json file | ||
156 | expect(files).to.have.lengthOf(resolutions.length * 2 + 2) | ||
157 | |||
158 | for (const resolution of resolutions) { | ||
159 | expect(files).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`) | ||
160 | expect(files).to.contain(`${resolution}.m3u8`) | ||
161 | } | ||
162 | |||
163 | expect(files).to.contain('master.m3u8') | ||
164 | expect(files).to.contain('segments-sha256.json') | ||
165 | } | ||
166 | |||
130 | // --------------------------------------------------------------------------- | 167 | // --------------------------------------------------------------------------- |
131 | 168 | ||
132 | export { | 169 | export { |
@@ -134,9 +171,11 @@ export { | |||
134 | updateLive, | 171 | updateLive, |
135 | waitUntilLiveStarts, | 172 | waitUntilLiveStarts, |
136 | createLive, | 173 | createLive, |
137 | testFfmpegStreamError, | 174 | runAndTestFfmpegStreamError, |
175 | checkLiveCleanup, | ||
138 | stopFfmpeg, | 176 | stopFfmpeg, |
139 | sendRTMPStreamInVideo, | 177 | sendRTMPStreamInVideo, |
140 | waitFfmpegUntilError, | 178 | waitFfmpegUntilError, |
141 | sendRTMPStream | 179 | sendRTMPStream, |
180 | testFfmpegStreamError | ||
142 | } | 181 | } |