]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/shared/live.ts
Bumped to version v5.2.1
[github/Chocobozzz/PeerTube.git] / server / tests / shared / live.ts
CommitLineData
c55e3d72
C
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { pathExists, readdir } from 'fs-extra'
5import { join } from 'path'
8059e050 6import { sha1 } from '@shared/extra-utils'
cfd57d2c
C
7import { LiveVideo, VideoStreamingPlaylistType } from '@shared/models'
8import { ObjectStorageCommand, PeerTubeServer } from '@shared/server-commands'
d102de1b 9import { SQLCommand } from './sql-command'
cfd57d2c 10import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist } from './streaming-playlists'
c55e3d72 11
aa887096
C
12async function checkLiveCleanup (options: {
13 server: PeerTubeServer
14 videoUUID: string
15 permanent: boolean
16 savedResolutions?: number[]
17}) {
18 const { server, videoUUID, permanent, savedResolutions = [] } = options
19
c55e3d72
C
20 const basePath = server.servers.buildDirectory('streaming-playlists')
21 const hlsPath = join(basePath, 'hls', videoUUID)
22
aa887096
C
23 if (permanent) {
24 if (!await pathExists(hlsPath)) return
25
26 const files = await readdir(hlsPath)
27 expect(files).to.have.lengthOf(0)
28 return
29 }
30
4ec52d04 31 if (savedResolutions.length === 0) {
cfd57d2c
C
32 return checkUnsavedLiveCleanup(server, videoUUID, hlsPath)
33 }
34
35 return checkSavedLiveCleanup(hlsPath, savedResolutions)
36}
37
38// ---------------------------------------------------------------------------
5333788c 39
d102de1b
C
40async function testLiveVideoResolutions (options: {
41 sqlCommand: SQLCommand
cfd57d2c 42 originServer: PeerTubeServer
d102de1b 43
cfd57d2c
C
44 servers: PeerTubeServer[]
45 liveVideoId: string
46 resolutions: number[]
47 transcoded: boolean
8059e050 48
f8918990 49 objectStorage?: ObjectStorageCommand
8059e050 50 objectStorageBaseUrl?: string
cfd57d2c 51}) {
8059e050
C
52 const {
53 originServer,
d102de1b 54 sqlCommand,
8059e050
C
55 servers,
56 liveVideoId,
57 resolutions,
58 transcoded,
59 objectStorage,
f8918990 60 objectStorageBaseUrl = objectStorage?.getMockPlaylistBaseUrl()
8059e050 61 } = options
5333788c 62
cfd57d2c
C
63 for (const server of servers) {
64 const { data } = await server.videos.list()
65 expect(data.find(v => v.uuid === liveVideoId)).to.exist
5333788c 66
cfd57d2c
C
67 const video = await server.videos.get({ id: liveVideoId })
68 expect(video.streamingPlaylists).to.have.lengthOf(1)
5333788c 69
cfd57d2c
C
70 const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
71 expect(hlsPlaylist).to.exist
72 expect(hlsPlaylist.files).to.have.lengthOf(0) // Only fragmented mp4 files are displayed
73
8bd6aa04
C
74 await checkResolutionsInMasterPlaylist({
75 server,
76 playlistUrl: hlsPlaylist.playlistUrl,
77 resolutions,
78 transcoded,
f8918990 79 withRetry: !!objectStorage
8bd6aa04 80 })
cfd57d2c
C
81
82 if (objectStorage) {
8059e050 83 expect(hlsPlaylist.playlistUrl).to.contain(objectStorageBaseUrl)
5333788c 84 }
c55e3d72 85
cfd57d2c
C
86 for (let i = 0; i < resolutions.length; i++) {
87 const segmentNum = 3
88 const segmentName = `${i}-00000${segmentNum}.ts`
bbae45c3
C
89 await originServer.live.waitUntilSegmentGeneration({
90 server: originServer,
91 videoUUID: video.uuid,
92 playlistNumber: i,
93 segment: segmentNum,
8059e050
C
94 objectStorage,
95 objectStorageBaseUrl
bbae45c3 96 })
cfd57d2c
C
97
98 const baseUrl = objectStorage
8059e050 99 ? join(objectStorageBaseUrl, 'hls')
cfd57d2c
C
100 : originServer.url + '/static/streaming-playlists/hls'
101
102 if (objectStorage) {
8059e050 103 expect(hlsPlaylist.segmentsSha256Url).to.contain(objectStorageBaseUrl)
cfd57d2c
C
104 }
105
34aa316f
C
106 const subPlaylist = await originServer.streamingPlaylists.get({
107 url: `${baseUrl}/${video.uuid}/${i}.m3u8`,
f8918990 108 withRetry: !!objectStorage // With object storage, the request may fail because of inconsistent data in S3
34aa316f 109 })
cfd57d2c
C
110
111 expect(subPlaylist).to.contain(segmentName)
112
113 await checkLiveSegmentHash({
114 server,
115 baseUrlSegment: baseUrl,
116 videoUUID: video.uuid,
117 segmentName,
5170f492 118 hlsPlaylist,
f8918990 119 withRetry: !!objectStorage // With object storage, the request may fail because of inconsistent data in S3
cfd57d2c 120 })
54db8e3d
C
121
122 if (originServer.internalServerNumber === server.internalServerNumber) {
123 const infohash = sha1(`${2 + hlsPlaylist.playlistUrl}+V${i}`)
d102de1b 124 const dbInfohashes = await sqlCommand.getPlaylistInfohash(hlsPlaylist.id)
54db8e3d
C
125
126 expect(dbInfohashes).to.include(infohash)
127 }
cfd57d2c 128 }
c55e3d72 129 }
cfd57d2c
C
130}
131
132// ---------------------------------------------------------------------------
133
134export {
135 checkLiveCleanup,
d102de1b 136 testLiveVideoResolutions
cfd57d2c 137}
c55e3d72 138
cfd57d2c
C
139// ---------------------------------------------------------------------------
140
141async function checkSavedLiveCleanup (hlsPath: string, savedResolutions: number[] = []) {
c55e3d72
C
142 const files = await readdir(hlsPath)
143
144 // fragmented file and playlist per resolution + master playlist + segments sha256 json file
26818a73 145 expect(files, `Directory content: ${files.join(', ')}`).to.have.lengthOf(savedResolutions.length * 2 + 2)
c55e3d72 146
4ec52d04 147 for (const resolution of savedResolutions) {
c55e3d72
C
148 const fragmentedFile = files.find(f => f.endsWith(`-${resolution}-fragmented.mp4`))
149 expect(fragmentedFile).to.exist
150
151 const playlistFile = files.find(f => f.endsWith(`${resolution}.m3u8`))
152 expect(playlistFile).to.exist
153 }
154
155 const masterPlaylistFile = files.find(f => f.endsWith('-master.m3u8'))
156 expect(masterPlaylistFile).to.exist
157
158 const shaFile = files.find(f => f.endsWith('-segments-sha256.json'))
159 expect(shaFile).to.exist
160}
161
cfd57d2c
C
162async function checkUnsavedLiveCleanup (server: PeerTubeServer, videoUUID: string, hlsPath: string) {
163 let live: LiveVideo
164
165 try {
166 live = await server.live.get({ videoId: videoUUID })
167 } catch {}
168
169 if (live?.permanentLive) {
170 expect(await pathExists(hlsPath)).to.be.true
171
172 const hlsFiles = await readdir(hlsPath)
173 expect(hlsFiles).to.have.lengthOf(1) // Only replays directory
174
175 const replayDir = join(hlsPath, 'replay')
176 expect(await pathExists(replayDir)).to.be.true
177
178 const replayFiles = await readdir(join(hlsPath, 'replay'))
179 expect(replayFiles).to.have.lengthOf(0)
180
181 return
182 }
183
184 expect(await pathExists(hlsPath)).to.be.false
c55e3d72 185}