aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/live
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/api/live')
-rw-r--r--server/tests/api/live/live-constraints.ts81
-rw-r--r--server/tests/api/live/live-permanent.ts99
-rw-r--r--server/tests/api/live/live-save-replay.ts126
-rw-r--r--server/tests/api/live/live-socket-messages.ts71
-rw-r--r--server/tests/api/live/live-views.ts51
-rw-r--r--server/tests/api/live/live.ts289
6 files changed, 340 insertions, 377 deletions
diff --git a/server/tests/api/live/live-constraints.ts b/server/tests/api/live/live-constraints.ts
index cc635de33..4acde3cc5 100644
--- a/server/tests/api/live/live-constraints.ts
+++ b/server/tests/api/live/live-constraints.ts
@@ -2,31 +2,24 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { VideoDetails, VideoPrivacy } from '@shared/models' 5import { VideoPrivacy } from '@shared/models'
6import { 6import {
7 checkLiveCleanup, 7 checkLiveCleanupAfterSave,
8 cleanupTests, 8 cleanupTests,
9 createLive, 9 ConfigCommand,
10 createMultipleServers,
10 doubleFollow, 11 doubleFollow,
11 flushAndRunMultipleServers, 12 PeerTubeServer,
12 generateUser,
13 getCustomConfigResolutions,
14 getVideo,
15 runAndTestFfmpegStreamError,
16 ServerInfo,
17 setAccessTokensToServers, 13 setAccessTokensToServers,
18 setDefaultVideoChannel, 14 setDefaultVideoChannel,
19 updateCustomSubConfig,
20 updateUser,
21 wait, 15 wait,
22 waitJobs, 16 waitJobs
23 waitUntilLivePublished
24} from '../../../../shared/extra-utils' 17} from '../../../../shared/extra-utils'
25 18
26const expect = chai.expect 19const expect = chai.expect
27 20
28describe('Test live constraints', function () { 21describe('Test live constraints', function () {
29 let servers: ServerInfo[] = [] 22 let servers: PeerTubeServer[] = []
30 let userId: number 23 let userId: number
31 let userAccessToken: string 24 let userAccessToken: string
32 let userChannelId: number 25 let userChannelId: number
@@ -39,32 +32,28 @@ describe('Test live constraints', function () {
39 saveReplay 32 saveReplay
40 } 33 }
41 34
42 const res = await createLive(servers[0].url, userAccessToken, liveAttributes) 35 const { uuid } = await servers[0].live.create({ token: userAccessToken, fields: liveAttributes })
43 return res.body.video.uuid as string 36 return uuid
44 } 37 }
45 38
46 async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) { 39 async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) {
47 for (const server of servers) { 40 for (const server of servers) {
48 const res = await getVideo(server.url, videoId) 41 const video = await server.videos.get({ id: videoId })
49
50 const video: VideoDetails = res.body
51 expect(video.isLive).to.be.false 42 expect(video.isLive).to.be.false
52 expect(video.duration).to.be.greaterThan(0) 43 expect(video.duration).to.be.greaterThan(0)
53 } 44 }
54 45
55 await checkLiveCleanup(servers[0], videoId, resolutions) 46 await checkLiveCleanupAfterSave(servers[0], videoId, resolutions)
56 } 47 }
57 48
58 async function waitUntilLivePublishedOnAllServers (videoId: string) { 49 async function waitUntilLivePublishedOnAllServers (videoId: string) {
59 for (const server of servers) { 50 for (const server of servers) {
60 await waitUntilLivePublished(server.url, server.accessToken, videoId) 51 await server.live.waitUntilPublished({ videoId })
61 } 52 }
62 } 53 }
63 54
64 function updateQuota (options: { total: number, daily: number }) { 55 function updateQuota (options: { total: number, daily: number }) {
65 return updateUser({ 56 return servers[0].users.update({
66 url: servers[0].url,
67 accessToken: servers[0].accessToken,
68 userId, 57 userId,
69 videoQuota: options.total, 58 videoQuota: options.total,
70 videoQuotaDaily: options.daily 59 videoQuotaDaily: options.daily
@@ -74,24 +63,26 @@ describe('Test live constraints', function () {
74 before(async function () { 63 before(async function () {
75 this.timeout(120000) 64 this.timeout(120000)
76 65
77 servers = await flushAndRunMultipleServers(2) 66 servers = await createMultipleServers(2)
78 67
79 // Get the access tokens 68 // Get the access tokens
80 await setAccessTokensToServers(servers) 69 await setAccessTokensToServers(servers)
81 await setDefaultVideoChannel(servers) 70 await setDefaultVideoChannel(servers)
82 71
83 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 72 await servers[0].config.updateCustomSubConfig({
84 live: { 73 newConfig: {
85 enabled: true, 74 live: {
86 allowReplay: true, 75 enabled: true,
87 transcoding: { 76 allowReplay: true,
88 enabled: false 77 transcoding: {
78 enabled: false
79 }
89 } 80 }
90 } 81 }
91 }) 82 })
92 83
93 { 84 {
94 const res = await generateUser(servers[0], 'user1') 85 const res = await servers[0].users.generate('user1')
95 userId = res.userId 86 userId = res.userId
96 userChannelId = res.userChannelId 87 userChannelId = res.userChannelId
97 userAccessToken = res.token 88 userAccessToken = res.token
@@ -107,7 +98,7 @@ describe('Test live constraints', function () {
107 this.timeout(60000) 98 this.timeout(60000)
108 99
109 const userVideoLiveoId = await createLiveWrapper(false) 100 const userVideoLiveoId = await createLiveWrapper(false)
110 await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, false) 101 await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
111 }) 102 })
112 103
113 it('Should have size limit depending on user global quota if save replay is enabled', async function () { 104 it('Should have size limit depending on user global quota if save replay is enabled', async function () {
@@ -117,7 +108,7 @@ describe('Test live constraints', function () {
117 await wait(5000) 108 await wait(5000)
118 109
119 const userVideoLiveoId = await createLiveWrapper(true) 110 const userVideoLiveoId = await createLiveWrapper(true)
120 await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true) 111 await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
121 112
122 await waitUntilLivePublishedOnAllServers(userVideoLiveoId) 113 await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
123 await waitJobs(servers) 114 await waitJobs(servers)
@@ -134,7 +125,7 @@ describe('Test live constraints', function () {
134 await updateQuota({ total: -1, daily: 1 }) 125 await updateQuota({ total: -1, daily: 1 })
135 126
136 const userVideoLiveoId = await createLiveWrapper(true) 127 const userVideoLiveoId = await createLiveWrapper(true)
137 await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true) 128 await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
138 129
139 await waitUntilLivePublishedOnAllServers(userVideoLiveoId) 130 await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
140 await waitJobs(servers) 131 await waitJobs(servers)
@@ -151,26 +142,28 @@ describe('Test live constraints', function () {
151 await updateQuota({ total: 10 * 1000 * 1000, daily: -1 }) 142 await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
152 143
153 const userVideoLiveoId = await createLiveWrapper(true) 144 const userVideoLiveoId = await createLiveWrapper(true)
154 await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, false) 145 await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
155 }) 146 })
156 147
157 it('Should have max duration limit', async function () { 148 it('Should have max duration limit', async function () {
158 this.timeout(60000) 149 this.timeout(60000)
159 150
160 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 151 await servers[0].config.updateCustomSubConfig({
161 live: { 152 newConfig: {
162 enabled: true, 153 live: {
163 allowReplay: true,
164 maxDuration: 1,
165 transcoding: {
166 enabled: true, 154 enabled: true,
167 resolutions: getCustomConfigResolutions(true) 155 allowReplay: true,
156 maxDuration: 1,
157 transcoding: {
158 enabled: true,
159 resolutions: ConfigCommand.getCustomConfigResolutions(true)
160 }
168 } 161 }
169 } 162 }
170 }) 163 })
171 164
172 const userVideoLiveoId = await createLiveWrapper(true) 165 const userVideoLiveoId = await createLiveWrapper(true)
173 await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true) 166 await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
174 167
175 await waitUntilLivePublishedOnAllServers(userVideoLiveoId) 168 await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
176 await waitJobs(servers) 169 await waitJobs(servers)
diff --git a/server/tests/api/live/live-permanent.ts b/server/tests/api/live/live-permanent.ts
index 71b7d28a8..f07d4cfec 100644
--- a/server/tests/api/live/live-permanent.ts
+++ b/server/tests/api/live/live-permanent.ts
@@ -2,59 +2,50 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared/models' 5import { LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
8 createLive, 8 ConfigCommand,
9 createMultipleServers,
9 doubleFollow, 10 doubleFollow,
10 flushAndRunMultipleServers, 11 PeerTubeServer,
11 getCustomConfigResolutions,
12 getLive,
13 getPlaylistsCount,
14 getVideo,
15 sendRTMPStreamInVideo,
16 ServerInfo,
17 setAccessTokensToServers, 12 setAccessTokensToServers,
18 setDefaultVideoChannel, 13 setDefaultVideoChannel,
19 stopFfmpeg, 14 stopFfmpeg,
20 updateCustomSubConfig,
21 updateLive,
22 wait, 15 wait,
23 waitJobs, 16 waitJobs
24 waitUntilLivePublished,
25 waitUntilLiveWaiting
26} from '../../../../shared/extra-utils' 17} from '../../../../shared/extra-utils'
27 18
28const expect = chai.expect 19const expect = chai.expect
29 20
30describe('Permanent live', function () { 21describe('Permanent live', function () {
31 let servers: ServerInfo[] = [] 22 let servers: PeerTubeServer[] = []
32 let videoUUID: string 23 let videoUUID: string
33 24
34 async function createLiveWrapper (permanentLive: boolean) { 25 async function createLiveWrapper (permanentLive: boolean) {
35 const attributes: LiveVideoCreate = { 26 const attributes: LiveVideoCreate = {
36 channelId: servers[0].videoChannel.id, 27 channelId: servers[0].store.channel.id,
37 privacy: VideoPrivacy.PUBLIC, 28 privacy: VideoPrivacy.PUBLIC,
38 name: 'my super live', 29 name: 'my super live',
39 saveReplay: false, 30 saveReplay: false,
40 permanentLive 31 permanentLive
41 } 32 }
42 33
43 const res = await createLive(servers[0].url, servers[0].accessToken, attributes) 34 const { uuid } = await servers[0].live.create({ fields: attributes })
44 return res.body.video.uuid 35 return uuid
45 } 36 }
46 37
47 async function checkVideoState (videoId: string, state: VideoState) { 38 async function checkVideoState (videoId: string, state: VideoState) {
48 for (const server of servers) { 39 for (const server of servers) {
49 const res = await getVideo(server.url, videoId) 40 const video = await server.videos.get({ id: videoId })
50 expect((res.body as VideoDetails).state.id).to.equal(state) 41 expect(video.state.id).to.equal(state)
51 } 42 }
52 } 43 }
53 44
54 before(async function () { 45 before(async function () {
55 this.timeout(120000) 46 this.timeout(120000)
56 47
57 servers = await flushAndRunMultipleServers(2) 48 servers = await createMultipleServers(2)
58 49
59 // Get the access tokens 50 // Get the access tokens
60 await setAccessTokensToServers(servers) 51 await setAccessTokensToServers(servers)
@@ -63,14 +54,16 @@ describe('Permanent live', function () {
63 // Server 1 and server 2 follow each other 54 // Server 1 and server 2 follow each other
64 await doubleFollow(servers[0], servers[1]) 55 await doubleFollow(servers[0], servers[1])
65 56
66 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 57 await servers[0].config.updateCustomSubConfig({
67 live: { 58 newConfig: {
68 enabled: true, 59 live: {
69 allowReplay: true,
70 maxDuration: -1,
71 transcoding: {
72 enabled: true, 60 enabled: true,
73 resolutions: getCustomConfigResolutions(true) 61 allowReplay: true,
62 maxDuration: -1,
63 transcoding: {
64 enabled: true,
65 resolutions: ConfigCommand.getCustomConfigResolutions(true)
66 }
74 } 67 }
75 } 68 }
76 }) 69 })
@@ -82,15 +75,15 @@ describe('Permanent live', function () {
82 const videoUUID = await createLiveWrapper(false) 75 const videoUUID = await createLiveWrapper(false)
83 76
84 { 77 {
85 const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID) 78 const live = await servers[0].live.get({ videoId: videoUUID })
86 expect(res.body.permanentLive).to.be.false 79 expect(live.permanentLive).to.be.false
87 } 80 }
88 81
89 await updateLive(servers[0].url, servers[0].accessToken, videoUUID, { permanentLive: true }) 82 await servers[0].live.update({ videoId: videoUUID, fields: { permanentLive: true } })
90 83
91 { 84 {
92 const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID) 85 const live = await servers[0].live.get({ videoId: videoUUID })
93 expect(res.body.permanentLive).to.be.true 86 expect(live.permanentLive).to.be.true
94 } 87 }
95 }) 88 })
96 89
@@ -99,8 +92,8 @@ describe('Permanent live', function () {
99 92
100 videoUUID = await createLiveWrapper(true) 93 videoUUID = await createLiveWrapper(true)
101 94
102 const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID) 95 const live = await servers[0].live.get({ videoId: videoUUID })
103 expect(res.body.permanentLive).to.be.true 96 expect(live.permanentLive).to.be.true
104 97
105 await waitJobs(servers) 98 await waitJobs(servers)
106 }) 99 })
@@ -108,16 +101,16 @@ describe('Permanent live', function () {
108 it('Should stream into this permanent live', async function () { 101 it('Should stream into this permanent live', async function () {
109 this.timeout(120000) 102 this.timeout(120000)
110 103
111 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID) 104 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
112 105
113 for (const server of servers) { 106 for (const server of servers) {
114 await waitUntilLivePublished(server.url, server.accessToken, videoUUID) 107 await server.live.waitUntilPublished({ videoId: videoUUID })
115 } 108 }
116 109
117 await checkVideoState(videoUUID, VideoState.PUBLISHED) 110 await checkVideoState(videoUUID, VideoState.PUBLISHED)
118 111
119 await stopFfmpeg(command) 112 await stopFfmpeg(ffmpegCommand)
120 await waitUntilLiveWaiting(servers[0].url, servers[0].accessToken, videoUUID) 113 await servers[0].live.waitUntilWaiting({ videoId: videoUUID })
121 114
122 await waitJobs(servers) 115 await waitJobs(servers)
123 }) 116 })
@@ -129,9 +122,7 @@ describe('Permanent live', function () {
129 await waitJobs(servers) 122 await waitJobs(servers)
130 123
131 for (const server of servers) { 124 for (const server of servers) {
132 const res = await getVideo(server.url, videoUUID) 125 const videoDetails = await server.videos.get({ id: videoUUID })
133
134 const videoDetails = res.body as VideoDetails
135 expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) 126 expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
136 } 127 }
137 }) 128 })
@@ -145,31 +136,33 @@ describe('Permanent live', function () {
145 it('Should be able to stream again in the permanent live', async function () { 136 it('Should be able to stream again in the permanent live', async function () {
146 this.timeout(20000) 137 this.timeout(20000)
147 138
148 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 139 await servers[0].config.updateCustomSubConfig({
149 live: { 140 newConfig: {
150 enabled: true, 141 live: {
151 allowReplay: true,
152 maxDuration: -1,
153 transcoding: {
154 enabled: true, 142 enabled: true,
155 resolutions: getCustomConfigResolutions(false) 143 allowReplay: true,
144 maxDuration: -1,
145 transcoding: {
146 enabled: true,
147 resolutions: ConfigCommand.getCustomConfigResolutions(false)
148 }
156 } 149 }
157 } 150 }
158 }) 151 })
159 152
160 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID) 153 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
161 154
162 for (const server of servers) { 155 for (const server of servers) {
163 await waitUntilLivePublished(server.url, server.accessToken, videoUUID) 156 await server.live.waitUntilPublished({ videoId: videoUUID })
164 } 157 }
165 158
166 await checkVideoState(videoUUID, VideoState.PUBLISHED) 159 await checkVideoState(videoUUID, VideoState.PUBLISHED)
167 160
168 const count = await getPlaylistsCount(servers[0], videoUUID) 161 const count = await servers[0].live.countPlaylists({ videoUUID })
169 // master playlist and 720p playlist 162 // master playlist and 720p playlist
170 expect(count).to.equal(2) 163 expect(count).to.equal(2)
171 164
172 await stopFfmpeg(command) 165 await stopFfmpeg(ffmpegCommand)
173 }) 166 })
174 167
175 after(async function () { 168 after(async function () {
diff --git a/server/tests/api/live/live-save-replay.ts b/server/tests/api/live/live-save-replay.ts
index 3d4736c8f..8f1fb78a5 100644
--- a/server/tests/api/live/live-save-replay.ts
+++ b/server/tests/api/live/live-save-replay.ts
@@ -3,97 +3,85 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { FfmpegCommand } from 'fluent-ffmpeg' 5import { FfmpegCommand } from 'fluent-ffmpeg'
6import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared/models'
7import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
8import { 6import {
9 addVideoToBlacklist, 7 checkLiveCleanupAfterSave,
10 checkLiveCleanup,
11 cleanupTests, 8 cleanupTests,
12 createLive, 9 ConfigCommand,
10 createMultipleServers,
13 doubleFollow, 11 doubleFollow,
14 flushAndRunMultipleServers, 12 PeerTubeServer,
15 getCustomConfigResolutions,
16 getVideo,
17 getVideosList,
18 removeVideo,
19 sendRTMPStreamInVideo,
20 ServerInfo,
21 setAccessTokensToServers, 13 setAccessTokensToServers,
22 setDefaultVideoChannel, 14 setDefaultVideoChannel,
23 stopFfmpeg, 15 stopFfmpeg,
24 testFfmpegStreamError, 16 testFfmpegStreamError,
25 updateCustomSubConfig,
26 updateVideo,
27 wait, 17 wait,
28 waitJobs, 18 waitJobs
29 waitUntilLiveEnded, 19} from '@shared/extra-utils'
30 waitUntilLivePublished, 20import { HttpStatusCode, LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
31 waitUntilLiveSaved
32} from '../../../../shared/extra-utils'
33 21
34const expect = chai.expect 22const expect = chai.expect
35 23
36describe('Save replay setting', function () { 24describe('Save replay setting', function () {
37 let servers: ServerInfo[] = [] 25 let servers: PeerTubeServer[] = []
38 let liveVideoUUID: string 26 let liveVideoUUID: string
39 let ffmpegCommand: FfmpegCommand 27 let ffmpegCommand: FfmpegCommand
40 28
41 async function createLiveWrapper (saveReplay: boolean) { 29 async function createLiveWrapper (saveReplay: boolean) {
42 if (liveVideoUUID) { 30 if (liveVideoUUID) {
43 try { 31 try {
44 await removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 32 await servers[0].videos.remove({ id: liveVideoUUID })
45 await waitJobs(servers) 33 await waitJobs(servers)
46 } catch {} 34 } catch {}
47 } 35 }
48 36
49 const attributes: LiveVideoCreate = { 37 const attributes: LiveVideoCreate = {
50 channelId: servers[0].videoChannel.id, 38 channelId: servers[0].store.channel.id,
51 privacy: VideoPrivacy.PUBLIC, 39 privacy: VideoPrivacy.PUBLIC,
52 name: 'my super live', 40 name: 'my super live',
53 saveReplay 41 saveReplay
54 } 42 }
55 43
56 const res = await createLive(servers[0].url, servers[0].accessToken, attributes) 44 const { uuid } = await servers[0].live.create({ fields: attributes })
57 return res.body.video.uuid 45 return uuid
58 } 46 }
59 47
60 async function checkVideosExist (videoId: string, existsInList: boolean, getStatus?: number) { 48 async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
61 for (const server of servers) { 49 for (const server of servers) {
62 const length = existsInList ? 1 : 0 50 const length = existsInList ? 1 : 0
63 51
64 const resVideos = await getVideosList(server.url) 52 const { data, total } = await server.videos.list()
65 expect(resVideos.body.data).to.have.lengthOf(length) 53 expect(data).to.have.lengthOf(length)
66 expect(resVideos.body.total).to.equal(length) 54 expect(total).to.equal(length)
67 55
68 if (getStatus) { 56 if (expectedStatus) {
69 await getVideo(server.url, videoId, getStatus) 57 await server.videos.get({ id: videoId, expectedStatus })
70 } 58 }
71 } 59 }
72 } 60 }
73 61
74 async function checkVideoState (videoId: string, state: VideoState) { 62 async function checkVideoState (videoId: string, state: VideoState) {
75 for (const server of servers) { 63 for (const server of servers) {
76 const res = await getVideo(server.url, videoId) 64 const video = await server.videos.get({ id: videoId })
77 expect((res.body as VideoDetails).state.id).to.equal(state) 65 expect(video.state.id).to.equal(state)
78 } 66 }
79 } 67 }
80 68
81 async function waitUntilLivePublishedOnAllServers (videoId: string) { 69 async function waitUntilLivePublishedOnAllServers (videoId: string) {
82 for (const server of servers) { 70 for (const server of servers) {
83 await waitUntilLivePublished(server.url, server.accessToken, videoId) 71 await server.live.waitUntilPublished({ videoId })
84 } 72 }
85 } 73 }
86 74
87 async function waitUntilLiveSavedOnAllServers (videoId: string) { 75 async function waitUntilLiveSavedOnAllServers (videoId: string) {
88 for (const server of servers) { 76 for (const server of servers) {
89 await waitUntilLiveSaved(server.url, server.accessToken, videoId) 77 await server.live.waitUntilSaved({ videoId })
90 } 78 }
91 } 79 }
92 80
93 before(async function () { 81 before(async function () {
94 this.timeout(120000) 82 this.timeout(120000)
95 83
96 servers = await flushAndRunMultipleServers(2) 84 servers = await createMultipleServers(2)
97 85
98 // Get the access tokens 86 // Get the access tokens
99 await setAccessTokensToServers(servers) 87 await setAccessTokensToServers(servers)
@@ -102,14 +90,16 @@ describe('Save replay setting', function () {
102 // Server 1 and server 2 follow each other 90 // Server 1 and server 2 follow each other
103 await doubleFollow(servers[0], servers[1]) 91 await doubleFollow(servers[0], servers[1])
104 92
105 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 93 await servers[0].config.updateCustomSubConfig({
106 live: { 94 newConfig: {
107 enabled: true, 95 live: {
108 allowReplay: true, 96 enabled: true,
109 maxDuration: -1, 97 allowReplay: true,
110 transcoding: { 98 maxDuration: -1,
111 enabled: false, 99 transcoding: {
112 resolutions: getCustomConfigResolutions(true) 100 enabled: false,
101 resolutions: ConfigCommand.getCustomConfigResolutions(true)
102 }
113 } 103 }
114 } 104 }
115 }) 105 })
@@ -135,7 +125,7 @@ describe('Save replay setting', function () {
135 it('Should correctly have updated the live and federated it when streaming in the live', async function () { 125 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
136 this.timeout(30000) 126 this.timeout(30000)
137 127
138 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 128 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
139 129
140 await waitUntilLivePublishedOnAllServers(liveVideoUUID) 130 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
141 131
@@ -151,7 +141,7 @@ describe('Save replay setting', function () {
151 await stopFfmpeg(ffmpegCommand) 141 await stopFfmpeg(ffmpegCommand)
152 142
153 for (const server of servers) { 143 for (const server of servers) {
154 await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID) 144 await server.live.waitUntilEnded({ videoId: liveVideoUUID })
155 } 145 }
156 await waitJobs(servers) 146 await waitJobs(servers)
157 147
@@ -160,7 +150,7 @@ describe('Save replay setting', function () {
160 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED) 150 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
161 151
162 // No resolutions saved since we did not save replay 152 // No resolutions saved since we did not save replay
163 await checkLiveCleanup(servers[0], liveVideoUUID, []) 153 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
164 }) 154 })
165 155
166 it('Should correctly terminate the stream on blacklist and delete the live', async function () { 156 it('Should correctly terminate the stream on blacklist and delete the live', async function () {
@@ -168,7 +158,7 @@ describe('Save replay setting', function () {
168 158
169 liveVideoUUID = await createLiveWrapper(false) 159 liveVideoUUID = await createLiveWrapper(false)
170 160
171 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 161 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
172 162
173 await waitUntilLivePublishedOnAllServers(liveVideoUUID) 163 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
174 164
@@ -176,7 +166,7 @@ describe('Save replay setting', function () {
176 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) 166 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
177 167
178 await Promise.all([ 168 await Promise.all([
179 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true), 169 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
180 testFfmpegStreamError(ffmpegCommand, true) 170 testFfmpegStreamError(ffmpegCommand, true)
181 ]) 171 ])
182 172
@@ -184,12 +174,12 @@ describe('Save replay setting', function () {
184 174
185 await checkVideosExist(liveVideoUUID, false) 175 await checkVideosExist(liveVideoUUID, false)
186 176
187 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401) 177 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
188 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404) 178 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
189 179
190 await wait(5000) 180 await wait(5000)
191 await waitJobs(servers) 181 await waitJobs(servers)
192 await checkLiveCleanup(servers[0], liveVideoUUID, []) 182 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
193 }) 183 })
194 184
195 it('Should correctly terminate the stream on delete and delete the video', async function () { 185 it('Should correctly terminate the stream on delete and delete the video', async function () {
@@ -197,7 +187,7 @@ describe('Save replay setting', function () {
197 187
198 liveVideoUUID = await createLiveWrapper(false) 188 liveVideoUUID = await createLiveWrapper(false)
199 189
200 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 190 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
201 191
202 await waitUntilLivePublishedOnAllServers(liveVideoUUID) 192 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
203 193
@@ -206,14 +196,14 @@ describe('Save replay setting', function () {
206 196
207 await Promise.all([ 197 await Promise.all([
208 testFfmpegStreamError(ffmpegCommand, true), 198 testFfmpegStreamError(ffmpegCommand, true),
209 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 199 servers[0].videos.remove({ id: liveVideoUUID })
210 ]) 200 ])
211 201
212 await wait(5000) 202 await wait(5000)
213 await waitJobs(servers) 203 await waitJobs(servers)
214 204
215 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404) 205 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
216 await checkLiveCleanup(servers[0], liveVideoUUID, []) 206 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
217 }) 207 })
218 }) 208 })
219 209
@@ -233,7 +223,7 @@ describe('Save replay setting', function () {
233 it('Should correctly have updated the live and federated it when streaming in the live', async function () { 223 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
234 this.timeout(20000) 224 this.timeout(20000)
235 225
236 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 226 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
237 await waitUntilLivePublishedOnAllServers(liveVideoUUID) 227 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
238 228
239 await waitJobs(servers) 229 await waitJobs(servers)
@@ -258,18 +248,18 @@ describe('Save replay setting', function () {
258 it('Should update the saved live and correctly federate the updated attributes', async function () { 248 it('Should update the saved live and correctly federate the updated attributes', async function () {
259 this.timeout(30000) 249 this.timeout(30000)
260 250
261 await updateVideo(servers[0].url, servers[0].accessToken, liveVideoUUID, { name: 'video updated' }) 251 await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated' } })
262 await waitJobs(servers) 252 await waitJobs(servers)
263 253
264 for (const server of servers) { 254 for (const server of servers) {
265 const res = await getVideo(server.url, liveVideoUUID) 255 const video = await server.videos.get({ id: liveVideoUUID })
266 expect(res.body.name).to.equal('video updated') 256 expect(video.name).to.equal('video updated')
267 expect(res.body.isLive).to.be.false 257 expect(video.isLive).to.be.false
268 } 258 }
269 }) 259 })
270 260
271 it('Should have cleaned up the live files', async function () { 261 it('Should have cleaned up the live files', async function () {
272 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ]) 262 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
273 }) 263 })
274 264
275 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () { 265 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
@@ -277,14 +267,14 @@ describe('Save replay setting', function () {
277 267
278 liveVideoUUID = await createLiveWrapper(true) 268 liveVideoUUID = await createLiveWrapper(true)
279 269
280 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 270 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
281 await waitUntilLivePublishedOnAllServers(liveVideoUUID) 271 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
282 272
283 await waitJobs(servers) 273 await waitJobs(servers)
284 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) 274 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
285 275
286 await Promise.all([ 276 await Promise.all([
287 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true), 277 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
288 testFfmpegStreamError(ffmpegCommand, true) 278 testFfmpegStreamError(ffmpegCommand, true)
289 ]) 279 ])
290 280
@@ -292,12 +282,12 @@ describe('Save replay setting', function () {
292 282
293 await checkVideosExist(liveVideoUUID, false) 283 await checkVideosExist(liveVideoUUID, false)
294 284
295 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401) 285 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
296 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404) 286 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
297 287
298 await wait(5000) 288 await wait(5000)
299 await waitJobs(servers) 289 await waitJobs(servers)
300 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ]) 290 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
301 }) 291 })
302 292
303 it('Should correctly terminate the stream on delete and delete the video', async function () { 293 it('Should correctly terminate the stream on delete and delete the video', async function () {
@@ -305,14 +295,14 @@ describe('Save replay setting', function () {
305 295
306 liveVideoUUID = await createLiveWrapper(true) 296 liveVideoUUID = await createLiveWrapper(true)
307 297
308 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 298 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
309 await waitUntilLivePublishedOnAllServers(liveVideoUUID) 299 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
310 300
311 await waitJobs(servers) 301 await waitJobs(servers)
312 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) 302 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
313 303
314 await Promise.all([ 304 await Promise.all([
315 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID), 305 servers[0].videos.remove({ id: liveVideoUUID }),
316 testFfmpegStreamError(ffmpegCommand, true) 306 testFfmpegStreamError(ffmpegCommand, true)
317 ]) 307 ])
318 308
@@ -320,7 +310,7 @@ describe('Save replay setting', function () {
320 await waitJobs(servers) 310 await waitJobs(servers)
321 311
322 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404) 312 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
323 await checkLiveCleanup(servers[0], liveVideoUUID, []) 313 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
324 }) 314 })
325 }) 315 })
326 316
diff --git a/server/tests/api/live/live-socket-messages.ts b/server/tests/api/live/live-socket-messages.ts
index e00909ade..2a1f9f108 100644
--- a/server/tests/api/live/live-socket-messages.ts
+++ b/server/tests/api/live/live-socket-messages.ts
@@ -2,47 +2,42 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { getLiveNotificationSocket } from '@shared/extra-utils/socket/socket-io'
6import { VideoPrivacy, VideoState } from '@shared/models' 5import { VideoPrivacy, VideoState } from '@shared/models'
7import { 6import {
8 cleanupTests, 7 cleanupTests,
9 createLive, 8 createMultipleServers,
10 doubleFollow, 9 doubleFollow,
11 flushAndRunMultipleServers, 10 PeerTubeServer,
12 getVideoIdFromUUID,
13 sendRTMPStreamInVideo,
14 ServerInfo,
15 setAccessTokensToServers, 11 setAccessTokensToServers,
16 setDefaultVideoChannel, 12 setDefaultVideoChannel,
17 stopFfmpeg, 13 stopFfmpeg,
18 updateCustomSubConfig,
19 viewVideo,
20 wait, 14 wait,
21 waitJobs, 15 waitJobs,
22 waitUntilLiveEnded,
23 waitUntilLivePublishedOnAllServers 16 waitUntilLivePublishedOnAllServers
24} from '../../../../shared/extra-utils' 17} from '../../../../shared/extra-utils'
25 18
26const expect = chai.expect 19const expect = chai.expect
27 20
28describe('Test live', function () { 21describe('Test live', function () {
29 let servers: ServerInfo[] = [] 22 let servers: PeerTubeServer[] = []
30 23
31 before(async function () { 24 before(async function () {
32 this.timeout(120000) 25 this.timeout(120000)
33 26
34 servers = await flushAndRunMultipleServers(2) 27 servers = await createMultipleServers(2)
35 28
36 // Get the access tokens 29 // Get the access tokens
37 await setAccessTokensToServers(servers) 30 await setAccessTokensToServers(servers)
38 await setDefaultVideoChannel(servers) 31 await setDefaultVideoChannel(servers)
39 32
40 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 33 await servers[0].config.updateCustomSubConfig({
41 live: { 34 newConfig: {
42 enabled: true, 35 live: {
43 allowReplay: true, 36 enabled: true,
44 transcoding: { 37 allowReplay: true,
45 enabled: false 38 transcoding: {
39 enabled: false
40 }
46 } 41 }
47 } 42 }
48 }) 43 })
@@ -56,12 +51,12 @@ describe('Test live', function () {
56 async function createLiveWrapper () { 51 async function createLiveWrapper () {
57 const liveAttributes = { 52 const liveAttributes = {
58 name: 'live video', 53 name: 'live video',
59 channelId: servers[0].videoChannel.id, 54 channelId: servers[0].store.channel.id,
60 privacy: VideoPrivacy.PUBLIC 55 privacy: VideoPrivacy.PUBLIC
61 } 56 }
62 57
63 const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) 58 const { uuid } = await servers[0].live.create({ fields: liveAttributes })
64 return res.body.video.uuid 59 return uuid
65 } 60 }
66 61
67 it('Should correctly send a message when the live starts and ends', async function () { 62 it('Should correctly send a message when the live starts and ends', async function () {
@@ -74,22 +69,22 @@ describe('Test live', function () {
74 await waitJobs(servers) 69 await waitJobs(servers)
75 70
76 { 71 {
77 const videoId = await getVideoIdFromUUID(servers[0].url, liveVideoUUID) 72 const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
78 73
79 const localSocket = getLiveNotificationSocket(servers[0].url) 74 const localSocket = servers[0].socketIO.getLiveNotificationSocket()
80 localSocket.on('state-change', data => localStateChanges.push(data.state)) 75 localSocket.on('state-change', data => localStateChanges.push(data.state))
81 localSocket.emit('subscribe', { videoId }) 76 localSocket.emit('subscribe', { videoId })
82 } 77 }
83 78
84 { 79 {
85 const videoId = await getVideoIdFromUUID(servers[1].url, liveVideoUUID) 80 const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
86 81
87 const remoteSocket = getLiveNotificationSocket(servers[1].url) 82 const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
88 remoteSocket.on('state-change', data => remoteStateChanges.push(data.state)) 83 remoteSocket.on('state-change', data => remoteStateChanges.push(data.state))
89 remoteSocket.emit('subscribe', { videoId }) 84 remoteSocket.emit('subscribe', { videoId })
90 } 85 }
91 86
92 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 87 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
93 88
94 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) 89 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
95 await waitJobs(servers) 90 await waitJobs(servers)
@@ -99,10 +94,10 @@ describe('Test live', function () {
99 expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED) 94 expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
100 } 95 }
101 96
102 await stopFfmpeg(command) 97 await stopFfmpeg(ffmpegCommand)
103 98
104 for (const server of servers) { 99 for (const server of servers) {
105 await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID) 100 await server.live.waitUntilEnded({ videoId: liveVideoUUID })
106 } 101 }
107 await waitJobs(servers) 102 await waitJobs(servers)
108 103
@@ -122,22 +117,22 @@ describe('Test live', function () {
122 await waitJobs(servers) 117 await waitJobs(servers)
123 118
124 { 119 {
125 const videoId = await getVideoIdFromUUID(servers[0].url, liveVideoUUID) 120 const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
126 121
127 const localSocket = getLiveNotificationSocket(servers[0].url) 122 const localSocket = servers[0].socketIO.getLiveNotificationSocket()
128 localSocket.on('views-change', data => { localLastVideoViews = data.views }) 123 localSocket.on('views-change', data => { localLastVideoViews = data.views })
129 localSocket.emit('subscribe', { videoId }) 124 localSocket.emit('subscribe', { videoId })
130 } 125 }
131 126
132 { 127 {
133 const videoId = await getVideoIdFromUUID(servers[1].url, liveVideoUUID) 128 const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
134 129
135 const remoteSocket = getLiveNotificationSocket(servers[1].url) 130 const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
136 remoteSocket.on('views-change', data => { remoteLastVideoViews = data.views }) 131 remoteSocket.on('views-change', data => { remoteLastVideoViews = data.views })
137 remoteSocket.emit('subscribe', { videoId }) 132 remoteSocket.emit('subscribe', { videoId })
138 } 133 }
139 134
140 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 135 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
141 136
142 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) 137 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
143 await waitJobs(servers) 138 await waitJobs(servers)
@@ -145,8 +140,8 @@ describe('Test live', function () {
145 expect(localLastVideoViews).to.equal(0) 140 expect(localLastVideoViews).to.equal(0)
146 expect(remoteLastVideoViews).to.equal(0) 141 expect(remoteLastVideoViews).to.equal(0)
147 142
148 await viewVideo(servers[0].url, liveVideoUUID) 143 await servers[0].videos.view({ id: liveVideoUUID })
149 await viewVideo(servers[1].url, liveVideoUUID) 144 await servers[1].videos.view({ id: liveVideoUUID })
150 145
151 await waitJobs(servers) 146 await waitJobs(servers)
152 await wait(5000) 147 await wait(5000)
@@ -155,7 +150,7 @@ describe('Test live', function () {
155 expect(localLastVideoViews).to.equal(2) 150 expect(localLastVideoViews).to.equal(2)
156 expect(remoteLastVideoViews).to.equal(2) 151 expect(remoteLastVideoViews).to.equal(2)
157 152
158 await stopFfmpeg(command) 153 await stopFfmpeg(ffmpegCommand)
159 }) 154 })
160 155
161 it('Should not receive a notification after unsubscribe', async function () { 156 it('Should not receive a notification after unsubscribe', async function () {
@@ -166,13 +161,13 @@ describe('Test live', function () {
166 const liveVideoUUID = await createLiveWrapper() 161 const liveVideoUUID = await createLiveWrapper()
167 await waitJobs(servers) 162 await waitJobs(servers)
168 163
169 const videoId = await getVideoIdFromUUID(servers[0].url, liveVideoUUID) 164 const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
170 165
171 const socket = getLiveNotificationSocket(servers[0].url) 166 const socket = servers[0].socketIO.getLiveNotificationSocket()
172 socket.on('state-change', data => stateChanges.push(data.state)) 167 socket.on('state-change', data => stateChanges.push(data.state))
173 socket.emit('subscribe', { videoId }) 168 socket.emit('subscribe', { videoId })
174 169
175 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 170 const command = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
176 171
177 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) 172 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
178 await waitJobs(servers) 173 await waitJobs(servers)
diff --git a/server/tests/api/live/live-views.ts b/server/tests/api/live/live-views.ts
index a44d21ffa..5e3a79c64 100644
--- a/server/tests/api/live/live-views.ts
+++ b/server/tests/api/live/live-views.ts
@@ -3,20 +3,15 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { FfmpegCommand } from 'fluent-ffmpeg' 5import { FfmpegCommand } from 'fluent-ffmpeg'
6import { VideoDetails, VideoPrivacy } from '@shared/models' 6import { VideoPrivacy } from '@shared/models'
7import { 7import {
8 cleanupTests, 8 cleanupTests,
9 createLive, 9 createMultipleServers,
10 doubleFollow, 10 doubleFollow,
11 flushAndRunMultipleServers, 11 PeerTubeServer,
12 getVideo,
13 sendRTMPStreamInVideo,
14 ServerInfo,
15 setAccessTokensToServers, 12 setAccessTokensToServers,
16 setDefaultVideoChannel, 13 setDefaultVideoChannel,
17 stopFfmpeg, 14 stopFfmpeg,
18 updateCustomSubConfig,
19 viewVideo,
20 wait, 15 wait,
21 waitJobs, 16 waitJobs,
22 waitUntilLivePublishedOnAllServers 17 waitUntilLivePublishedOnAllServers
@@ -25,23 +20,25 @@ import {
25const expect = chai.expect 20const expect = chai.expect
26 21
27describe('Test live', function () { 22describe('Test live', function () {
28 let servers: ServerInfo[] = [] 23 let servers: PeerTubeServer[] = []
29 24
30 before(async function () { 25 before(async function () {
31 this.timeout(120000) 26 this.timeout(120000)
32 27
33 servers = await flushAndRunMultipleServers(2) 28 servers = await createMultipleServers(2)
34 29
35 // Get the access tokens 30 // Get the access tokens
36 await setAccessTokensToServers(servers) 31 await setAccessTokensToServers(servers)
37 await setDefaultVideoChannel(servers) 32 await setDefaultVideoChannel(servers)
38 33
39 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 34 await servers[0].config.updateCustomSubConfig({
40 live: { 35 newConfig: {
41 enabled: true, 36 live: {
42 allowReplay: true, 37 enabled: true,
43 transcoding: { 38 allowReplay: true,
44 enabled: false 39 transcoding: {
40 enabled: false
41 }
45 } 42 }
46 } 43 }
47 }) 44 })
@@ -56,9 +53,7 @@ describe('Test live', function () {
56 53
57 async function countViews (expected: number) { 54 async function countViews (expected: number) {
58 for (const server of servers) { 55 for (const server of servers) {
59 const res = await getVideo(server.url, liveVideoId) 56 const video = await server.videos.get({ id: liveVideoId })
60 const video: VideoDetails = res.body
61
62 expect(video.views).to.equal(expected) 57 expect(video.views).to.equal(expected)
63 } 58 }
64 } 59 }
@@ -68,14 +63,14 @@ describe('Test live', function () {
68 63
69 const liveAttributes = { 64 const liveAttributes = {
70 name: 'live video', 65 name: 'live video',
71 channelId: servers[0].videoChannel.id, 66 channelId: servers[0].store.channel.id,
72 privacy: VideoPrivacy.PUBLIC 67 privacy: VideoPrivacy.PUBLIC
73 } 68 }
74 69
75 const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) 70 const live = await servers[0].live.create({ fields: liveAttributes })
76 liveVideoId = res.body.video.uuid 71 liveVideoId = live.uuid
77 72
78 command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) 73 command = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId })
79 await waitUntilLivePublishedOnAllServers(servers, liveVideoId) 74 await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
80 await waitJobs(servers) 75 await waitJobs(servers)
81 }) 76 })
@@ -87,8 +82,8 @@ describe('Test live', function () {
87 it('Should view a live twice and display 1 view', async function () { 82 it('Should view a live twice and display 1 view', async function () {
88 this.timeout(30000) 83 this.timeout(30000)
89 84
90 await viewVideo(servers[0].url, liveVideoId) 85 await servers[0].videos.view({ id: liveVideoId })
91 await viewVideo(servers[0].url, liveVideoId) 86 await servers[0].videos.view({ id: liveVideoId })
92 87
93 await wait(7000) 88 await wait(7000)
94 89
@@ -109,9 +104,9 @@ describe('Test live', function () {
109 it('Should view a live on a remote and on local and display 2 views', async function () { 104 it('Should view a live on a remote and on local and display 2 views', async function () {
110 this.timeout(30000) 105 this.timeout(30000)
111 106
112 await viewVideo(servers[0].url, liveVideoId) 107 await servers[0].videos.view({ id: liveVideoId })
113 await viewVideo(servers[1].url, liveVideoId) 108 await servers[1].videos.view({ id: liveVideoId })
114 await viewVideo(servers[1].url, liveVideoId) 109 await servers[1].videos.view({ id: liveVideoId })
115 110
116 await wait(7000) 111 await wait(7000)
117 await waitJobs(servers) 112 await waitJobs(servers)
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts
index 50397924e..d555cff19 100644
--- a/server/tests/api/live/live.ts
+++ b/server/tests/api/live/live.ts
@@ -2,75 +2,70 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { join } from 'path' 5import { basename, join } from 'path'
6import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils' 6import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
7import { LiveVideo, LiveVideoCreate, Video, VideoDetails, VideoPrivacy, VideoState, VideoStreamingPlaylistType } from '@shared/models'
8import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
9import { 7import {
10 addVideoToBlacklist, 8 checkLiveCleanupAfterSave,
11 buildServerDirectory,
12 checkLiveCleanup,
13 checkLiveSegmentHash, 9 checkLiveSegmentHash,
14 checkResolutionsInMasterPlaylist, 10 checkResolutionsInMasterPlaylist,
15 cleanupTests, 11 cleanupTests,
16 createLive, 12 createMultipleServers,
17 doubleFollow, 13 doubleFollow,
18 flushAndRunMultipleServers,
19 getLive,
20 getMyVideosWithFilter,
21 getPlaylist,
22 getVideo,
23 getVideosList,
24 getVideosWithFilters,
25 killallServers, 14 killallServers,
15 LiveCommand,
26 makeRawRequest, 16 makeRawRequest,
27 removeVideo, 17 PeerTubeServer,
28 reRunServer,
29 sendRTMPStream, 18 sendRTMPStream,
30 sendRTMPStreamInVideo,
31 ServerInfo,
32 setAccessTokensToServers, 19 setAccessTokensToServers,
33 setDefaultVideoChannel, 20 setDefaultVideoChannel,
34 stopFfmpeg, 21 stopFfmpeg,
35 testFfmpegStreamError, 22 testFfmpegStreamError,
36 testImage, 23 testImage,
37 updateCustomSubConfig,
38 updateLive,
39 uploadVideoAndGetId,
40 wait, 24 wait,
41 waitJobs, 25 waitJobs,
42 waitUntilLiveEnded, 26 waitUntilLivePublishedOnAllServers
43 waitUntilLivePublished, 27} from '@shared/extra-utils'
44 waitUntilLivePublishedOnAllServers, 28import {
45 waitUntilLiveSegmentGeneration 29 HttpStatusCode,
46} from '../../../../shared/extra-utils' 30 LiveVideo,
31 LiveVideoCreate,
32 VideoDetails,
33 VideoPrivacy,
34 VideoState,
35 VideoStreamingPlaylistType
36} from '@shared/models'
47 37
48const expect = chai.expect 38const expect = chai.expect
49 39
50describe('Test live', function () { 40describe('Test live', function () {
51 let servers: ServerInfo[] = [] 41 let servers: PeerTubeServer[] = []
42 let commands: LiveCommand[]
52 43
53 before(async function () { 44 before(async function () {
54 this.timeout(120000) 45 this.timeout(120000)
55 46
56 servers = await flushAndRunMultipleServers(2) 47 servers = await createMultipleServers(2)
57 48
58 // Get the access tokens 49 // Get the access tokens
59 await setAccessTokensToServers(servers) 50 await setAccessTokensToServers(servers)
60 await setDefaultVideoChannel(servers) 51 await setDefaultVideoChannel(servers)
61 52
62 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 53 await servers[0].config.updateCustomSubConfig({
63 live: { 54 newConfig: {
64 enabled: true, 55 live: {
65 allowReplay: true, 56 enabled: true,
66 transcoding: { 57 allowReplay: true,
67 enabled: false 58 transcoding: {
59 enabled: false
60 }
68 } 61 }
69 } 62 }
70 }) 63 })
71 64
72 // Server 1 and server 2 follow each other 65 // Server 1 and server 2 follow each other
73 await doubleFollow(servers[0], servers[1]) 66 await doubleFollow(servers[0], servers[1])
67
68 commands = servers.map(s => s.live)
74 }) 69 })
75 70
76 describe('Live creation, update and delete', function () { 71 describe('Live creation, update and delete', function () {
@@ -85,7 +80,7 @@ describe('Test live', function () {
85 language: 'fr', 80 language: 'fr',
86 description: 'super live description', 81 description: 'super live description',
87 support: 'support field', 82 support: 'support field',
88 channelId: servers[0].videoChannel.id, 83 channelId: servers[0].store.channel.id,
89 nsfw: false, 84 nsfw: false,
90 waitTranscoding: false, 85 waitTranscoding: false,
91 name: 'my super live', 86 name: 'my super live',
@@ -98,14 +93,13 @@ describe('Test live', function () {
98 thumbnailfile: 'video_short1.webm.jpg' 93 thumbnailfile: 'video_short1.webm.jpg'
99 } 94 }
100 95
101 const res = await createLive(servers[0].url, servers[0].accessToken, attributes) 96 const live = await commands[0].create({ fields: attributes })
102 liveVideoUUID = res.body.video.uuid 97 liveVideoUUID = live.uuid
103 98
104 await waitJobs(servers) 99 await waitJobs(servers)
105 100
106 for (const server of servers) { 101 for (const server of servers) {
107 const resVideo = await getVideo(server.url, liveVideoUUID) 102 const video = await server.videos.get({ id: liveVideoUUID })
108 const video: VideoDetails = resVideo.body
109 103
110 expect(video.category.id).to.equal(1) 104 expect(video.category.id).to.equal(1)
111 expect(video.licence.id).to.equal(2) 105 expect(video.licence.id).to.equal(2)
@@ -113,8 +107,8 @@ describe('Test live', function () {
113 expect(video.description).to.equal('super live description') 107 expect(video.description).to.equal('super live description')
114 expect(video.support).to.equal('support field') 108 expect(video.support).to.equal('support field')
115 109
116 expect(video.channel.name).to.equal(servers[0].videoChannel.name) 110 expect(video.channel.name).to.equal(servers[0].store.channel.name)
117 expect(video.channel.host).to.equal(servers[0].videoChannel.host) 111 expect(video.channel.host).to.equal(servers[0].store.channel.host)
118 112
119 expect(video.isLive).to.be.true 113 expect(video.isLive).to.be.true
120 114
@@ -129,8 +123,7 @@ describe('Test live', function () {
129 await testImage(server.url, 'video_short1-preview.webm', video.previewPath) 123 await testImage(server.url, 'video_short1-preview.webm', video.previewPath)
130 await testImage(server.url, 'video_short1.webm', video.thumbnailPath) 124 await testImage(server.url, 'video_short1.webm', video.thumbnailPath)
131 125
132 const resLive = await getLive(server.url, server.accessToken, liveVideoUUID) 126 const live = await server.live.get({ videoId: liveVideoUUID })
133 const live: LiveVideo = resLive.body
134 127
135 if (server.url === servers[0].url) { 128 if (server.url === servers[0].url) {
136 expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live') 129 expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
@@ -149,20 +142,18 @@ describe('Test live', function () {
149 142
150 const attributes: LiveVideoCreate = { 143 const attributes: LiveVideoCreate = {
151 name: 'default live thumbnail', 144 name: 'default live thumbnail',
152 channelId: servers[0].videoChannel.id, 145 channelId: servers[0].store.channel.id,
153 privacy: VideoPrivacy.UNLISTED, 146 privacy: VideoPrivacy.UNLISTED,
154 nsfw: true 147 nsfw: true
155 } 148 }
156 149
157 const res = await createLive(servers[0].url, servers[0].accessToken, attributes) 150 const live = await commands[0].create({ fields: attributes })
158 const videoId = res.body.video.uuid 151 const videoId = live.uuid
159 152
160 await waitJobs(servers) 153 await waitJobs(servers)
161 154
162 for (const server of servers) { 155 for (const server of servers) {
163 const resVideo = await getVideo(server.url, videoId) 156 const video = await server.videos.get({ id: videoId })
164 const video: VideoDetails = resVideo.body
165
166 expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED) 157 expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
167 expect(video.nsfw).to.be.true 158 expect(video.nsfw).to.be.true
168 159
@@ -173,28 +164,27 @@ describe('Test live', function () {
173 164
174 it('Should not have the live listed since nobody streams into', async function () { 165 it('Should not have the live listed since nobody streams into', async function () {
175 for (const server of servers) { 166 for (const server of servers) {
176 const res = await getVideosList(server.url) 167 const { total, data } = await server.videos.list()
177 168
178 expect(res.body.total).to.equal(0) 169 expect(total).to.equal(0)
179 expect(res.body.data).to.have.lengthOf(0) 170 expect(data).to.have.lengthOf(0)
180 } 171 }
181 }) 172 })
182 173
183 it('Should not be able to update a live of another server', async function () { 174 it('Should not be able to update a live of another server', async function () {
184 await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403) 175 await commands[1].update({ videoId: liveVideoUUID, fields: { saveReplay: false }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
185 }) 176 })
186 177
187 it('Should update the live', async function () { 178 it('Should update the live', async function () {
188 this.timeout(10000) 179 this.timeout(10000)
189 180
190 await updateLive(servers[0].url, servers[0].accessToken, liveVideoUUID, { saveReplay: false }) 181 await commands[0].update({ videoId: liveVideoUUID, fields: { saveReplay: false } })
191 await waitJobs(servers) 182 await waitJobs(servers)
192 }) 183 })
193 184
194 it('Have the live updated', async function () { 185 it('Have the live updated', async function () {
195 for (const server of servers) { 186 for (const server of servers) {
196 const res = await getLive(server.url, server.accessToken, liveVideoUUID) 187 const live = await server.live.get({ videoId: liveVideoUUID })
197 const live: LiveVideo = res.body
198 188
199 if (server.url === servers[0].url) { 189 if (server.url === servers[0].url) {
200 expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live') 190 expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
@@ -211,77 +201,75 @@ describe('Test live', function () {
211 it('Delete the live', async function () { 201 it('Delete the live', async function () {
212 this.timeout(10000) 202 this.timeout(10000)
213 203
214 await removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) 204 await servers[0].videos.remove({ id: liveVideoUUID })
215 await waitJobs(servers) 205 await waitJobs(servers)
216 }) 206 })
217 207
218 it('Should have the live deleted', async function () { 208 it('Should have the live deleted', async function () {
219 for (const server of servers) { 209 for (const server of servers) {
220 await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404) 210 await server.videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
221 await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404) 211 await server.live.get({ videoId: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
222 } 212 }
223 }) 213 })
224 }) 214 })
225 215
226 describe('Live filters', function () { 216 describe('Live filters', function () {
227 let command: any 217 let ffmpegCommand: any
228 let liveVideoId: string 218 let liveVideoId: string
229 let vodVideoId: string 219 let vodVideoId: string
230 220
231 before(async function () { 221 before(async function () {
232 this.timeout(120000) 222 this.timeout(120000)
233 223
234 vodVideoId = (await uploadVideoAndGetId({ server: servers[0], videoName: 'vod video' })).uuid 224 vodVideoId = (await servers[0].videos.quickUpload({ name: 'vod video' })).uuid
235 225
236 const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].videoChannel.id } 226 const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].store.channel.id }
237 const resLive = await createLive(servers[0].url, servers[0].accessToken, liveOptions) 227 const live = await commands[0].create({ fields: liveOptions })
238 liveVideoId = resLive.body.video.uuid 228 liveVideoId = live.uuid
239 229
240 command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) 230 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId })
241 await waitUntilLivePublishedOnAllServers(servers, liveVideoId) 231 await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
242 await waitJobs(servers) 232 await waitJobs(servers)
243 }) 233 })
244 234
245 it('Should only display lives', async function () { 235 it('Should only display lives', async function () {
246 const res = await getVideosWithFilters(servers[0].url, { isLive: true }) 236 const { data, total } = await servers[0].videos.list({ isLive: true })
247 237
248 expect(res.body.total).to.equal(1) 238 expect(total).to.equal(1)
249 expect(res.body.data).to.have.lengthOf(1) 239 expect(data).to.have.lengthOf(1)
250 expect(res.body.data[0].name).to.equal('live') 240 expect(data[0].name).to.equal('live')
251 }) 241 })
252 242
253 it('Should not display lives', async function () { 243 it('Should not display lives', async function () {
254 const res = await getVideosWithFilters(servers[0].url, { isLive: false }) 244 const { data, total } = await servers[0].videos.list({ isLive: false })
255 245
256 expect(res.body.total).to.equal(1) 246 expect(total).to.equal(1)
257 expect(res.body.data).to.have.lengthOf(1) 247 expect(data).to.have.lengthOf(1)
258 expect(res.body.data[0].name).to.equal('vod video') 248 expect(data[0].name).to.equal('vod video')
259 }) 249 })
260 250
261 it('Should display my lives', async function () { 251 it('Should display my lives', async function () {
262 this.timeout(60000) 252 this.timeout(60000)
263 253
264 await stopFfmpeg(command) 254 await stopFfmpeg(ffmpegCommand)
265 await waitJobs(servers) 255 await waitJobs(servers)
266 256
267 const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: true }) 257 const { data } = await servers[0].videos.listMyVideos({ isLive: true })
268 const videos = res.body.data as Video[]
269 258
270 const result = videos.every(v => v.isLive) 259 const result = data.every(v => v.isLive)
271 expect(result).to.be.true 260 expect(result).to.be.true
272 }) 261 })
273 262
274 it('Should not display my lives', async function () { 263 it('Should not display my lives', async function () {
275 const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: false }) 264 const { data } = await servers[0].videos.listMyVideos({ isLive: false })
276 const videos = res.body.data as Video[]
277 265
278 const result = videos.every(v => !v.isLive) 266 const result = data.every(v => !v.isLive)
279 expect(result).to.be.true 267 expect(result).to.be.true
280 }) 268 })
281 269
282 after(async function () { 270 after(async function () {
283 await removeVideo(servers[0].url, servers[0].accessToken, vodVideoId) 271 await servers[0].videos.remove({ id: vodVideoId })
284 await removeVideo(servers[0].url, servers[0].accessToken, liveVideoId) 272 await servers[0].videos.remove({ id: liveVideoId })
285 }) 273 })
286 }) 274 })
287 275
@@ -296,18 +284,17 @@ describe('Test live', function () {
296 async function createLiveWrapper () { 284 async function createLiveWrapper () {
297 const liveAttributes = { 285 const liveAttributes = {
298 name: 'user live', 286 name: 'user live',
299 channelId: servers[0].videoChannel.id, 287 channelId: servers[0].store.channel.id,
300 privacy: VideoPrivacy.PUBLIC, 288 privacy: VideoPrivacy.PUBLIC,
301 saveReplay: false 289 saveReplay: false
302 } 290 }
303 291
304 const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) 292 const { uuid } = await commands[0].create({ fields: liveAttributes })
305 const uuid = res.body.video.uuid
306 293
307 const resLive = await getLive(servers[0].url, servers[0].accessToken, uuid) 294 const live = await commands[0].get({ videoId: uuid })
308 const resVideo = await getVideo(servers[0].url, uuid) 295 const video = await servers[0].videos.get({ id: uuid })
309 296
310 return Object.assign(resVideo.body, resLive.body) as LiveVideo & VideoDetails 297 return Object.assign(video, live)
311 } 298 }
312 299
313 it('Should not allow a stream without the appropriate path', async function () { 300 it('Should not allow a stream without the appropriate path', async function () {
@@ -335,13 +322,12 @@ describe('Test live', function () {
335 322
336 it('Should list this live now someone stream into it', async function () { 323 it('Should list this live now someone stream into it', async function () {
337 for (const server of servers) { 324 for (const server of servers) {
338 const res = await getVideosList(server.url) 325 const { total, data } = await server.videos.list()
339 326
340 expect(res.body.total).to.equal(1) 327 expect(total).to.equal(1)
341 expect(res.body.data).to.have.lengthOf(1) 328 expect(data).to.have.lengthOf(1)
342
343 const video: Video = res.body.data[0]
344 329
330 const video = data[0]
345 expect(video.name).to.equal('user live') 331 expect(video.name).to.equal('user live')
346 expect(video.isLive).to.be.true 332 expect(video.isLive).to.be.true
347 } 333 }
@@ -352,7 +338,7 @@ describe('Test live', function () {
352 338
353 liveVideo = await createLiveWrapper() 339 liveVideo = await createLiveWrapper()
354 340
355 await addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideo.uuid) 341 await servers[0].blacklist.add({ videoId: liveVideo.uuid })
356 342
357 const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) 343 const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey)
358 await testFfmpegStreamError(command, true) 344 await testFfmpegStreamError(command, true)
@@ -363,7 +349,7 @@ describe('Test live', function () {
363 349
364 liveVideo = await createLiveWrapper() 350 liveVideo = await createLiveWrapper()
365 351
366 await removeVideo(servers[0].url, servers[0].accessToken, liveVideo.uuid) 352 await servers[0].videos.remove({ id: liveVideo.uuid })
367 353
368 const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) 354 const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey)
369 await testFfmpegStreamError(command, true) 355 await testFfmpegStreamError(command, true)
@@ -376,24 +362,21 @@ describe('Test live', function () {
376 async function createLiveWrapper (saveReplay: boolean) { 362 async function createLiveWrapper (saveReplay: boolean) {
377 const liveAttributes = { 363 const liveAttributes = {
378 name: 'live video', 364 name: 'live video',
379 channelId: servers[0].videoChannel.id, 365 channelId: servers[0].store.channel.id,
380 privacy: VideoPrivacy.PUBLIC, 366 privacy: VideoPrivacy.PUBLIC,
381 saveReplay 367 saveReplay
382 } 368 }
383 369
384 const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) 370 const { uuid } = await commands[0].create({ fields: liveAttributes })
385 return res.body.video.uuid 371 return uuid
386 } 372 }
387 373
388 async function testVideoResolutions (liveVideoId: string, resolutions: number[]) { 374 async function testVideoResolutions (liveVideoId: string, resolutions: number[]) {
389 for (const server of servers) { 375 for (const server of servers) {
390 const resList = await getVideosList(server.url) 376 const { data } = await server.videos.list()
391 const videos: Video[] = resList.body.data 377 expect(data.find(v => v.uuid === liveVideoId)).to.exist
392
393 expect(videos.find(v => v.uuid === liveVideoId)).to.exist
394 378
395 const resVideo = await getVideo(server.url, liveVideoId) 379 const video = await server.videos.get({ id: liveVideoId })
396 const video: VideoDetails = resVideo.body
397 380
398 expect(video.streamingPlaylists).to.have.lengthOf(1) 381 expect(video.streamingPlaylists).to.have.lengthOf(1)
399 382
@@ -403,39 +386,48 @@ describe('Test live', function () {
403 // Only finite files are displayed 386 // Only finite files are displayed
404 expect(hlsPlaylist.files).to.have.lengthOf(0) 387 expect(hlsPlaylist.files).to.have.lengthOf(0)
405 388
406 await checkResolutionsInMasterPlaylist(hlsPlaylist.playlistUrl, resolutions) 389 await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions })
407 390
408 for (let i = 0; i < resolutions.length; i++) { 391 for (let i = 0; i < resolutions.length; i++) {
409 const segmentNum = 3 392 const segmentNum = 3
410 const segmentName = `${i}-00000${segmentNum}.ts` 393 const segmentName = `${i}-00000${segmentNum}.ts`
411 await waitUntilLiveSegmentGeneration(servers[0], video.uuid, i, segmentNum) 394 await commands[0].waitUntilSegmentGeneration({ videoUUID: video.uuid, resolution: i, segment: segmentNum })
412 395
413 const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`) 396 const subPlaylist = await servers[0].streamingPlaylists.get({
414 const subPlaylist = res.text 397 url: `${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`
398 })
415 399
416 expect(subPlaylist).to.contain(segmentName) 400 expect(subPlaylist).to.contain(segmentName)
417 401
418 const baseUrlAndPath = servers[0].url + '/static/streaming-playlists/hls' 402 const baseUrlAndPath = servers[0].url + '/static/streaming-playlists/hls'
419 await checkLiveSegmentHash(baseUrlAndPath, video.uuid, segmentName, hlsPlaylist) 403 await checkLiveSegmentHash({
404 server,
405 baseUrlSegment: baseUrlAndPath,
406 videoUUID: video.uuid,
407 segmentName,
408 hlsPlaylist
409 })
420 } 410 }
421 } 411 }
422 } 412 }
423 413
424 function updateConf (resolutions: number[]) { 414 function updateConf (resolutions: number[]) {
425 return updateCustomSubConfig(servers[0].url, servers[0].accessToken, { 415 return servers[0].config.updateCustomSubConfig({
426 live: { 416 newConfig: {
427 enabled: true, 417 live: {
428 allowReplay: true,
429 maxDuration: -1,
430 transcoding: {
431 enabled: true, 418 enabled: true,
432 resolutions: { 419 allowReplay: true,
433 '240p': resolutions.includes(240), 420 maxDuration: -1,
434 '360p': resolutions.includes(360), 421 transcoding: {
435 '480p': resolutions.includes(480), 422 enabled: true,
436 '720p': resolutions.includes(720), 423 resolutions: {
437 '1080p': resolutions.includes(1080), 424 '240p': resolutions.includes(240),
438 '2160p': resolutions.includes(2160) 425 '360p': resolutions.includes(360),
426 '480p': resolutions.includes(480),
427 '720p': resolutions.includes(720),
428 '1080p': resolutions.includes(1080),
429 '2160p': resolutions.includes(2160)
430 }
439 } 431 }
440 } 432 }
441 } 433 }
@@ -451,13 +443,13 @@ describe('Test live', function () {
451 443
452 liveVideoId = await createLiveWrapper(false) 444 liveVideoId = await createLiveWrapper(false)
453 445
454 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) 446 const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
455 await waitUntilLivePublishedOnAllServers(servers, liveVideoId) 447 await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
456 await waitJobs(servers) 448 await waitJobs(servers)
457 449
458 await testVideoResolutions(liveVideoId, [ 720 ]) 450 await testVideoResolutions(liveVideoId, [ 720 ])
459 451
460 await stopFfmpeg(command) 452 await stopFfmpeg(ffmpegCommand)
461 }) 453 })
462 454
463 it('Should enable transcoding with some resolutions', async function () { 455 it('Should enable transcoding with some resolutions', async function () {
@@ -467,13 +459,13 @@ describe('Test live', function () {
467 await updateConf(resolutions) 459 await updateConf(resolutions)
468 liveVideoId = await createLiveWrapper(false) 460 liveVideoId = await createLiveWrapper(false)
469 461
470 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) 462 const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
471 await waitUntilLivePublishedOnAllServers(servers, liveVideoId) 463 await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
472 await waitJobs(servers) 464 await waitJobs(servers)
473 465
474 await testVideoResolutions(liveVideoId, resolutions) 466 await testVideoResolutions(liveVideoId, resolutions)
475 467
476 await stopFfmpeg(command) 468 await stopFfmpeg(ffmpegCommand)
477 }) 469 })
478 470
479 it('Should enable transcoding with some resolutions and correctly save them', async function () { 471 it('Should enable transcoding with some resolutions and correctly save them', async function () {
@@ -484,14 +476,14 @@ describe('Test live', function () {
484 await updateConf(resolutions) 476 await updateConf(resolutions)
485 liveVideoId = await createLiveWrapper(true) 477 liveVideoId = await createLiveWrapper(true)
486 478
487 const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId, 'video_short2.webm') 479 const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
488 await waitUntilLivePublishedOnAllServers(servers, liveVideoId) 480 await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
489 await waitJobs(servers) 481 await waitJobs(servers)
490 482
491 await testVideoResolutions(liveVideoId, resolutions) 483 await testVideoResolutions(liveVideoId, resolutions)
492 484
493 await stopFfmpeg(command) 485 await stopFfmpeg(ffmpegCommand)
494 await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId) 486 await commands[0].waitUntilEnded({ videoId: liveVideoId })
495 487
496 await waitJobs(servers) 488 await waitJobs(servers)
497 489
@@ -504,8 +496,7 @@ describe('Test live', function () {
504 } 496 }
505 497
506 for (const server of servers) { 498 for (const server of servers) {
507 const resVideo = await getVideo(server.url, liveVideoId) 499 const video = await server.videos.get({ id: liveVideoId })
508 const video: VideoDetails = resVideo.body
509 500
510 expect(video.state.id).to.equal(VideoState.PUBLISHED) 501 expect(video.state.id).to.equal(VideoState.PUBLISHED)
511 expect(video.duration).to.be.greaterThan(1) 502 expect(video.duration).to.be.greaterThan(1)
@@ -515,6 +506,10 @@ describe('Test live', function () {
515 await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200) 506 await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200)
516 await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200) 507 await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200)
517 508
509 // We should have generated random filenames
510 expect(basename(hlsPlaylist.playlistUrl)).to.not.equal('master.m3u8')
511 expect(basename(hlsPlaylist.segmentsSha256Url)).to.not.equal('segments-sha256.json')
512
518 expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length) 513 expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
519 514
520 for (const resolution of resolutions) { 515 for (const resolution of resolutions) {
@@ -529,8 +524,10 @@ describe('Test live', function () {
529 expect(file.fps).to.be.approximately(30, 2) 524 expect(file.fps).to.be.approximately(30, 2)
530 } 525 }
531 526
532 const filename = `${video.uuid}-${resolution}-fragmented.mp4` 527 const filename = basename(file.fileUrl)
533 const segmentPath = buildServerDirectory(servers[0], join('streaming-playlists', 'hls', video.uuid, filename)) 528 expect(filename).to.not.contain(video.uuid)
529
530 const segmentPath = servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', video.uuid, filename))
534 531
535 const probe = await ffprobePromise(segmentPath) 532 const probe = await ffprobePromise(segmentPath)
536 const videoStream = await getVideoStreamFromFile(segmentPath, probe) 533 const videoStream = await getVideoStreamFromFile(segmentPath, probe)
@@ -546,7 +543,7 @@ describe('Test live', function () {
546 it('Should correctly have cleaned up the live files', async function () { 543 it('Should correctly have cleaned up the live files', async function () {
547 this.timeout(30000) 544 this.timeout(30000)
548 545
549 await checkLiveCleanup(servers[0], liveVideoId, [ 240, 360, 720 ]) 546 await checkLiveCleanupAfterSave(servers[0], liveVideoId, [ 240, 360, 720 ])
550 }) 547 })
551 }) 548 })
552 549
@@ -557,13 +554,13 @@ describe('Test live', function () {
557 async function createLiveWrapper (saveReplay: boolean) { 554 async function createLiveWrapper (saveReplay: boolean) {
558 const liveAttributes = { 555 const liveAttributes = {
559 name: 'live video', 556 name: 'live video',
560 channelId: servers[0].videoChannel.id, 557 channelId: servers[0].store.channel.id,
561 privacy: VideoPrivacy.PUBLIC, 558 privacy: VideoPrivacy.PUBLIC,
562 saveReplay 559 saveReplay
563 } 560 }
564 561
565 const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) 562 const { uuid } = await commands[0].create({ fields: liveAttributes })
566 return res.body.video.uuid 563 return uuid
567 } 564 }
568 565
569 before(async function () { 566 before(async function () {
@@ -573,20 +570,20 @@ describe('Test live', function () {
573 liveVideoReplayId = await createLiveWrapper(true) 570 liveVideoReplayId = await createLiveWrapper(true)
574 571
575 await Promise.all([ 572 await Promise.all([
576 sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId), 573 commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }),
577 sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoReplayId) 574 commands[0].sendRTMPStreamInVideo({ videoId: liveVideoReplayId })
578 ]) 575 ])
579 576
580 await Promise.all([ 577 await Promise.all([
581 waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId), 578 commands[0].waitUntilPublished({ videoId: liveVideoId }),
582 waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId) 579 commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
583 ]) 580 ])
584 581
585 await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2) 582 await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoId, resolution: 0, segment: 2 })
586 await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2) 583 await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 })
587 584
588 await killallServers([ servers[0] ]) 585 await killallServers([ servers[0] ])
589 await reRunServer(servers[0]) 586 await servers[0].run()
590 587
591 await wait(5000) 588 await wait(5000)
592 }) 589 })
@@ -594,13 +591,13 @@ describe('Test live', function () {
594 it('Should cleanup lives', async function () { 591 it('Should cleanup lives', async function () {
595 this.timeout(60000) 592 this.timeout(60000)
596 593
597 await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId) 594 await commands[0].waitUntilEnded({ videoId: liveVideoId })
598 }) 595 })
599 596
600 it('Should save a live replay', async function () { 597 it('Should save a live replay', async function () {
601 this.timeout(120000) 598 this.timeout(120000)
602 599
603 await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId) 600 await commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
604 }) 601 })
605 }) 602 })
606 603