aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/config.ts2
-rw-r--r--server/helpers/activitypub.ts1
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts3
-rw-r--r--server/lib/activitypub/process/process-update.ts2
-rw-r--r--server/lib/activitypub/videos.ts3
-rw-r--r--server/models/video/video.ts3
-rw-r--r--server/tests/api/videos/video-transcoder.ts168
7 files changed, 98 insertions, 84 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index acbeab70b..950a1498e 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -66,7 +66,7 @@ async function getConfig (req: express.Request, res: express.Response, next: exp
66 enabledResolutions 66 enabledResolutions
67 }, 67 },
68 import: { 68 import: {
69 video: { 69 videos: {
70 http: { 70 http: {
71 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED 71 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
72 } 72 }
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index d710f5c97..a9de11fb0 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -24,6 +24,7 @@ function activityPubContextify <T> (data: T) {
24 views: 'http://schema.org/Number', 24 views: 'http://schema.org/Number',
25 stats: 'http://schema.org/Number', 25 stats: 'http://schema.org/Number',
26 size: 'http://schema.org/Number', 26 size: 'http://schema.org/Number',
27 fps: 'http://schema.org/Number',
27 commentsEnabled: 'http://schema.org/Boolean', 28 commentsEnabled: 'http://schema.org/Boolean',
28 waitTranscoding: 'http://schema.org/Boolean', 29 waitTranscoding: 'http://schema.org/Boolean',
29 support: 'http://schema.org/Text' 30 support: 'http://schema.org/Text'
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
index c6a350236..b8075f3c7 100644
--- a/server/helpers/custom-validators/activitypub/videos.ts
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -153,7 +153,8 @@ function isRemoteVideoUrlValid (url: any) {
153 ACTIVITY_PUB.URL_MIME_TYPES.VIDEO.indexOf(url.mimeType) !== -1 && 153 ACTIVITY_PUB.URL_MIME_TYPES.VIDEO.indexOf(url.mimeType) !== -1 &&
154 isActivityPubUrlValid(url.href) && 154 isActivityPubUrlValid(url.href) &&
155 validator.isInt(url.width + '', { min: 0 }) && 155 validator.isInt(url.width + '', { min: 0 }) &&
156 validator.isInt(url.size + '', { min: 0 }) 156 validator.isInt(url.size + '', { min: 0 }) &&
157 (!url.fps || validator.isInt(url.fps + '', { min: 0 }))
157 ) || 158 ) ||
158 ( 159 (
159 ACTIVITY_PUB.URL_MIME_TYPES.TORRENT.indexOf(url.mimeType) !== -1 && 160 ACTIVITY_PUB.URL_MIME_TYPES.TORRENT.indexOf(url.mimeType) !== -1 &&
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts
index 62791ff1b..82b661a03 100644
--- a/server/lib/activitypub/process/process-update.ts
+++ b/server/lib/activitypub/process/process-update.ts
@@ -108,7 +108,7 @@ async function processUpdateVideo (actor: ActorModel, activity: ActivityUpdate)
108 await Promise.all(videoFileDestroyTasks) 108 await Promise.all(videoFileDestroyTasks)
109 109
110 const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoInstance, videoObject) 110 const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoInstance, videoObject)
111 const tasks = videoFileAttributes.map(f => VideoFileModel.create(f)) 111 const tasks = videoFileAttributes.map(f => VideoFileModel.create(f, sequelizeOptions))
112 await Promise.all(tasks) 112 await Promise.all(tasks)
113 113
114 // Update Tags 114 // Update Tags
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index b3fbf88d0..e2f46bd02 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -162,7 +162,8 @@ function videoFileActivityUrlToDBAttributes (videoCreated: VideoModel, videoObje
162 infoHash: parsed.infoHash, 162 infoHash: parsed.infoHash,
163 resolution: fileUrl.width, 163 resolution: fileUrl.width,
164 size: fileUrl.size, 164 size: fileUrl.size,
165 videoId: videoCreated.id 165 videoId: videoCreated.id,
166 fps: fileUrl.fps
166 } as VideoFileModel 167 } as VideoFileModel
167 attributes.push(attribute) 168 attributes.push(attribute)
168 } 169 }
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 67711b102..39fe21007 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1355,7 +1355,8 @@ export class VideoModel extends Model<VideoModel> {
1355 mimeType: VIDEO_EXT_MIMETYPE[file.extname], 1355 mimeType: VIDEO_EXT_MIMETYPE[file.extname],
1356 href: this.getVideoFileUrl(file, baseUrlHttp), 1356 href: this.getVideoFileUrl(file, baseUrlHttp),
1357 width: file.resolution, 1357 width: file.resolution,
1358 size: file.size 1358 size: file.size,
1359 fps: file.fps
1359 }) 1360 })
1360 1361
1361 url.push({ 1362 url.push({
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts
index 4a39ee3e3..0f83d4d57 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/videos/video-transcoder.ts
@@ -35,6 +35,8 @@ describe('Test video transcoding', function () {
35 servers = await flushAndRunMultipleServers(2) 35 servers = await flushAndRunMultipleServers(2)
36 36
37 await setAccessTokensToServers(servers) 37 await setAccessTokensToServers(servers)
38
39 await doubleFollow(servers[0], servers[1])
38 }) 40 })
39 41
40 it('Should not transcode video on server 1', async function () { 42 it('Should not transcode video on server 1', async function () {
@@ -49,20 +51,22 @@ describe('Test video transcoding', function () {
49 51
50 await waitJobs(servers) 52 await waitJobs(servers)
51 53
52 const res = await getVideosList(servers[0].url) 54 for (const server of servers) {
53 const video = res.body.data[0] 55 const res = await getVideosList(server.url)
56 const video = res.body.data[ 0 ]
54 57
55 const res2 = await getVideo(servers[0].url, video.id) 58 const res2 = await getVideo(server.url, video.id)
56 const videoDetails = res2.body 59 const videoDetails = res2.body
57 expect(videoDetails.files).to.have.lengthOf(1) 60 expect(videoDetails.files).to.have.lengthOf(1)
58 61
59 const magnetUri = videoDetails.files[0].magnetUri 62 const magnetUri = videoDetails.files[ 0 ].magnetUri
60 expect(magnetUri).to.match(/\.webm/) 63 expect(magnetUri).to.match(/\.webm/)
61 64
62 const torrent = await webtorrentAdd(magnetUri) 65 const torrent = await webtorrentAdd(magnetUri, true)
63 expect(torrent.files).to.be.an('array') 66 expect(torrent.files).to.be.an('array')
64 expect(torrent.files.length).to.equal(1) 67 expect(torrent.files.length).to.equal(1)
65 expect(torrent.files[0].path).match(/\.webm$/) 68 expect(torrent.files[ 0 ].path).match(/\.webm$/)
69 }
66 }) 70 })
67 71
68 it('Should transcode video on server 2', async function () { 72 it('Should transcode video on server 2', async function () {
@@ -77,21 +81,23 @@ describe('Test video transcoding', function () {
77 81
78 await waitJobs(servers) 82 await waitJobs(servers)
79 83
80 const res = await getVideosList(servers[1].url) 84 for (const server of servers) {
85 const res = await getVideosList(server.url)
81 86
82 const video = res.body.data[0] 87 const video = res.body.data.find(v => v.name === videoAttributes.name)
83 const res2 = await getVideo(servers[1].url, video.id) 88 const res2 = await getVideo(server.url, video.id)
84 const videoDetails = res2.body 89 const videoDetails = res2.body
85 90
86 expect(videoDetails.files).to.have.lengthOf(4) 91 expect(videoDetails.files).to.have.lengthOf(4)
87 92
88 const magnetUri = videoDetails.files[0].magnetUri 93 const magnetUri = videoDetails.files[ 0 ].magnetUri
89 expect(magnetUri).to.match(/\.mp4/) 94 expect(magnetUri).to.match(/\.mp4/)
90 95
91 const torrent = await webtorrentAdd(magnetUri) 96 const torrent = await webtorrentAdd(magnetUri, true)
92 expect(torrent.files).to.be.an('array') 97 expect(torrent.files).to.be.an('array')
93 expect(torrent.files.length).to.equal(1) 98 expect(torrent.files.length).to.equal(1)
94 expect(torrent.files[0].path).match(/\.mp4$/) 99 expect(torrent.files[ 0 ].path).match(/\.mp4$/)
100 }
95 }) 101 })
96 102
97 it('Should transcode high bit rate mp3 to proper bit rate', async function () { 103 it('Should transcode high bit rate mp3 to proper bit rate', async function () {
@@ -105,22 +111,24 @@ describe('Test video transcoding', function () {
105 111
106 await waitJobs(servers) 112 await waitJobs(servers)
107 113
108 const res = await getVideosList(servers[1].url) 114 for (const server of servers) {
115 const res = await getVideosList(server.url)
109 116
110 const video = res.body.data.find(v => v.name === videoAttributes.name) 117 const video = res.body.data.find(v => v.name === videoAttributes.name)
111 const res2 = await getVideo(servers[1].url, video.id) 118 const res2 = await getVideo(server.url, video.id)
112 const videoDetails: VideoDetails = res2.body 119 const videoDetails: VideoDetails = res2.body
113 120
114 expect(videoDetails.files).to.have.lengthOf(4) 121 expect(videoDetails.files).to.have.lengthOf(4)
115 122
116 const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') 123 const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4')
117 const probe = await audio.get(ffmpeg, path) 124 const probe = await audio.get(ffmpeg, path)
118 125
119 if (probe.audioStream) { 126 if (probe.audioStream) {
120 expect(probe.audioStream['codec_name']).to.be.equal('aac') 127 expect(probe.audioStream[ 'codec_name' ]).to.be.equal('aac')
121 expect(probe.audioStream['bit_rate']).to.be.at.most(384 * 8000) 128 expect(probe.audioStream[ 'bit_rate' ]).to.be.at.most(384 * 8000)
122 } else { 129 } else {
123 this.fail('Could not retrieve the audio stream on ' + probe.absolutePath) 130 this.fail('Could not retrieve the audio stream on ' + probe.absolutePath)
131 }
124 } 132 }
125 }) 133 })
126 134
@@ -135,16 +143,18 @@ describe('Test video transcoding', function () {
135 143
136 await waitJobs(servers) 144 await waitJobs(servers)
137 145
138 const res = await getVideosList(servers[1].url) 146 for (const server of servers) {
147 const res = await getVideosList(server.url)
139 148
140 const video = res.body.data.find(v => v.name === videoAttributes.name) 149 const video = res.body.data.find(v => v.name === videoAttributes.name)
141 const res2 = await getVideo(servers[1].url, video.id) 150 const res2 = await getVideo(server.url, video.id)
142 const videoDetails: VideoDetails = res2.body 151 const videoDetails: VideoDetails = res2.body
143 152
144 expect(videoDetails.files).to.have.lengthOf(4) 153 expect(videoDetails.files).to.have.lengthOf(4)
145 const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') 154 const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4')
146 const probe = await audio.get(ffmpeg, path) 155 const probe = await audio.get(ffmpeg, path)
147 expect(probe).to.not.have.property('audioStream') 156 expect(probe).to.not.have.property('audioStream')
157 }
148 }) 158 })
149 159
150 it('Should leave the audio untouched, but properly transcode the video', async function () { 160 it('Should leave the audio untouched, but properly transcode the video', async function () {
@@ -158,22 +168,24 @@ describe('Test video transcoding', function () {
158 168
159 await waitJobs(servers) 169 await waitJobs(servers)
160 170
161 const res = await getVideosList(servers[1].url) 171 for (const server of servers) {
162 172 const res = await getVideosList(server.url)
163 const video = res.body.data.find(v => v.name === videoAttributes.name) 173
164 const res2 = await getVideo(servers[1].url, video.id) 174 const video = res.body.data.find(v => v.name === videoAttributes.name)
165 const videoDetails: VideoDetails = res2.body 175 const res2 = await getVideo(server.url, video.id)
166 176 const videoDetails: VideoDetails = res2.body
167 expect(videoDetails.files).to.have.lengthOf(4) 177
168 const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture) 178 expect(videoDetails.files).to.have.lengthOf(4)
169 const fixtureVideoProbe = await audio.get(ffmpeg, fixturePath) 179 const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture)
170 const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') 180 const fixtureVideoProbe = await audio.get(ffmpeg, fixturePath)
171 const videoProbe = await audio.get(ffmpeg, path) 181 const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4')
172 if (videoProbe.audioStream && fixtureVideoProbe.audioStream) { 182 const videoProbe = await audio.get(ffmpeg, path)
173 const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ] 183 if (videoProbe.audioStream && fixtureVideoProbe.audioStream) {
174 expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit)) 184 const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ]
175 } else { 185 expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit))
176 this.fail('Could not retrieve the audio stream on ' + videoProbe.absolutePath) 186 } else {
187 this.fail('Could not retrieve the audio stream on ' + videoProbe.absolutePath)
188 }
177 } 189 }
178 }) 190 })
179 191
@@ -189,38 +201,36 @@ describe('Test video transcoding', function () {
189 201
190 await waitJobs(servers) 202 await waitJobs(servers)
191 203
192 const res = await getVideosList(servers[1].url) 204 for (const server of servers) {
205 const res = await getVideosList(server.url)
193 206
194 const video = res.body.data.find(v => v.name === videoAttributes.name) 207 const video = res.body.data.find(v => v.name === videoAttributes.name)
195 const res2 = await getVideo(servers[1].url, video.id) 208 const res2 = await getVideo(server.url, video.id)
196 const videoDetails: VideoDetails = res2.body 209 const videoDetails: VideoDetails = res2.body
197 210
198 expect(videoDetails.files).to.have.lengthOf(4) 211 expect(videoDetails.files).to.have.lengthOf(4)
199 expect(videoDetails.files[0].fps).to.be.above(58).and.below(62) 212 expect(videoDetails.files[ 0 ].fps).to.be.above(58).and.below(62)
200 expect(videoDetails.files[1].fps).to.be.below(31) 213 expect(videoDetails.files[ 1 ].fps).to.be.below(31)
201 expect(videoDetails.files[2].fps).to.be.below(31) 214 expect(videoDetails.files[ 2 ].fps).to.be.below(31)
202 expect(videoDetails.files[3].fps).to.be.below(31) 215 expect(videoDetails.files[ 3 ].fps).to.be.below(31)
203 216
204 for (const resolution of [ '240', '360', '480' ]) { 217 for (const resolution of [ '240', '360', '480' ]) {
205 const path = join(root(), 'test2', 'videos', video.uuid + '-' + resolution + '.mp4') 218 const path = join(root(), 'test2', 'videos', video.uuid + '-' + resolution + '.mp4')
206 const fps = await getVideoFileFPS(path) 219 const fps = await getVideoFileFPS(path)
207 220
208 expect(fps).to.be.below(31) 221 expect(fps).to.be.below(31)
209 } 222 }
210 223
211 const path = join(root(), 'test2', 'videos', video.uuid + '-720.mp4') 224 const path = join(root(), 'test2', 'videos', video.uuid + '-720.mp4')
212 const fps = await getVideoFileFPS(path) 225 const fps = await getVideoFileFPS(path)
213 226
214 expect(fps).to.be.above(58).and.below(62) 227 expect(fps).to.be.above(58).and.below(62)
228 }
215 }) 229 })
216 230
217 it('Should wait transcoding before publishing the video', async function () { 231 it('Should wait transcoding before publishing the video', async function () {
218 this.timeout(80000) 232 this.timeout(80000)
219 233
220 await doubleFollow(servers[0], servers[1])
221
222 await waitJobs(servers)
223
224 { 234 {
225 // Upload the video, but wait transcoding 235 // Upload the video, but wait transcoding
226 const videoAttributes = { 236 const videoAttributes = {