aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/server-commands/videos
diff options
context:
space:
mode:
Diffstat (limited to 'shared/server-commands/videos')
-rw-r--r--shared/server-commands/videos/blacklist-command.ts3
-rw-r--r--shared/server-commands/videos/captions-command.ts2
-rw-r--r--shared/server-commands/videos/captions.ts21
-rw-r--r--shared/server-commands/videos/channels-command.ts12
-rw-r--r--shared/server-commands/videos/index.ts4
-rw-r--r--shared/server-commands/videos/live-command.ts2
-rw-r--r--shared/server-commands/videos/live.ts41
-rw-r--r--shared/server-commands/videos/playlists.ts25
-rw-r--r--shared/server-commands/videos/streaming-playlists.ts77
-rw-r--r--shared/server-commands/videos/videos-command.ts4
-rw-r--r--shared/server-commands/videos/videos.ts104
11 files changed, 15 insertions, 280 deletions
diff --git a/shared/server-commands/videos/blacklist-command.ts b/shared/server-commands/videos/blacklist-command.ts
index 3a2ef89ba..47e23ebc8 100644
--- a/shared/server-commands/videos/blacklist-command.ts
+++ b/shared/server-commands/videos/blacklist-command.ts
@@ -1,6 +1,5 @@
1 1
2import { HttpStatusCode, ResultList } from '@shared/models' 2import { HttpStatusCode, ResultList, VideoBlacklist, VideoBlacklistType } from '@shared/models'
3import { VideoBlacklist, VideoBlacklistType } from '../../models/videos'
4import { AbstractCommand, OverrideCommandOptions } from '../shared' 3import { AbstractCommand, OverrideCommandOptions } from '../shared'
5 4
6export class BlacklistCommand extends AbstractCommand { 5export class BlacklistCommand extends AbstractCommand {
diff --git a/shared/server-commands/videos/captions-command.ts b/shared/server-commands/videos/captions-command.ts
index a65ea99e3..62bf9c5e6 100644
--- a/shared/server-commands/videos/captions-command.ts
+++ b/shared/server-commands/videos/captions-command.ts
@@ -1,5 +1,5 @@
1import { buildAbsoluteFixturePath } from '@shared/core-utils'
1import { HttpStatusCode, ResultList, VideoCaption } from '@shared/models' 2import { HttpStatusCode, ResultList, VideoCaption } from '@shared/models'
2import { buildAbsoluteFixturePath } from '../miscs'
3import { AbstractCommand, OverrideCommandOptions } from '../shared' 3import { AbstractCommand, OverrideCommandOptions } from '../shared'
4 4
5export class CaptionsCommand extends AbstractCommand { 5export class CaptionsCommand extends AbstractCommand {
diff --git a/shared/server-commands/videos/captions.ts b/shared/server-commands/videos/captions.ts
deleted file mode 100644
index 35e722408..000000000
--- a/shared/server-commands/videos/captions.ts
+++ /dev/null
@@ -1,21 +0,0 @@
1import { expect } from 'chai'
2import request from 'supertest'
3import { HttpStatusCode } from '@shared/models'
4
5async function testCaptionFile (url: string, captionPath: string, toTest: RegExp | string) {
6 const res = await request(url)
7 .get(captionPath)
8 .expect(HttpStatusCode.OK_200)
9
10 if (toTest instanceof RegExp) {
11 expect(res.text).to.match(toTest)
12 } else {
13 expect(res.text).to.contain(toTest)
14 }
15}
16
17// ---------------------------------------------------------------------------
18
19export {
20 testCaptionFile
21}
diff --git a/shared/server-commands/videos/channels-command.ts b/shared/server-commands/videos/channels-command.ts
index e406e570b..8ab124658 100644
--- a/shared/server-commands/videos/channels-command.ts
+++ b/shared/server-commands/videos/channels-command.ts
@@ -1,7 +1,13 @@
1import { pick } from '@shared/core-utils' 1import { pick } from '@shared/core-utils'
2import { ActorFollow, HttpStatusCode, ResultList, VideoChannel, VideoChannelCreateResult } from '@shared/models' 2import {
3import { VideoChannelCreate } from '../../models/videos/channel/video-channel-create.model' 3 ActorFollow,
4import { VideoChannelUpdate } from '../../models/videos/channel/video-channel-update.model' 4 HttpStatusCode,
5 ResultList,
6 VideoChannel,
7 VideoChannelCreate,
8 VideoChannelCreateResult,
9 VideoChannelUpdate
10} from '@shared/models'
5import { unwrapBody } from '../requests' 11import { unwrapBody } from '../requests'
6import { AbstractCommand, OverrideCommandOptions } from '../shared' 12import { AbstractCommand, OverrideCommandOptions } from '../shared'
7 13
diff --git a/shared/server-commands/videos/index.ts b/shared/server-commands/videos/index.ts
index 26e663f46..68a188b21 100644
--- a/shared/server-commands/videos/index.ts
+++ b/shared/server-commands/videos/index.ts
@@ -1,6 +1,5 @@
1export * from './blacklist-command' 1export * from './blacklist-command'
2export * from './captions-command' 2export * from './captions-command'
3export * from './captions'
4export * from './change-ownership-command' 3export * from './change-ownership-command'
5export * from './channels' 4export * from './channels'
6export * from './channels-command' 5export * from './channels-command'
@@ -10,10 +9,7 @@ export * from './imports-command'
10export * from './live-command' 9export * from './live-command'
11export * from './live' 10export * from './live'
12export * from './playlists-command' 11export * from './playlists-command'
13export * from './playlists'
14export * from './services-command' 12export * from './services-command'
15export * from './streaming-playlists-command' 13export * from './streaming-playlists-command'
16export * from './streaming-playlists'
17export * from './comments-command' 14export * from './comments-command'
18export * from './videos-command' 15export * from './videos-command'
19export * from './videos'
diff --git a/shared/server-commands/videos/live-command.ts b/shared/server-commands/videos/live-command.ts
index 74f5d3089..f7816eca0 100644
--- a/shared/server-commands/videos/live-command.ts
+++ b/shared/server-commands/videos/live-command.ts
@@ -3,8 +3,8 @@
3import { readdir } from 'fs-extra' 3import { readdir } from 'fs-extra'
4import { omit } from 'lodash' 4import { omit } from 'lodash'
5import { join } from 'path' 5import { join } from 'path'
6import { wait } from '@shared/core-utils'
6import { HttpStatusCode, LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models' 7import { HttpStatusCode, LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models'
7import { wait } from '../miscs'
8import { unwrapBody } from '../requests' 8import { unwrapBody } from '../requests'
9import { AbstractCommand, OverrideCommandOptions } from '../shared' 9import { AbstractCommand, OverrideCommandOptions } from '../shared'
10import { sendRTMPStream, testFfmpegStreamError } from './live' 10import { sendRTMPStream, testFfmpegStreamError } from './live'
diff --git a/shared/server-commands/videos/live.ts b/shared/server-commands/videos/live.ts
index d3665bc90..7a7faa911 100644
--- a/shared/server-commands/videos/live.ts
+++ b/shared/server-commands/videos/live.ts
@@ -1,10 +1,5 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg' 1import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
5import { pathExists, readdir } from 'fs-extra' 2import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
6import { join } from 'path'
7import { buildAbsoluteFixturePath, wait } from '../miscs'
8import { PeerTubeServer } from '../server/server' 3import { PeerTubeServer } from '../server/server'
9 4
10function sendRTMPStream (options: { 5function sendRTMPStream (options: {
@@ -95,43 +90,11 @@ async function waitUntilLiveSavedOnAllServers (servers: PeerTubeServer[], videoI
95 } 90 }
96} 91}
97 92
98async function checkLiveCleanupAfterSave (server: PeerTubeServer, videoUUID: string, resolutions: number[] = []) {
99 const basePath = server.servers.buildDirectory('streaming-playlists')
100 const hlsPath = join(basePath, 'hls', videoUUID)
101
102 if (resolutions.length === 0) {
103 const result = await pathExists(hlsPath)
104 expect(result).to.be.false
105
106 return
107 }
108
109 const files = await readdir(hlsPath)
110
111 // fragmented file and playlist per resolution + master playlist + segments sha256 json file
112 expect(files).to.have.lengthOf(resolutions.length * 2 + 2)
113
114 for (const resolution of resolutions) {
115 const fragmentedFile = files.find(f => f.endsWith(`-${resolution}-fragmented.mp4`))
116 expect(fragmentedFile).to.exist
117
118 const playlistFile = files.find(f => f.endsWith(`${resolution}.m3u8`))
119 expect(playlistFile).to.exist
120 }
121
122 const masterPlaylistFile = files.find(f => f.endsWith('-master.m3u8'))
123 expect(masterPlaylistFile).to.exist
124
125 const shaFile = files.find(f => f.endsWith('-segments-sha256.json'))
126 expect(shaFile).to.exist
127}
128
129export { 93export {
130 sendRTMPStream, 94 sendRTMPStream,
131 waitFfmpegUntilError, 95 waitFfmpegUntilError,
132 testFfmpegStreamError, 96 testFfmpegStreamError,
133 stopFfmpeg, 97 stopFfmpeg,
134 waitUntilLivePublishedOnAllServers, 98 waitUntilLivePublishedOnAllServers,
135 waitUntilLiveSavedOnAllServers, 99 waitUntilLiveSavedOnAllServers
136 checkLiveCleanupAfterSave
137} 100}
diff --git a/shared/server-commands/videos/playlists.ts b/shared/server-commands/videos/playlists.ts
deleted file mode 100644
index 3dde52bb9..000000000
--- a/shared/server-commands/videos/playlists.ts
+++ /dev/null
@@ -1,25 +0,0 @@
1import { expect } from 'chai'
2import { readdir } from 'fs-extra'
3import { join } from 'path'
4import { root } from '../miscs'
5
6async function checkPlaylistFilesWereRemoved (
7 playlistUUID: string,
8 internalServerNumber: number,
9 directories = [ 'thumbnails' ]
10) {
11 const testDirectory = 'test' + internalServerNumber
12
13 for (const directory of directories) {
14 const directoryPath = join(root(), testDirectory, directory)
15
16 const files = await readdir(directoryPath)
17 for (const file of files) {
18 expect(file).to.not.contain(playlistUUID)
19 }
20 }
21}
22
23export {
24 checkPlaylistFilesWereRemoved
25}
diff --git a/shared/server-commands/videos/streaming-playlists.ts b/shared/server-commands/videos/streaming-playlists.ts
deleted file mode 100644
index 0451c0efe..000000000
--- a/shared/server-commands/videos/streaming-playlists.ts
+++ /dev/null
@@ -1,77 +0,0 @@
1import { expect } from 'chai'
2import { basename } from 'path'
3import { sha256 } from '@shared/core-utils/crypto'
4import { removeFragmentedMP4Ext } from '@shared/core-utils'
5import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models'
6import { PeerTubeServer } from '../server'
7
8async function checkSegmentHash (options: {
9 server: PeerTubeServer
10 baseUrlPlaylist: string
11 baseUrlSegment: string
12 resolution: number
13 hlsPlaylist: VideoStreamingPlaylist
14}) {
15 const { server, baseUrlPlaylist, baseUrlSegment, resolution, hlsPlaylist } = options
16 const command = server.streamingPlaylists
17
18 const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
19 const videoName = basename(file.fileUrl)
20
21 const playlist = await command.get({ url: `${baseUrlPlaylist}/${removeFragmentedMP4Ext(videoName)}.m3u8` })
22
23 const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
24
25 const length = parseInt(matches[1], 10)
26 const offset = parseInt(matches[2], 10)
27 const range = `${offset}-${offset + length - 1}`
28
29 const segmentBody = await command.getSegment({
30 url: `${baseUrlSegment}/${videoName}`,
31 expectedStatus: HttpStatusCode.PARTIAL_CONTENT_206,
32 range: `bytes=${range}`
33 })
34
35 const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url })
36 expect(sha256(segmentBody)).to.equal(shaBody[videoName][range])
37}
38
39async function checkLiveSegmentHash (options: {
40 server: PeerTubeServer
41 baseUrlSegment: string
42 videoUUID: string
43 segmentName: string
44 hlsPlaylist: VideoStreamingPlaylist
45}) {
46 const { server, baseUrlSegment, videoUUID, segmentName, hlsPlaylist } = options
47 const command = server.streamingPlaylists
48
49 const segmentBody = await command.getSegment({ url: `${baseUrlSegment}/${videoUUID}/${segmentName}` })
50 const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url })
51
52 expect(sha256(segmentBody)).to.equal(shaBody[segmentName])
53}
54
55async function checkResolutionsInMasterPlaylist (options: {
56 server: PeerTubeServer
57 playlistUrl: string
58 resolutions: number[]
59}) {
60 const { server, playlistUrl, resolutions } = options
61
62 const masterPlaylist = await server.streamingPlaylists.get({ url: playlistUrl })
63
64 for (const resolution of resolutions) {
65 const reg = new RegExp(
66 '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"'
67 )
68
69 expect(masterPlaylist).to.match(reg)
70 }
71}
72
73export {
74 checkSegmentHash,
75 checkLiveSegmentHash,
76 checkResolutionsInMasterPlaylist
77}
diff --git a/shared/server-commands/videos/videos-command.ts b/shared/server-commands/videos/videos-command.ts
index 8ea828b40..ead57b9aa 100644
--- a/shared/server-commands/videos/videos-command.ts
+++ b/shared/server-commands/videos/videos-command.ts
@@ -5,8 +5,7 @@ import { createReadStream, stat } from 'fs-extra'
5import got, { Response as GotResponse } from 'got' 5import got, { Response as GotResponse } from 'got'
6import { omit } from 'lodash' 6import { omit } from 'lodash'
7import validator from 'validator' 7import validator from 'validator'
8import { buildUUID } from '@shared/core-utils/uuid' 8import { buildAbsoluteFixturePath, buildUUID, pick, wait } from '@shared/core-utils'
9import { pick } from '@shared/core-utils'
10import { 9import {
11 HttpStatusCode, 10 HttpStatusCode,
12 ResultList, 11 ResultList,
@@ -20,7 +19,6 @@ import {
20 VideosCommonQuery, 19 VideosCommonQuery,
21 VideoTranscodingCreate 20 VideoTranscodingCreate
22} from '@shared/models' 21} from '@shared/models'
23import { buildAbsoluteFixturePath, wait } from '../miscs'
24import { unwrapBody } from '../requests' 22import { unwrapBody } from '../requests'
25import { waitJobs } from '../server' 23import { waitJobs } from '../server'
26import { AbstractCommand, OverrideCommandOptions } from '../shared' 24import { AbstractCommand, OverrideCommandOptions } from '../shared'
diff --git a/shared/server-commands/videos/videos.ts b/shared/server-commands/videos/videos.ts
deleted file mode 100644
index 2c3464aa8..000000000
--- a/shared/server-commands/videos/videos.ts
+++ /dev/null
@@ -1,104 +0,0 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
2
3import { expect } from 'chai'
4import { pathExists, readdir } from 'fs-extra'
5import { basename, join } from 'path'
6import { HttpStatusCode, VideoCaption, VideoDetails } from '@shared/models'
7import { waitJobs } from '../server'
8import { PeerTubeServer } from '../server/server'
9import { VideoEdit } from './videos-command'
10
11async function checkVideoFilesWereRemoved (options: {
12 server: PeerTubeServer
13 video: VideoDetails
14 captions?: VideoCaption[]
15 onlyVideoFiles?: boolean // default false
16}) {
17 const { video, server, captions = [], onlyVideoFiles = false } = options
18
19 const webtorrentFiles = video.files || []
20 const hlsFiles = video.streamingPlaylists[0]?.files || []
21
22 const thumbnailName = basename(video.thumbnailPath)
23 const previewName = basename(video.previewPath)
24
25 const torrentNames = webtorrentFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
26
27 const captionNames = captions.map(c => basename(c.captionPath))
28
29 const webtorrentFilenames = webtorrentFiles.map(f => basename(f.fileUrl))
30 const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
31
32 let directories: { [ directory: string ]: string[] } = {
33 videos: webtorrentFilenames,
34 redundancy: webtorrentFilenames,
35 [join('playlists', 'hls')]: hlsFilenames,
36 [join('redundancy', 'hls')]: hlsFilenames
37 }
38
39 if (onlyVideoFiles !== true) {
40 directories = {
41 ...directories,
42
43 thumbnails: [ thumbnailName ],
44 previews: [ previewName ],
45 torrents: torrentNames,
46 captions: captionNames
47 }
48 }
49
50 for (const directory of Object.keys(directories)) {
51 const directoryPath = server.servers.buildDirectory(directory)
52
53 const directoryExists = await pathExists(directoryPath)
54 if (directoryExists === false) continue
55
56 const existingFiles = await readdir(directoryPath)
57 for (const existingFile of existingFiles) {
58 for (const shouldNotExist of directories[directory]) {
59 expect(existingFile, `File ${existingFile} should not exist in ${directoryPath}`).to.not.contain(shouldNotExist)
60 }
61 }
62 }
63}
64
65async function saveVideoInServers (servers: PeerTubeServer[], uuid: string) {
66 for (const server of servers) {
67 server.store.videoDetails = await server.videos.get({ id: uuid })
68 }
69}
70
71function checkUploadVideoParam (
72 server: PeerTubeServer,
73 token: string,
74 attributes: Partial<VideoEdit>,
75 expectedStatus = HttpStatusCode.OK_200,
76 mode: 'legacy' | 'resumable' = 'legacy'
77) {
78 return mode === 'legacy'
79 ? server.videos.buildLegacyUpload({ token, attributes, expectedStatus })
80 : server.videos.buildResumeUpload({ token, attributes, expectedStatus })
81}
82
83// serverNumber starts from 1
84async function uploadRandomVideoOnServers (
85 servers: PeerTubeServer[],
86 serverNumber: number,
87 additionalParams?: VideoEdit & { prefixName?: string }
88) {
89 const server = servers.find(s => s.serverNumber === serverNumber)
90 const res = await server.videos.randomUpload({ wait: false, additionalParams })
91
92 await waitJobs(servers)
93
94 return res
95}
96
97// ---------------------------------------------------------------------------
98
99export {
100 checkUploadVideoParam,
101 uploadRandomVideoOnServers,
102 checkVideoFilesWereRemoved,
103 saveVideoInServers
104}