diff options
author | Chocobozzz <me@florianbigard.com> | 2019-01-29 08:37:25 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-02-11 09:13:02 +0100 |
commit | 092092969633bbcf6d4891a083ea497a7d5c3154 (patch) | |
tree | 69e82fe4f60c444cca216830e96afe143a9dac71 /shared | |
parent | 4348a27d252a3349bafa7ef4859c0e2cf060c255 (diff) | |
download | PeerTube-092092969633bbcf6d4891a083ea497a7d5c3154.tar.gz PeerTube-092092969633bbcf6d4891a083ea497a7d5c3154.tar.zst PeerTube-092092969633bbcf6d4891a083ea497a7d5c3154.zip |
Add hls support on server
Diffstat (limited to 'shared')
-rw-r--r-- | shared/models/activitypub/objects/cache-file-object.ts | 4 | ||||
-rw-r--r-- | shared/models/activitypub/objects/common-objects.ts | 60 | ||||
-rw-r--r-- | shared/models/server/custom-config.model.ts | 3 | ||||
-rw-r--r-- | shared/models/server/server-config.model.ts | 8 | ||||
-rw-r--r-- | shared/models/videos/video-streaming-playlist.model.ts | 12 | ||||
-rw-r--r-- | shared/models/videos/video-streaming-playlist.type.ts | 3 | ||||
-rw-r--r-- | shared/models/videos/video.model.ts | 5 | ||||
-rw-r--r-- | shared/utils/index.ts | 2 | ||||
-rw-r--r-- | shared/utils/requests/requests.ts | 13 | ||||
-rw-r--r-- | shared/utils/server/config.ts | 3 | ||||
-rw-r--r-- | shared/utils/server/servers.ts | 7 | ||||
-rw-r--r-- | shared/utils/videos/video-playlists.ts | 21 | ||||
-rw-r--r-- | shared/utils/videos/videos.ts | 13 |
13 files changed, 125 insertions, 29 deletions
diff --git a/shared/models/activitypub/objects/cache-file-object.ts b/shared/models/activitypub/objects/cache-file-object.ts index 0a5125f5b..4b0a3a724 100644 --- a/shared/models/activitypub/objects/cache-file-object.ts +++ b/shared/models/activitypub/objects/cache-file-object.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { ActivityVideoUrlObject } from './common-objects' | 1 | import { ActivityVideoUrlObject, ActivityPlaylistUrlObject } from './common-objects' |
2 | 2 | ||
3 | export interface CacheFileObject { | 3 | export interface CacheFileObject { |
4 | id: string | 4 | id: string |
5 | type: 'CacheFile', | 5 | type: 'CacheFile', |
6 | object: string | 6 | object: string |
7 | expires: string | 7 | expires: string |
8 | url: ActivityVideoUrlObject | 8 | url: ActivityVideoUrlObject | ActivityPlaylistUrlObject |
9 | } | 9 | } |
diff --git a/shared/models/activitypub/objects/common-objects.ts b/shared/models/activitypub/objects/common-objects.ts index 118a4f43d..8c89810d6 100644 --- a/shared/models/activitypub/objects/common-objects.ts +++ b/shared/models/activitypub/objects/common-objects.ts | |||
@@ -28,25 +28,47 @@ export type ActivityVideoUrlObject = { | |||
28 | fps: number | 28 | fps: number |
29 | } | 29 | } |
30 | 30 | ||
31 | export type ActivityUrlObject = | 31 | export type ActivityPlaylistSegmentHashesObject = { |
32 | ActivityVideoUrlObject | 32 | type: 'Link' |
33 | | | 33 | name: 'sha256' |
34 | { | 34 | // TODO: remove mimeType (backward compatibility, introduced in v1.1.0) |
35 | type: 'Link' | 35 | mimeType?: 'application/json' |
36 | // TODO: remove mimeType (backward compatibility, introduced in v1.1.0) | 36 | mediaType: 'application/json' |
37 | mimeType?: 'application/x-bittorrent' | 'application/x-bittorrent;x-scheme-handler/magnet' | 37 | href: string |
38 | mediaType: 'application/x-bittorrent' | 'application/x-bittorrent;x-scheme-handler/magnet' | 38 | } |
39 | href: string | 39 | |
40 | height: number | 40 | export type ActivityPlaylistInfohashesObject = { |
41 | } | 41 | type: 'Infohash' |
42 | | | 42 | name: string |
43 | { | 43 | } |
44 | type: 'Link' | 44 | |
45 | // TODO: remove mimeType (backward compatibility, introduced in v1.1.0) | 45 | export type ActivityPlaylistUrlObject = { |
46 | mimeType?: 'text/html' | 46 | type: 'Link' |
47 | mediaType: 'text/html' | 47 | // TODO: remove mimeType (backward compatibility, introduced in v1.1.0) |
48 | href: string | 48 | mimeType?: 'application/x-mpegURL' |
49 | } | 49 | mediaType: 'application/x-mpegURL' |
50 | href: string | ||
51 | tag?: (ActivityPlaylistSegmentHashesObject | ActivityPlaylistInfohashesObject)[] | ||
52 | } | ||
53 | |||
54 | export type ActivityBitTorrentUrlObject = { | ||
55 | type: 'Link' | ||
56 | // TODO: remove mimeType (backward compatibility, introduced in v1.1.0) | ||
57 | mimeType?: 'application/x-bittorrent' | 'application/x-bittorrent;x-scheme-handler/magnet' | ||
58 | mediaType: 'application/x-bittorrent' | 'application/x-bittorrent;x-scheme-handler/magnet' | ||
59 | href: string | ||
60 | height: number | ||
61 | } | ||
62 | |||
63 | export type ActivityHtmlUrlObject = { | ||
64 | type: 'Link' | ||
65 | // TODO: remove mimeType (backward compatibility, introduced in v1.1.0) | ||
66 | mimeType?: 'text/html' | ||
67 | mediaType: 'text/html' | ||
68 | href: string | ||
69 | } | ||
70 | |||
71 | export type ActivityUrlObject = ActivityVideoUrlObject | ActivityPlaylistUrlObject | ActivityBitTorrentUrlObject | ActivityHtmlUrlObject | ||
50 | 72 | ||
51 | export interface ActivityPubAttributedTo { | 73 | export interface ActivityPubAttributedTo { |
52 | type: 'Group' | 'Person' | 74 | type: 'Group' | 'Person' |
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts index 7a3eaa33f..b42ff90c6 100644 --- a/shared/models/server/custom-config.model.ts +++ b/shared/models/server/custom-config.model.ts | |||
@@ -61,6 +61,9 @@ export interface CustomConfig { | |||
61 | '720p': boolean | 61 | '720p': boolean |
62 | '1080p': boolean | 62 | '1080p': boolean |
63 | } | 63 | } |
64 | hls: { | ||
65 | enabled: boolean | ||
66 | } | ||
64 | } | 67 | } |
65 | 68 | ||
66 | import: { | 69 | import: { |
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index f4245ed4d..baafed31f 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts | |||
@@ -25,11 +25,15 @@ export interface ServerConfig { | |||
25 | 25 | ||
26 | signup: { | 26 | signup: { |
27 | allowed: boolean, | 27 | allowed: boolean, |
28 | allowedForCurrentIP: boolean, | 28 | allowedForCurrentIP: boolean |
29 | requiresEmailVerification: boolean | 29 | requiresEmailVerification: boolean |
30 | } | 30 | } |
31 | 31 | ||
32 | transcoding: { | 32 | transcoding: { |
33 | hls: { | ||
34 | enabled: boolean | ||
35 | } | ||
36 | |||
33 | enabledResolutions: number[] | 37 | enabledResolutions: number[] |
34 | } | 38 | } |
35 | 39 | ||
@@ -48,7 +52,7 @@ export interface ServerConfig { | |||
48 | file: { | 52 | file: { |
49 | size: { | 53 | size: { |
50 | max: number | 54 | max: number |
51 | }, | 55 | } |
52 | extensions: string[] | 56 | extensions: string[] |
53 | } | 57 | } |
54 | } | 58 | } |
diff --git a/shared/models/videos/video-streaming-playlist.model.ts b/shared/models/videos/video-streaming-playlist.model.ts new file mode 100644 index 000000000..17f8fe865 --- /dev/null +++ b/shared/models/videos/video-streaming-playlist.model.ts | |||
@@ -0,0 +1,12 @@ | |||
1 | import { VideoStreamingPlaylistType } from './video-streaming-playlist.type' | ||
2 | |||
3 | export class VideoStreamingPlaylist { | ||
4 | id: number | ||
5 | type: VideoStreamingPlaylistType | ||
6 | playlistUrl: string | ||
7 | segmentsSha256Url: string | ||
8 | |||
9 | redundancies: { | ||
10 | baseUrl: string | ||
11 | }[] | ||
12 | } | ||
diff --git a/shared/models/videos/video-streaming-playlist.type.ts b/shared/models/videos/video-streaming-playlist.type.ts new file mode 100644 index 000000000..3b403f295 --- /dev/null +++ b/shared/models/videos/video-streaming-playlist.type.ts | |||
@@ -0,0 +1,3 @@ | |||
1 | export enum VideoStreamingPlaylistType { | ||
2 | HLS = 1 | ||
3 | } | ||
diff --git a/shared/models/videos/video.model.ts b/shared/models/videos/video.model.ts index 022876a0b..803db8255 100644 --- a/shared/models/videos/video.model.ts +++ b/shared/models/videos/video.model.ts | |||
@@ -5,6 +5,7 @@ import { VideoChannel } from './channel/video-channel.model' | |||
5 | import { VideoPrivacy } from './video-privacy.enum' | 5 | import { VideoPrivacy } from './video-privacy.enum' |
6 | import { VideoScheduleUpdate } from './video-schedule-update.model' | 6 | import { VideoScheduleUpdate } from './video-schedule-update.model' |
7 | import { VideoConstant } from './video-constant.model' | 7 | import { VideoConstant } from './video-constant.model' |
8 | import { VideoStreamingPlaylist } from './video-streaming-playlist.model' | ||
8 | 9 | ||
9 | export interface VideoFile { | 10 | export interface VideoFile { |
10 | magnetUri: string | 11 | magnetUri: string |
@@ -86,4 +87,8 @@ export interface VideoDetails extends Video { | |||
86 | // Not optional in details (unlike in Video) | 87 | // Not optional in details (unlike in Video) |
87 | waitTranscoding: boolean | 88 | waitTranscoding: boolean |
88 | state: VideoConstant<VideoState> | 89 | state: VideoConstant<VideoState> |
90 | |||
91 | trackerUrls: string[] | ||
92 | |||
93 | streamingPlaylists: VideoStreamingPlaylist[] | ||
89 | } | 94 | } |
diff --git a/shared/utils/index.ts b/shared/utils/index.ts index e08bbfd2a..156901372 100644 --- a/shared/utils/index.ts +++ b/shared/utils/index.ts | |||
@@ -17,6 +17,8 @@ export * from './users/users' | |||
17 | export * from './videos/video-abuses' | 17 | export * from './videos/video-abuses' |
18 | export * from './videos/video-blacklist' | 18 | export * from './videos/video-blacklist' |
19 | export * from './videos/video-channels' | 19 | export * from './videos/video-channels' |
20 | export * from './videos/video-comments' | ||
21 | export * from './videos/video-playlists' | ||
20 | export * from './videos/videos' | 22 | export * from './videos/videos' |
21 | export * from './videos/video-change-ownership' | 23 | export * from './videos/video-change-ownership' |
22 | export * from './feeds/feeds' | 24 | export * from './feeds/feeds' |
diff --git a/shared/utils/requests/requests.ts b/shared/utils/requests/requests.ts index 77e9f6164..fc687c701 100644 --- a/shared/utils/requests/requests.ts +++ b/shared/utils/requests/requests.ts | |||
@@ -1,10 +1,17 @@ | |||
1 | import * as request from 'supertest' | 1 | import * as request from 'supertest' |
2 | import { buildAbsoluteFixturePath, root } from '../miscs/miscs' | 2 | import { buildAbsoluteFixturePath, root } from '../miscs/miscs' |
3 | import { isAbsolute, join } from 'path' | 3 | import { isAbsolute, join } from 'path' |
4 | import { parse } from 'url' | ||
5 | |||
6 | function makeRawRequest (url: string, statusCodeExpected?: number) { | ||
7 | const { host, protocol, pathname } = parse(url) | ||
8 | |||
9 | return makeGetRequest({ url: `${protocol}//${host}`, path: pathname, statusCodeExpected }) | ||
10 | } | ||
4 | 11 | ||
5 | function makeGetRequest (options: { | 12 | function makeGetRequest (options: { |
6 | url: string, | 13 | url: string, |
7 | path: string, | 14 | path?: string, |
8 | query?: any, | 15 | query?: any, |
9 | token?: string, | 16 | token?: string, |
10 | statusCodeExpected?: number, | 17 | statusCodeExpected?: number, |
@@ -13,8 +20,7 @@ function makeGetRequest (options: { | |||
13 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | 20 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 |
14 | if (options.contentType === undefined) options.contentType = 'application/json' | 21 | if (options.contentType === undefined) options.contentType = 'application/json' |
15 | 22 | ||
16 | const req = request(options.url) | 23 | const req = request(options.url).get(options.path) |
17 | .get(options.path) | ||
18 | 24 | ||
19 | if (options.contentType) req.set('Accept', options.contentType) | 25 | if (options.contentType) req.set('Accept', options.contentType) |
20 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | 26 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) |
@@ -164,5 +170,6 @@ export { | |||
164 | makePostBodyRequest, | 170 | makePostBodyRequest, |
165 | makePutBodyRequest, | 171 | makePutBodyRequest, |
166 | makeDeleteRequest, | 172 | makeDeleteRequest, |
173 | makeRawRequest, | ||
167 | updateAvatarRequest | 174 | updateAvatarRequest |
168 | } | 175 | } |
diff --git a/shared/utils/server/config.ts b/shared/utils/server/config.ts index 0c5512bab..29c24cff9 100644 --- a/shared/utils/server/config.ts +++ b/shared/utils/server/config.ts | |||
@@ -97,6 +97,9 @@ function updateCustomSubConfig (url: string, token: string, newConfig: any) { | |||
97 | '480p': true, | 97 | '480p': true, |
98 | '720p': false, | 98 | '720p': false, |
99 | '1080p': false | 99 | '1080p': false |
100 | }, | ||
101 | hls: { | ||
102 | enabled: false | ||
100 | } | 103 | } |
101 | }, | 104 | }, |
102 | import: { | 105 | import: { |
diff --git a/shared/utils/server/servers.ts b/shared/utils/server/servers.ts index cb57e0a69..bde7dd5c2 100644 --- a/shared/utils/server/servers.ts +++ b/shared/utils/server/servers.ts | |||
@@ -166,9 +166,13 @@ async function reRunServer (server: ServerInfo, configOverride?: any) { | |||
166 | } | 166 | } |
167 | 167 | ||
168 | async function checkTmpIsEmpty (server: ServerInfo) { | 168 | async function checkTmpIsEmpty (server: ServerInfo) { |
169 | return checkDirectoryIsEmpty(server, 'tmp') | ||
170 | } | ||
171 | |||
172 | async function checkDirectoryIsEmpty (server: ServerInfo, directory: string) { | ||
169 | const testDirectory = 'test' + server.serverNumber | 173 | const testDirectory = 'test' + server.serverNumber |
170 | 174 | ||
171 | const directoryPath = join(root(), testDirectory, 'tmp') | 175 | const directoryPath = join(root(), testDirectory, directory) |
172 | 176 | ||
173 | const directoryExists = existsSync(directoryPath) | 177 | const directoryExists = existsSync(directoryPath) |
174 | expect(directoryExists).to.be.true | 178 | expect(directoryExists).to.be.true |
@@ -199,6 +203,7 @@ async function waitUntilLog (server: ServerInfo, str: string, count = 1) { | |||
199 | // --------------------------------------------------------------------------- | 203 | // --------------------------------------------------------------------------- |
200 | 204 | ||
201 | export { | 205 | export { |
206 | checkDirectoryIsEmpty, | ||
202 | checkTmpIsEmpty, | 207 | checkTmpIsEmpty, |
203 | ServerInfo, | 208 | ServerInfo, |
204 | flushAndRunMultipleServers, | 209 | flushAndRunMultipleServers, |
diff --git a/shared/utils/videos/video-playlists.ts b/shared/utils/videos/video-playlists.ts new file mode 100644 index 000000000..9a0710ca6 --- /dev/null +++ b/shared/utils/videos/video-playlists.ts | |||
@@ -0,0 +1,21 @@ | |||
1 | import { makeRawRequest } from '../requests/requests' | ||
2 | |||
3 | function getPlaylist (url: string, statusCodeExpected = 200) { | ||
4 | return makeRawRequest(url, statusCodeExpected) | ||
5 | } | ||
6 | |||
7 | function getSegment (url: string, statusCodeExpected = 200) { | ||
8 | return makeRawRequest(url, statusCodeExpected) | ||
9 | } | ||
10 | |||
11 | function getSegmentSha256 (url: string, statusCodeExpected = 200) { | ||
12 | return makeRawRequest(url, statusCodeExpected) | ||
13 | } | ||
14 | |||
15 | // --------------------------------------------------------------------------- | ||
16 | |||
17 | export { | ||
18 | getPlaylist, | ||
19 | getSegment, | ||
20 | getSegmentSha256 | ||
21 | } | ||
diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts index 0cf6e7c4f..b5b33e038 100644 --- a/shared/utils/videos/videos.ts +++ b/shared/utils/videos/videos.ts | |||
@@ -271,7 +271,16 @@ function removeVideo (url: string, token: string, id: number | string, expectedS | |||
271 | async function checkVideoFilesWereRemoved ( | 271 | async function checkVideoFilesWereRemoved ( |
272 | videoUUID: string, | 272 | videoUUID: string, |
273 | serverNumber: number, | 273 | serverNumber: number, |
274 | directories = [ 'redundancy', 'videos', 'thumbnails', 'torrents', 'previews', 'captions' ] | 274 | directories = [ |
275 | 'redundancy', | ||
276 | 'videos', | ||
277 | 'thumbnails', | ||
278 | 'torrents', | ||
279 | 'previews', | ||
280 | 'captions', | ||
281 | join('playlists', 'hls'), | ||
282 | join('redundancy', 'hls') | ||
283 | ] | ||
275 | ) { | 284 | ) { |
276 | const testDirectory = 'test' + serverNumber | 285 | const testDirectory = 'test' + serverNumber |
277 | 286 | ||
@@ -279,7 +288,7 @@ async function checkVideoFilesWereRemoved ( | |||
279 | const directoryPath = join(root(), testDirectory, directory) | 288 | const directoryPath = join(root(), testDirectory, directory) |
280 | 289 | ||
281 | const directoryExists = existsSync(directoryPath) | 290 | const directoryExists = existsSync(directoryPath) |
282 | expect(directoryExists).to.be.true | 291 | if (!directoryExists) continue |
283 | 292 | ||
284 | const files = await readdir(directoryPath) | 293 | const files = await readdir(directoryPath) |
285 | for (const file of files) { | 294 | for (const file of files) { |