diff options
author | Chocobozzz <me@florianbigard.com> | 2022-10-04 10:03:17 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-10-04 10:03:17 +0200 |
commit | cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1 (patch) | |
tree | dc899a1504ecac588e5580553e02571e0f5d7e4b /server/tests/shared/live.ts | |
parent | 9c0cdc5047918b959ebd5e075ddad81eb7fb93f0 (diff) | |
download | PeerTube-cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1.tar.gz PeerTube-cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1.tar.zst PeerTube-cfd57d2ca0bb058087f7dc90fcc3e8442b0288e1.zip |
Live supports object storage
* Sync live files (segments, master playlist, resolution playlist,
segment sha file) into object storage
* Automatically delete them when the live ends
* Segment sha file is now a file on disk, and not stored in memory
anymore
Diffstat (limited to 'server/tests/shared/live.ts')
-rw-r--r-- | server/tests/shared/live.ts | 116 |
1 files changed, 95 insertions, 21 deletions
diff --git a/server/tests/shared/live.ts b/server/tests/shared/live.ts index 4bd4786fc..aa79622cb 100644 --- a/server/tests/shared/live.ts +++ b/server/tests/shared/live.ts | |||
@@ -3,39 +3,92 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { pathExists, readdir } from 'fs-extra' | 4 | import { pathExists, readdir } from 'fs-extra' |
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { LiveVideo } from '@shared/models' | 6 | import { wait } from '@shared/core-utils' |
7 | import { PeerTubeServer } from '@shared/server-commands' | 7 | import { LiveVideo, VideoStreamingPlaylistType } from '@shared/models' |
8 | import { ObjectStorageCommand, PeerTubeServer } from '@shared/server-commands' | ||
9 | import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist } from './streaming-playlists' | ||
8 | 10 | ||
9 | async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, savedResolutions: number[] = []) { | 11 | async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, savedResolutions: number[] = []) { |
10 | let live: LiveVideo | ||
11 | |||
12 | try { | ||
13 | live = await server.live.get({ videoId: videoUUID }) | ||
14 | } catch {} | ||
15 | |||
16 | const basePath = server.servers.buildDirectory('streaming-playlists') | 12 | const basePath = server.servers.buildDirectory('streaming-playlists') |
17 | const hlsPath = join(basePath, 'hls', videoUUID) | 13 | const hlsPath = join(basePath, 'hls', videoUUID) |
18 | 14 | ||
19 | if (savedResolutions.length === 0) { | 15 | if (savedResolutions.length === 0) { |
16 | return checkUnsavedLiveCleanup(server, videoUUID, hlsPath) | ||
17 | } | ||
18 | |||
19 | return checkSavedLiveCleanup(hlsPath, savedResolutions) | ||
20 | } | ||
21 | |||
22 | // --------------------------------------------------------------------------- | ||
20 | 23 | ||
21 | if (live?.permanentLive) { | 24 | async function testVideoResolutions (options: { |
22 | expect(await pathExists(hlsPath)).to.be.true | 25 | originServer: PeerTubeServer |
26 | servers: PeerTubeServer[] | ||
27 | liveVideoId: string | ||
28 | resolutions: number[] | ||
29 | transcoded: boolean | ||
30 | objectStorage: boolean | ||
31 | }) { | ||
32 | const { originServer, servers, liveVideoId, resolutions, transcoded, objectStorage } = options | ||
23 | 33 | ||
24 | const hlsFiles = await readdir(hlsPath) | 34 | for (const server of servers) { |
25 | expect(hlsFiles).to.have.lengthOf(1) // Only replays directory | 35 | const { data } = await server.videos.list() |
36 | expect(data.find(v => v.uuid === liveVideoId)).to.exist | ||
26 | 37 | ||
27 | const replayDir = join(hlsPath, 'replay') | 38 | const video = await server.videos.get({ id: liveVideoId }) |
28 | expect(await pathExists(replayDir)).to.be.true | 39 | expect(video.streamingPlaylists).to.have.lengthOf(1) |
29 | 40 | ||
30 | const replayFiles = await readdir(join(hlsPath, 'replay')) | 41 | const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS) |
31 | expect(replayFiles).to.have.lengthOf(0) | 42 | expect(hlsPlaylist).to.exist |
32 | } else { | 43 | expect(hlsPlaylist.files).to.have.lengthOf(0) // Only fragmented mp4 files are displayed |
33 | expect(await pathExists(hlsPath)).to.be.false | 44 | |
45 | await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions, transcoded }) | ||
46 | |||
47 | if (objectStorage) { | ||
48 | expect(hlsPlaylist.playlistUrl).to.contain(ObjectStorageCommand.getPlaylistBaseUrl()) | ||
34 | } | 49 | } |
35 | 50 | ||
36 | return | 51 | for (let i = 0; i < resolutions.length; i++) { |
52 | const segmentNum = 3 | ||
53 | const segmentName = `${i}-00000${segmentNum}.ts` | ||
54 | await originServer.live.waitUntilSegmentGeneration({ videoUUID: video.uuid, playlistNumber: i, segment: segmentNum }) | ||
55 | |||
56 | const baseUrl = objectStorage | ||
57 | ? ObjectStorageCommand.getPlaylistBaseUrl() + 'hls' | ||
58 | : originServer.url + '/static/streaming-playlists/hls' | ||
59 | |||
60 | if (objectStorage) { | ||
61 | // Playlist file upload | ||
62 | await wait(500) | ||
63 | |||
64 | expect(hlsPlaylist.segmentsSha256Url).to.contain(ObjectStorageCommand.getPlaylistBaseUrl()) | ||
65 | } | ||
66 | |||
67 | const subPlaylist = await originServer.streamingPlaylists.get({ url: `${baseUrl}/${video.uuid}/${i}.m3u8` }) | ||
68 | |||
69 | expect(subPlaylist).to.contain(segmentName) | ||
70 | |||
71 | await checkLiveSegmentHash({ | ||
72 | server, | ||
73 | baseUrlSegment: baseUrl, | ||
74 | videoUUID: video.uuid, | ||
75 | segmentName, | ||
76 | hlsPlaylist | ||
77 | }) | ||
78 | } | ||
37 | } | 79 | } |
80 | } | ||
81 | |||
82 | // --------------------------------------------------------------------------- | ||
83 | |||
84 | export { | ||
85 | checkLiveCleanup, | ||
86 | testVideoResolutions | ||
87 | } | ||
38 | 88 | ||
89 | // --------------------------------------------------------------------------- | ||
90 | |||
91 | async function checkSavedLiveCleanup (hlsPath: string, savedResolutions: number[] = []) { | ||
39 | const files = await readdir(hlsPath) | 92 | const files = await readdir(hlsPath) |
40 | 93 | ||
41 | // fragmented file and playlist per resolution + master playlist + segments sha256 json file | 94 | // fragmented file and playlist per resolution + master playlist + segments sha256 json file |
@@ -56,6 +109,27 @@ async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, save | |||
56 | expect(shaFile).to.exist | 109 | expect(shaFile).to.exist |
57 | } | 110 | } |
58 | 111 | ||
59 | export { | 112 | async function checkUnsavedLiveCleanup (server: PeerTubeServer, videoUUID: string, hlsPath: string) { |
60 | checkLiveCleanup | 113 | let live: LiveVideo |
114 | |||
115 | try { | ||
116 | live = await server.live.get({ videoId: videoUUID }) | ||
117 | } catch {} | ||
118 | |||
119 | if (live?.permanentLive) { | ||
120 | expect(await pathExists(hlsPath)).to.be.true | ||
121 | |||
122 | const hlsFiles = await readdir(hlsPath) | ||
123 | expect(hlsFiles).to.have.lengthOf(1) // Only replays directory | ||
124 | |||
125 | const replayDir = join(hlsPath, 'replay') | ||
126 | expect(await pathExists(replayDir)).to.be.true | ||
127 | |||
128 | const replayFiles = await readdir(join(hlsPath, 'replay')) | ||
129 | expect(replayFiles).to.have.lengthOf(0) | ||
130 | |||
131 | return | ||
132 | } | ||
133 | |||
134 | expect(await pathExists(hlsPath)).to.be.false | ||
61 | } | 135 | } |