diff options
author | Chocobozzz <me@florianbigard.com> | 2021-01-28 15:52:44 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-01-28 15:55:39 +0100 |
commit | 1896bca09e088b0da9d5e845407ecebae330618c (patch) | |
tree | 56041c445c0cd49aca536d0fd6b586730f4d341e /server/lib/plugins | |
parent | 529b37527cff5203a0689a15ce73dcee6e1eece2 (diff) | |
download | PeerTube-1896bca09e088b0da9d5e845407ecebae330618c.tar.gz PeerTube-1896bca09e088b0da9d5e845407ecebae330618c.tar.zst PeerTube-1896bca09e088b0da9d5e845407ecebae330618c.zip |
Support transcoding options/encoders by plugins
Diffstat (limited to 'server/lib/plugins')
-rw-r--r-- | server/lib/plugins/plugin-helpers-builder.ts (renamed from server/lib/plugins/plugin-helpers.ts) | 0 | ||||
-rw-r--r-- | server/lib/plugins/plugin-manager.ts | 35 | ||||
-rw-r--r-- | server/lib/plugins/register-helpers.ts (renamed from server/lib/plugins/register-helpers-store.ts) | 91 |
3 files changed, 107 insertions, 19 deletions
diff --git a/server/lib/plugins/plugin-helpers.ts b/server/lib/plugins/plugin-helpers-builder.ts index 39773f693..39773f693 100644 --- a/server/lib/plugins/plugin-helpers.ts +++ b/server/lib/plugins/plugin-helpers-builder.ts | |||
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index 8e7491257..c19b40135 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts | |||
@@ -20,7 +20,7 @@ import { PLUGIN_GLOBAL_CSS_PATH } from '../../initializers/constants' | |||
20 | import { PluginModel } from '../../models/server/plugin' | 20 | import { PluginModel } from '../../models/server/plugin' |
21 | import { PluginLibrary, RegisterServerAuthExternalOptions, RegisterServerAuthPassOptions, RegisterServerOptions } from '../../types/plugins' | 21 | import { PluginLibrary, RegisterServerAuthExternalOptions, RegisterServerAuthPassOptions, RegisterServerOptions } from '../../types/plugins' |
22 | import { ClientHtml } from '../client-html' | 22 | import { ClientHtml } from '../client-html' |
23 | import { RegisterHelpersStore } from './register-helpers-store' | 23 | import { RegisterHelpers } from './register-helpers' |
24 | import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' | 24 | import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' |
25 | 25 | ||
26 | export interface RegisteredPlugin { | 26 | export interface RegisteredPlugin { |
@@ -40,7 +40,7 @@ export interface RegisteredPlugin { | |||
40 | css: string[] | 40 | css: string[] |
41 | 41 | ||
42 | // Only if this is a plugin | 42 | // Only if this is a plugin |
43 | registerHelpersStore?: RegisterHelpersStore | 43 | registerHelpers?: RegisterHelpers |
44 | unregister?: Function | 44 | unregister?: Function |
45 | } | 45 | } |
46 | 46 | ||
@@ -109,7 +109,7 @@ export class PluginManager implements ServerHook { | |||
109 | npmName: p.npmName, | 109 | npmName: p.npmName, |
110 | name: p.name, | 110 | name: p.name, |
111 | version: p.version, | 111 | version: p.version, |
112 | idAndPassAuths: p.registerHelpersStore.getIdAndPassAuths() | 112 | idAndPassAuths: p.registerHelpers.getIdAndPassAuths() |
113 | })) | 113 | })) |
114 | .filter(v => v.idAndPassAuths.length !== 0) | 114 | .filter(v => v.idAndPassAuths.length !== 0) |
115 | } | 115 | } |
@@ -120,7 +120,7 @@ export class PluginManager implements ServerHook { | |||
120 | npmName: p.npmName, | 120 | npmName: p.npmName, |
121 | name: p.name, | 121 | name: p.name, |
122 | version: p.version, | 122 | version: p.version, |
123 | externalAuths: p.registerHelpersStore.getExternalAuths() | 123 | externalAuths: p.registerHelpers.getExternalAuths() |
124 | })) | 124 | })) |
125 | .filter(v => v.externalAuths.length !== 0) | 125 | .filter(v => v.externalAuths.length !== 0) |
126 | } | 126 | } |
@@ -129,14 +129,14 @@ export class PluginManager implements ServerHook { | |||
129 | const result = this.getRegisteredPluginOrTheme(npmName) | 129 | const result = this.getRegisteredPluginOrTheme(npmName) |
130 | if (!result || result.type !== PluginType.PLUGIN) return [] | 130 | if (!result || result.type !== PluginType.PLUGIN) return [] |
131 | 131 | ||
132 | return result.registerHelpersStore.getSettings() | 132 | return result.registerHelpers.getSettings() |
133 | } | 133 | } |
134 | 134 | ||
135 | getRouter (npmName: string) { | 135 | getRouter (npmName: string) { |
136 | const result = this.getRegisteredPluginOrTheme(npmName) | 136 | const result = this.getRegisteredPluginOrTheme(npmName) |
137 | if (!result || result.type !== PluginType.PLUGIN) return null | 137 | if (!result || result.type !== PluginType.PLUGIN) return null |
138 | 138 | ||
139 | return result.registerHelpersStore.getRouter() | 139 | return result.registerHelpers.getRouter() |
140 | } | 140 | } |
141 | 141 | ||
142 | getTranslations (locale: string) { | 142 | getTranslations (locale: string) { |
@@ -194,7 +194,7 @@ export class PluginManager implements ServerHook { | |||
194 | logger.error('Cannot find plugin %s to call on settings changed.', name) | 194 | logger.error('Cannot find plugin %s to call on settings changed.', name) |
195 | } | 195 | } |
196 | 196 | ||
197 | for (const cb of registered.registerHelpersStore.getOnSettingsChangedCallbacks()) { | 197 | for (const cb of registered.registerHelpers.getOnSettingsChangedCallbacks()) { |
198 | try { | 198 | try { |
199 | cb(settings) | 199 | cb(settings) |
200 | } catch (err) { | 200 | } catch (err) { |
@@ -268,8 +268,9 @@ export class PluginManager implements ServerHook { | |||
268 | this.hooks[key] = this.hooks[key].filter(h => h.npmName !== npmName) | 268 | this.hooks[key] = this.hooks[key].filter(h => h.npmName !== npmName) |
269 | } | 269 | } |
270 | 270 | ||
271 | const store = plugin.registerHelpersStore | 271 | const store = plugin.registerHelpers |
272 | store.reinitVideoConstants(plugin.npmName) | 272 | store.reinitVideoConstants(plugin.npmName) |
273 | store.reinitTranscodingProfilesAndEncoders(plugin.npmName) | ||
273 | 274 | ||
274 | logger.info('Regenerating registered plugin CSS to global file.') | 275 | logger.info('Regenerating registered plugin CSS to global file.') |
275 | await this.regeneratePluginGlobalCSS() | 276 | await this.regeneratePluginGlobalCSS() |
@@ -375,11 +376,11 @@ export class PluginManager implements ServerHook { | |||
375 | this.sanitizeAndCheckPackageJSONOrThrow(packageJSON, plugin.type) | 376 | this.sanitizeAndCheckPackageJSONOrThrow(packageJSON, plugin.type) |
376 | 377 | ||
377 | let library: PluginLibrary | 378 | let library: PluginLibrary |
378 | let registerHelpersStore: RegisterHelpersStore | 379 | let registerHelpers: RegisterHelpers |
379 | if (plugin.type === PluginType.PLUGIN) { | 380 | if (plugin.type === PluginType.PLUGIN) { |
380 | const result = await this.registerPlugin(plugin, pluginPath, packageJSON) | 381 | const result = await this.registerPlugin(plugin, pluginPath, packageJSON) |
381 | library = result.library | 382 | library = result.library |
382 | registerHelpersStore = result.registerStore | 383 | registerHelpers = result.registerStore |
383 | } | 384 | } |
384 | 385 | ||
385 | const clientScripts: { [id: string]: ClientScript } = {} | 386 | const clientScripts: { [id: string]: ClientScript } = {} |
@@ -398,7 +399,7 @@ export class PluginManager implements ServerHook { | |||
398 | staticDirs: packageJSON.staticDirs, | 399 | staticDirs: packageJSON.staticDirs, |
399 | clientScripts, | 400 | clientScripts, |
400 | css: packageJSON.css, | 401 | css: packageJSON.css, |
401 | registerHelpersStore: registerHelpersStore || undefined, | 402 | registerHelpers: registerHelpers || undefined, |
402 | unregister: library ? library.unregister : undefined | 403 | unregister: library ? library.unregister : undefined |
403 | } | 404 | } |
404 | 405 | ||
@@ -512,8 +513,8 @@ export class PluginManager implements ServerHook { | |||
512 | const plugin = this.getRegisteredPluginOrTheme(npmName) | 513 | const plugin = this.getRegisteredPluginOrTheme(npmName) |
513 | if (!plugin || plugin.type !== PluginType.PLUGIN) return null | 514 | if (!plugin || plugin.type !== PluginType.PLUGIN) return null |
514 | 515 | ||
515 | let auths: (RegisterServerAuthPassOptions | RegisterServerAuthExternalOptions)[] = plugin.registerHelpersStore.getIdAndPassAuths() | 516 | let auths: (RegisterServerAuthPassOptions | RegisterServerAuthExternalOptions)[] = plugin.registerHelpers.getIdAndPassAuths() |
516 | auths = auths.concat(plugin.registerHelpersStore.getExternalAuths()) | 517 | auths = auths.concat(plugin.registerHelpers.getExternalAuths()) |
517 | 518 | ||
518 | return auths.find(a => a.authName === authName) | 519 | return auths.find(a => a.authName === authName) |
519 | } | 520 | } |
@@ -538,7 +539,7 @@ export class PluginManager implements ServerHook { | |||
538 | private getRegisterHelpers ( | 539 | private getRegisterHelpers ( |
539 | npmName: string, | 540 | npmName: string, |
540 | plugin: PluginModel | 541 | plugin: PluginModel |
541 | ): { registerStore: RegisterHelpersStore, registerOptions: RegisterServerOptions } { | 542 | ): { registerStore: RegisterHelpers, registerOptions: RegisterServerOptions } { |
542 | const onHookAdded = (options: RegisterServerHookOptions) => { | 543 | const onHookAdded = (options: RegisterServerHookOptions) => { |
543 | if (!this.hooks[options.target]) this.hooks[options.target] = [] | 544 | if (!this.hooks[options.target]) this.hooks[options.target] = [] |
544 | 545 | ||
@@ -550,11 +551,11 @@ export class PluginManager implements ServerHook { | |||
550 | }) | 551 | }) |
551 | } | 552 | } |
552 | 553 | ||
553 | const registerHelpersStore = new RegisterHelpersStore(npmName, plugin, onHookAdded.bind(this)) | 554 | const registerHelpers = new RegisterHelpers(npmName, plugin, onHookAdded.bind(this)) |
554 | 555 | ||
555 | return { | 556 | return { |
556 | registerStore: registerHelpersStore, | 557 | registerStore: registerHelpers, |
557 | registerOptions: registerHelpersStore.buildRegisterHelpers() | 558 | registerOptions: registerHelpers.buildRegisterHelpers() |
558 | } | 559 | } |
559 | } | 560 | } |
560 | 561 | ||
diff --git a/server/lib/plugins/register-helpers-store.ts b/server/lib/plugins/register-helpers.ts index c73079302..3a38a4835 100644 --- a/server/lib/plugins/register-helpers-store.ts +++ b/server/lib/plugins/register-helpers.ts | |||
@@ -17,6 +17,7 @@ import { | |||
17 | RegisterServerOptions | 17 | RegisterServerOptions |
18 | } from '@server/types/plugins' | 18 | } from '@server/types/plugins' |
19 | import { | 19 | import { |
20 | EncoderOptionsBuilder, | ||
20 | PluginPlaylistPrivacyManager, | 21 | PluginPlaylistPrivacyManager, |
21 | PluginSettingsManager, | 22 | PluginSettingsManager, |
22 | PluginStorageManager, | 23 | PluginStorageManager, |
@@ -28,7 +29,8 @@ import { | |||
28 | RegisterServerSettingOptions | 29 | RegisterServerSettingOptions |
29 | } from '@shared/models' | 30 | } from '@shared/models' |
30 | import { serverHookObject } from '@shared/models/plugins/server-hook.model' | 31 | import { serverHookObject } from '@shared/models/plugins/server-hook.model' |
31 | import { buildPluginHelpers } from './plugin-helpers' | 32 | import { VideoTranscodingProfilesManager } from '../video-transcoding-profiles' |
33 | import { buildPluginHelpers } from './plugin-helpers-builder' | ||
32 | 34 | ||
33 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' | 35 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' |
34 | type VideoConstant = { [key in number | string]: string } | 36 | type VideoConstant = { [key in number | string]: string } |
@@ -40,7 +42,7 @@ type UpdatedVideoConstant = { | |||
40 | } | 42 | } |
41 | } | 43 | } |
42 | 44 | ||
43 | export class RegisterHelpersStore { | 45 | export class RegisterHelpers { |
44 | private readonly updatedVideoConstants: UpdatedVideoConstant = { | 46 | private readonly updatedVideoConstants: UpdatedVideoConstant = { |
45 | playlistPrivacy: { added: [], deleted: [] }, | 47 | playlistPrivacy: { added: [], deleted: [] }, |
46 | privacy: { added: [], deleted: [] }, | 48 | privacy: { added: [], deleted: [] }, |
@@ -49,6 +51,23 @@ export class RegisterHelpersStore { | |||
49 | category: { added: [], deleted: [] } | 51 | category: { added: [], deleted: [] } |
50 | } | 52 | } |
51 | 53 | ||
54 | private readonly transcodingProfiles: { | ||
55 | [ npmName: string ]: { | ||
56 | type: 'vod' | 'live' | ||
57 | encoder: string | ||
58 | profile: string | ||
59 | }[] | ||
60 | } = {} | ||
61 | |||
62 | private readonly transcodingEncoders: { | ||
63 | [ npmName: string ]: { | ||
64 | type: 'vod' | 'live' | ||
65 | streamType: 'audio' | 'video' | ||
66 | encoder: string | ||
67 | priority: number | ||
68 | }[] | ||
69 | } = {} | ||
70 | |||
52 | private readonly settings: RegisterServerSettingOptions[] = [] | 71 | private readonly settings: RegisterServerSettingOptions[] = [] |
53 | 72 | ||
54 | private idAndPassAuths: RegisterServerAuthPassOptions[] = [] | 73 | private idAndPassAuths: RegisterServerAuthPassOptions[] = [] |
@@ -83,6 +102,8 @@ export class RegisterHelpersStore { | |||
83 | const videoPrivacyManager = this.buildVideoPrivacyManager() | 102 | const videoPrivacyManager = this.buildVideoPrivacyManager() |
84 | const playlistPrivacyManager = this.buildPlaylistPrivacyManager() | 103 | const playlistPrivacyManager = this.buildPlaylistPrivacyManager() |
85 | 104 | ||
105 | const transcodingManager = this.buildTranscodingManager() | ||
106 | |||
86 | const registerIdAndPassAuth = this.buildRegisterIdAndPassAuth() | 107 | const registerIdAndPassAuth = this.buildRegisterIdAndPassAuth() |
87 | const registerExternalAuth = this.buildRegisterExternalAuth() | 108 | const registerExternalAuth = this.buildRegisterExternalAuth() |
88 | const unregisterIdAndPassAuth = this.buildUnregisterIdAndPassAuth() | 109 | const unregisterIdAndPassAuth = this.buildUnregisterIdAndPassAuth() |
@@ -106,6 +127,8 @@ export class RegisterHelpersStore { | |||
106 | videoPrivacyManager, | 127 | videoPrivacyManager, |
107 | playlistPrivacyManager, | 128 | playlistPrivacyManager, |
108 | 129 | ||
130 | transcodingManager, | ||
131 | |||
109 | registerIdAndPassAuth, | 132 | registerIdAndPassAuth, |
110 | registerExternalAuth, | 133 | registerExternalAuth, |
111 | unregisterIdAndPassAuth, | 134 | unregisterIdAndPassAuth, |
@@ -141,6 +164,22 @@ export class RegisterHelpersStore { | |||
141 | } | 164 | } |
142 | } | 165 | } |
143 | 166 | ||
167 | reinitTranscodingProfilesAndEncoders (npmName: string) { | ||
168 | const profiles = this.transcodingProfiles[npmName] | ||
169 | if (Array.isArray(profiles)) { | ||
170 | for (const profile of profiles) { | ||
171 | VideoTranscodingProfilesManager.Instance.removeProfile(profile) | ||
172 | } | ||
173 | } | ||
174 | |||
175 | const encoders = this.transcodingEncoders[npmName] | ||
176 | if (Array.isArray(encoders)) { | ||
177 | for (const o of encoders) { | ||
178 | VideoTranscodingProfilesManager.Instance.removeEncoderPriority(o.type, o.streamType, o.encoder, o.priority) | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | |||
144 | getSettings () { | 183 | getSettings () { |
145 | return this.settings | 184 | return this.settings |
146 | } | 185 | } |
@@ -354,4 +393,52 @@ export class RegisterHelpersStore { | |||
354 | 393 | ||
355 | return true | 394 | return true |
356 | } | 395 | } |
396 | |||
397 | private buildTranscodingManager () { | ||
398 | const self = this | ||
399 | |||
400 | function addProfile (type: 'live' | 'vod', encoder: string, profile: string, builder: EncoderOptionsBuilder) { | ||
401 | if (profile === 'default') { | ||
402 | logger.error('A plugin cannot add a default live transcoding profile') | ||
403 | return false | ||
404 | } | ||
405 | |||
406 | VideoTranscodingProfilesManager.Instance.addProfile({ | ||
407 | type, | ||
408 | encoder, | ||
409 | profile, | ||
410 | builder | ||
411 | }) | ||
412 | |||
413 | if (!self.transcodingProfiles[self.npmName]) self.transcodingProfiles[self.npmName] = [] | ||
414 | self.transcodingProfiles[self.npmName].push({ type, encoder, profile }) | ||
415 | |||
416 | return true | ||
417 | } | ||
418 | |||
419 | function addEncoderPriority (type: 'live' | 'vod', streamType: 'audio' | 'video', encoder: string, priority: number) { | ||
420 | VideoTranscodingProfilesManager.Instance.addEncoderPriority(type, streamType, encoder, priority) | ||
421 | |||
422 | if (!self.transcodingEncoders[self.npmName]) self.transcodingEncoders[self.npmName] = [] | ||
423 | self.transcodingEncoders[self.npmName].push({ type, streamType, encoder, priority }) | ||
424 | } | ||
425 | |||
426 | return { | ||
427 | addLiveProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder) { | ||
428 | return addProfile('live', encoder, profile, builder) | ||
429 | }, | ||
430 | |||
431 | addVODProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder) { | ||
432 | return addProfile('vod', encoder, profile, builder) | ||
433 | }, | ||
434 | |||
435 | addLiveEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number) { | ||
436 | return addEncoderPriority('live', streamType, encoder, priority) | ||
437 | }, | ||
438 | |||
439 | addVODEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number) { | ||
440 | return addEncoderPriority('vod', streamType, encoder, priority) | ||
441 | } | ||
442 | } | ||
443 | } | ||
357 | } | 444 | } |