Plugins & Themes API
This is the API reference for plugins and themes. An introduction and quickstart into its use is provided in the corresponding Contribute guide.
Hooks
Server hooks (only plugins)
// {hookType}:{root}.{location}.{subLocation?}.{actionType}.{target}
export const serverFilterHookObject = {
// Filter params/result used to list videos for the REST API
// (used by the trending page, recently-added page, local page etc)
'filter:api.videos.list.params': true,
'filter:api.videos.list.result': true,
// Filter params/result used to list a video playlists videos
// for the REST API
'filter:api.video-playlist.videos.list.params': true,
'filter:api.video-playlist.videos.list.result': true,
// Filter params/result used to list account videos for the REST API
'filter:api.accounts.videos.list.params': true,
'filter:api.accounts.videos.list.result': true,
// Filter params/result used to list channel videos for the REST API
'filter:api.video-channels.videos.list.params': true,
'filter:api.video-channels.videos.list.result': true,
// Filter params/result used to list my user videos for the REST API
'filter:api.user.me.videos.list.params': true,
'filter:api.user.me.videos.list.result': true,
// Filter params/result used to list overview videos for the REST API
'filter:api.overviews.videos.list.params': true,
'filter:api.overviews.videos.list.result': true,
// Filter params/result used to list subscription videos for the REST API
'filter:api.user.me.subscription-videos.list.params': true,
'filter:api.user.me.subscription-videos.list.result': true,
// Filter params/results to search videos/channels in the DB or on the remote index
'filter:api.search.videos.local.list.params': true,
'filter:api.search.videos.local.list.result': true,
'filter:api.search.videos.index.list.params': true,
'filter:api.search.videos.index.list.result': true,
'filter:api.search.video-channels.local.list.params': true,
'filter:api.search.video-channels.local.list.result': true,
'filter:api.search.video-channels.index.list.params': true,
'filter:api.search.video-channels.index.list.result': true,
'filter:api.search.video-playlists.local.list.params': true,
'filter:api.search.video-playlists.local.list.result': true,
'filter:api.search.video-playlists.index.list.params': true,
'filter:api.search.video-playlists.index.list.result': true,
// Filter the result of the get function
// Used to get detailed video information (video watch page for example)
'filter:api.video.get.result': true,
// Filter params/results when listing video channels
'filter:api.video-channels.list.params': true,
'filter:api.video-channels.list.result': true,
// Filter the result when getting a video channel
'filter:api.video-channel.get.result': true,
// Filter the result of the accept upload/live, import via torrent/url functions
// If this function returns false then the upload is aborted with an error
'filter:api.video.upload.accept.result': true,
'filter:api.live-video.create.accept.result': true,
'filter:api.video.pre-import-url.accept.result': true,
'filter:api.video.pre-import-torrent.accept.result': true,
'filter:api.video.post-import-url.accept.result': true,
'filter:api.video.post-import-torrent.accept.result': true,
'filter:api.video.update-file.accept.result': true,
// PeerTube >= 6.1
'filter:api.video.user-import.accept.result': true,
// Filter the result of the accept comment (thread or reply) functions
// If the functions return false then the user cannot post its comment
'filter:api.video-thread.create.accept.result': true,
'filter:api.video-comment-reply.create.accept.result': true,
// Filter attributes when creating video object
'filter:api.video.upload.video-attribute.result': true,
'filter:api.video.import-url.video-attribute.result': true,
'filter:api.video.import-torrent.video-attribute.result': true,
'filter:api.video.live.video-attribute.result': true,
// PeerTube >= 6.1
'filter:api.video.user-import.video-attribute.result': true,
// Filter params/result used to list threads of a specific video
// (used by the video watch page)
'filter:api.video-threads.list.params': true,
'filter:api.video-threads.list.result': true,
// Filter params/result used to list replies of a specific thread
// (used by the video watch page when we click on the "View replies" button)
'filter:api.video-thread-comments.list.params': true,
'filter:api.video-thread-comments.list.result': true,
// Filter get stats result
'filter:api.server.stats.get.result': true,
// Filter result used to check if we need to auto blacklist a video
// (fired when a local or remote video is created or updated)
'filter:video.auto-blacklist.result': true,
// Filter result used to check if a user can register on the instance
'filter:api.user.signup.allowed.result': true,
// Filter result used to check if a user can send a registration request on the instance
// PeerTube >= 5.1
'filter:api.user.request-signup.allowed.result': true,
// Filter result used to check if video/torrent download is allowed
'filter:api.download.video.allowed.result': true,
'filter:api.download.generated-video.allowed.result': true,
'filter:api.download.torrent.allowed.result': true,
// Filter result to check if the embed is allowed for a particular request
'filter:html.embed.video.allowed.result': true,
'filter:html.embed.video-playlist.allowed.result': true,
// Peertube >= 5.2
'filter:html.client.json-ld.result': true,
'filter:job-queue.process.params': true,
'filter:job-queue.process.result': true,
'filter:transcoding.manual.resolutions-to-transcode.result': true,
'filter:transcoding.auto.resolutions-to-transcode.result': true,
'filter:activity-pub.remote-video-comment.create.accept.result': true,
'filter:activity-pub.activity.context.build.result': true,
// Filter the result of video JSON LD builder
// You may also need to use filter:activity-pub.activity.context.build.result to also update JSON LD context
'filter:activity-pub.video.json-ld.build.result': true,
// Filter result to allow custom XMLNS definitions in podcast RSS feeds
// Peertube >= 5.2
'filter:feed.podcast.rss.create-custom-xmlns.result': true,
// Filter result to allow custom tags in podcast RSS feeds
// Peertube >= 5.2
'filter:feed.podcast.channel.create-custom-tags.result': true,
// Peertube >= 5.2
'filter:feed.podcast.video.create-custom-tags.result': true,
// Peertube >= 6.1
'filter:api.user.me.get.result': true
}
export type ServerFilterHookName = keyof typeof serverFilterHookObject
export const serverActionHookObject = {
// Fired when the application has been loaded and is listening HTTP requests
'action:application.listening': true,
// Fired when a new notification is created
'action:notifier.notification.created': true,
// API actions hooks give access to the original express `req` and `res` parameters
// Fired when a local video is updated
'action:api.video.updated': true,
// Fired when a local video is deleted
'action:api.video.deleted': true,
// Fired when a local video is uploaded
'action:api.video.uploaded': true,
// Fired when a local video is viewed
'action:api.video.viewed': true,
// Fired when a local video file has been replaced by a new one
'action:api.video.file-updated': true,
// Fired when a video channel is created
'action:api.video-channel.created': true,
// Fired when a video channel is updated
'action:api.video-channel.updated': true,
// Fired when a video channel is deleted
'action:api.video-channel.deleted': true,
// Fired when a live video is created
'action:api.live-video.created': true,
// Fired when a live video starts or ends
// Peertube >= 5.2
'action:live.video.state.updated': true,
// Fired when a thread is created
'action:api.video-thread.created': true,
// Fired when a reply to a thread is created
'action:api.video-comment-reply.created': true,
// Fired when a comment (thread or reply) is deleted
'action:api.video-comment.deleted': true,
// Fired when a caption is created
'action:api.video-caption.created': true,
// Fired when a caption is deleted
'action:api.video-caption.deleted': true,
// Fired when a user is blocked (banned)
'action:api.user.blocked': true,
// Fired when a user is unblocked (unbanned)
'action:api.user.unblocked': true,
// Fired when a user registered on the instance
'action:api.user.registered': true,
// Fired when a user requested registration on the instance
// PeerTube >= 5.1
'action:api.user.requested-registration': true,
// Fired when an admin/moderator created a user
'action:api.user.created': true,
// Fired when a user is removed by an admin/moderator
'action:api.user.deleted': true,
// Fired when a user is updated by an admin/moderator
'action:api.user.updated': true,
// Fired when a user got a new oauth2 token
'action:api.user.oauth2-got-token': true,
// Fired when a video is added to a playlist
'action:api.video-playlist-element.created': true,
// Fired when a remote video has been created/updated
'action:activity-pub.remote-video.created': true,
'action:activity-pub.remote-video.updated': true
}
export type ServerActionHookName = keyof typeof serverActionHookObject
export const serverHookObject = Object.assign({}, serverFilterHookObject, serverActionHookObject)
export type ServerHookName = keyof typeof serverHookObject
export interface ServerHook {
runHook <T> (hookName: ServerHookName, result?: T, params?: any): Promise<T>
}
Client hooks
// Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target}
// Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target}
export const clientFilterHookObject = {
// Filter params/result of the function that fetch videos of the trending page
'filter:api.trending-videos.videos.list.params': true,
'filter:api.trending-videos.videos.list.result': true,
// Filter params/result of the function that fetch videos of the trending page
'filter:api.most-liked-videos.videos.list.params': true,
'filter:api.most-liked-videos.videos.list.result': true,
// Filter params/result of the function that fetch videos of the local page
'filter:api.local-videos.videos.list.params': true,
'filter:api.local-videos.videos.list.result': true,
// Filter params/result of the function that fetch videos of the recently-added page
'filter:api.recently-added-videos.videos.list.params': true,
'filter:api.recently-added-videos.videos.list.result': true,
// Filter params/result of the function that fetch videos of the user subscription page
'filter:api.user-subscriptions-videos.videos.list.params': true,
'filter:api.user-subscriptions-videos.videos.list.result': true,
// Filter params/result of the function that fetch the video of the video-watch page
'filter:api.video-watch.video.get.params': true,
'filter:api.video-watch.video.get.result': true,
// Filter params/result of the function that fetch video playlist elements of the video-watch page
'filter:api.video-watch.video-playlist-elements.get.params': true,
'filter:api.video-watch.video-playlist-elements.get.result': true,
// Filter params/result of the function that fetch the threads of the video-watch page
'filter:api.video-watch.video-threads.list.params': true,
'filter:api.video-watch.video-threads.list.result': true,
// Filter params/result of the function that fetch the replies of a thread in the video-watch page
'filter:api.video-watch.video-thread-replies.list.params': true,
'filter:api.video-watch.video-thread-replies.list.result': true,
// Filter params/result of the function that fetch videos according to the user search
'filter:api.search.videos.list.params': true,
'filter:api.search.videos.list.result': true,
// Filter params/result of the function that fetch video channels according to the user search
'filter:api.search.video-channels.list.params': true,
'filter:api.search.video-channels.list.result': true,
// Filter params/result of the function that fetch video playlists according to the user search
'filter:api.search.video-playlists.list.params': true,
'filter:api.search.video-playlists.list.result': true,
// Filter form
'filter:api.signup.registration.create.params': true,
// Filter params/result of the function that fetch video playlist elements of the my-library page
'filter:api.my-library.video-playlist-elements.list.params': true,
'filter:api.my-library.video-playlist-elements.list.result': true,
// Filter the options to create our player
'filter:internal.video-watch.player.build-options.params': true,
'filter:internal.video-watch.player.build-options.result': true,
// Filter the options to load a new video in our player
'filter:internal.video-watch.player.load-options.params': true,
'filter:internal.video-watch.player.load-options.result': true,
// Filter our SVG icons content
'filter:internal.common.svg-icons.get-content.params': true,
'filter:internal.common.svg-icons.get-content.result': true,
// Filter left menu links
'filter:left-menu.links.create.result': true,
// Filter upload page alert messages
'filter:upload.messages.create.result': true,
'filter:login.instance-about-plugin-panels.create.result': true,
'filter:signup.instance-about-plugin-panels.create.result': true,
'filter:share.video-embed-code.build.params': true,
'filter:share.video-embed-code.build.result': true,
'filter:share.video-playlist-embed-code.build.params': true,
'filter:share.video-playlist-embed-code.build.result': true,
'filter:share.video-embed-url.build.params': true,
'filter:share.video-embed-url.build.result': true,
'filter:share.video-playlist-embed-url.build.params': true,
'filter:share.video-playlist-embed-url.build.result': true,
'filter:share.video-url.build.params': true,
'filter:share.video-url.build.result': true,
'filter:share.video-playlist-url.build.params': true,
'filter:share.video-playlist-url.build.result': true,
'filter:video-watch.video-plugin-metadata.result': true,
// Filter videojs options built for PeerTube player
'filter:internal.player.videojs.options.result': true,
// Filter p2p media loader options built for PeerTube player
'filter:internal.player.p2p-media-loader.options.result': true
}
export type ClientFilterHookName = keyof typeof clientFilterHookObject
export const clientActionHookObject = {
// Fired when the application is being initialized
'action:application.init': true,
// Fired when the video watch page is being initialized
'action:video-watch.init': true,
// Fired when the video watch page loaded the video
'action:video-watch.video.loaded': true,
// Fired when the player finished loading
'action:video-watch.player.loaded': true,
// Fired when the video watch page comments(threads) are loaded and load more comments on scroll
'action:video-watch.video-threads.loaded': true,
// Fired when a user click on 'View x replies' and they're loaded
'action:video-watch.video-thread-replies.loaded': true,
// Fired when the video channel creation page is being initialized
'action:video-channel-create.init': true,
// Fired when the video channel update page is being initialized
'action:video-channel-update.init': true,
'action:video-channel-update.video-channel.loaded': true,
// Fired when the page that list video channel videos is being initialized
'action:video-channel-videos.init': true,
'action:video-channel-videos.video-channel.loaded': true,
'action:video-channel-videos.videos.loaded': true,
// Fired when the page that list video channel playlists is being initialized
'action:video-channel-playlists.init': true,
'action:video-channel-playlists.video-channel.loaded': true,
'action:video-channel-playlists.playlists.loaded': true,
// Fired when the video edit page (upload, URL/torrent import, update) is being initialized
// Contains a `type` and `updateForm` object attributes
'action:video-edit.init': true,
// Fired when values of the video edit form changed
'action:video-edit.form.updated': true,
// Fired when the login page is being initialized
'action:login.init': true,
// Fired when the search page is being initialized
'action:search.init': true,
// Fired every time Angular URL changes
'action:router.navigation-end': true,
// Fired when the registration page is being initialized
'action:signup.register.init': true,
// PeerTube >= 3.2
// Fired when the admin plugin settings page is being initialized
'action:admin-plugin-settings.init': true,
// Fired when the video upload page is being initialized
'action:video-upload.init': true,
// Fired when the video import by URL page is being initialized
'action:video-url-import.init': true,
// Fired when the video import by torrent/magnet URI page is being initialized
'action:video-torrent-import.init': true,
// Fired when the "Go Live" page is being initialized
'action:go-live.init': true,
// Fired when the user explicitly logged in/logged out
'action:auth-user.logged-in': true,
'action:auth-user.logged-out': true,
// Fired when the application loaded user information (using tokens from the local storage or after a successful login)
'action:auth-user.information-loaded': true,
// Fired when the modal to download a video/caption is shown
'action:modal.video-download.shown': true,
// Fired when the modal to share a video/playlist is shown
'action:modal.share.shown': true,
// ####### Embed hooks #######
// /!\ In embed scope, peertube helpers are not available
// ###########################
// Fired when the embed loaded the player
'action:embed.player.loaded': true
}
export type ClientActionHookName = keyof typeof clientActionHookObject
export const clientHookObject = Object.assign({}, clientFilterHookObject, clientActionHookObject)
export type ClientHookName = keyof typeof clientHookObject
export interface ClientHook {
runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T>
}
export type PluginClientScope =
'common' |
'video-watch' |
'search' |
'signup' |
'login' |
'embed' |
'video-edit' |
'admin-plugin' |
'my-library' |
'video-channel' |
'my-account'
Server register/unregister (only plugins)
Your library file should export a register
and unregister
functions:
import { RegisterServerOptions } from './register-server-option.model.js'
export interface PluginLibrary {
register: (options: RegisterServerOptions) => Promise<any>
unregister: () => Promise<any>
}
PeerTube provides different helpers to the register
function:
import { Response, Router } from 'express'
import { Server } from 'http'
import { Logger } from 'winston'
import {
PluginPlaylistPrivacyManager,
PluginSettingsManager,
PluginStorageManager,
PluginTranscodingManager,
PluginVideoCategoryManager,
PluginVideoLanguageManager,
PluginVideoLicenceManager,
PluginVideoPrivacyManager,
RegisterServerHookOptions,
RegisterServerSettingOptions,
ServerConfig,
ThumbnailType_Type,
VideoBlacklistCreate
} from '@peertube/peertube-models'
import { ActorModel } from '@server/models/actor/actor.js'
import { MUserDefault, MVideo, MVideoThumbnail, MVideoWithAllFiles, UserNotificationModelForApi } from '../models/index.js'
import {
RegisterServerAuthExternalOptions,
RegisterServerAuthExternalResult,
RegisterServerAuthPassOptions
} from './register-server-auth.model.js'
import { RegisterServerWebSocketRouteOptions } from './register-server-websocket-route.model.js'
export type PeerTubeHelpers = {
logger: Logger
database: {
query: Function
}
videos: {
loadByUrl: (url: string) => Promise<MVideoThumbnail>
loadByIdOrUUIDWithFiles: (id: number | string) => Promise<MVideoWithAllFiles>
loadByIdOrUUID: (id: number | string) => Promise<MVideoThumbnail>
removeVideo: (videoId: number) => Promise<void>
ffprobe: (path: string) => Promise<any>
getFiles: (id: number | string) => Promise<{
webVideo: {
videoFiles: {
path: string // Could be null if using remote storage
url: string
resolution: number
size: number
fps: number
}[]
}
hls: {
videoFiles: {
path: string // Could be null if using remote storage
url: string
resolution: number
size: number
fps: number
}[]
}
thumbnails: {
type: ThumbnailType_Type
path: string
}[]
}>
}
config: {
getWebserverUrl: () => string
// PeerTube >= 5.1
getServerListeningConfig: () => { hostname: string, port: number }
getServerConfig: () => Promise<ServerConfig>
}
moderation: {
blockServer: (options: { byAccountId: number, hostToBlock: string }) => Promise<void>
unblockServer: (options: { byAccountId: number, hostToUnblock: string }) => Promise<void>
blockAccount: (options: { byAccountId: number, handleToBlock: string }) => Promise<void>
unblockAccount: (options: { byAccountId: number, handleToUnblock: string }) => Promise<void>
blacklistVideo: (options: { videoIdOrUUID: number | string, createOptions: VideoBlacklistCreate }) => Promise<void>
unblacklistVideo: (options: { videoIdOrUUID: number | string }) => Promise<void>
}
server: {
// PeerTube >= 5.0
getHTTPServer: () => Server
getServerActor: () => Promise<ActorModel>
}
socket: {
sendNotification: (userId: number, notification: UserNotificationModelForApi) => void
sendVideoLiveNewState: (video: MVideo) => void
}
plugin: {
// PeerTube >= 3.2
getBaseStaticRoute: () => string
// PeerTube >= 3.2
getBaseRouterRoute: () => string
// PeerTube >= 5.0
getBaseWebSocketRoute: () => string
// PeerTube >= 3.2
getDataDirectoryPath: () => string
}
user: {
// PeerTube >= 3.2
getAuthUser: (response: Response) => Promise<MUserDefault>
// PeerTube >= 4.3
loadById: (id: number) => Promise<MUserDefault>
}
}
export type RegisterServerOptions = {
registerHook: (options: RegisterServerHookOptions) => void
registerSetting: (options: RegisterServerSettingOptions) => void
settingsManager: PluginSettingsManager
storageManager: PluginStorageManager
videoCategoryManager: PluginVideoCategoryManager
videoLanguageManager: PluginVideoLanguageManager
videoLicenceManager: PluginVideoLicenceManager
videoPrivacyManager: PluginVideoPrivacyManager
playlistPrivacyManager: PluginPlaylistPrivacyManager
transcodingManager: PluginTranscodingManager
registerIdAndPassAuth: (options: RegisterServerAuthPassOptions) => void
registerExternalAuth: (options: RegisterServerAuthExternalOptions) => RegisterServerAuthExternalResult
unregisterIdAndPassAuth: (authName: string) => void
unregisterExternalAuth: (authName: string) => void
// Get plugin router to create custom routes
// Base routes of this router are
// * /plugins/:pluginName/:pluginVersion/router/...
// * /plugins/:pluginName/router/...
getRouter(): Router
// PeerTube >= 5.0
// Register WebSocket route
// Base routes of the WebSocket router are
// * /plugins/:pluginName/:pluginVersion/ws/...
// * /plugins/:pluginName/ws/...
registerWebSocketRoute: (options: RegisterServerWebSocketRouteOptions) => void
peertubeHelpers: PeerTubeHelpers
}
Register hook options
To register hook listeners:
import { ServerHookName } from './server-hook.model.js'
export interface RegisterServerHookOptions {
target: ServerHookName
handler: Function
priority?: number
}
Register settings options
To register settings:
import { RegisterClientFormFieldOptions } from '../../client/index.js'
export type RegisterServerSettingOptions = RegisterClientFormFieldOptions & {
// If the setting is not private, anyone can view its value (client code included)
// If the setting is private, only server-side hooks can access it
// Mainly used by the PeerTube client to get admin config
private: boolean
}
export interface RegisteredServerSettings {
registeredSettings: RegisterServerSettingOptions[]
}
export type RegisterClientFormFieldOptions = {
name?: string
label?: string
type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced' | 'select' | 'html'
// For select type
options?: { value: string, label: string }[]
// For html type
html?: string
descriptionHTML?: string
// Default setting value
default?: string | boolean
// Not supported by plugin setting registration, use registerSettingsScript instead
hidden?: (options: any) => boolean
// Return undefined | null if there is no error or return a string with the detailed error
// Not supported by plugin setting registration
error?: (options: any) => Promise<{ error: boolean, text?: string }>
}
export interface RegisterClientVideoFieldOptions {
type: 'update' | 'upload' | 'import-url' | 'import-torrent' | 'go-live'
// Default to 'plugin-settings'
tab?: 'main' | 'plugin-settings'
}
export type SettingValue = string | boolean
export interface SettingEntries {
[settingName: string]: SettingValue
}
export type SettingsChangeCallback = (settings: SettingEntries) => Promise<any>
export interface PluginSettingsManager {
getSetting: (name: string) => Promise<SettingValue>
getSettings: (names: string[]) => Promise<SettingEntries>
setSetting: (name: string, value: SettingValue) => Promise<any>
onSettingsChange: (cb: SettingsChangeCallback) => void
}
Storage manager API
To save/load JSON (please don't put too much data in there because we store it in the PeerTube database):
export interface PluginStorageManager {
getData: (key: string) => Promise<string>
storeData: (key: string, data: any) => Promise<any>
}
Register auth methods API
To register id and pass auth methods (LDAP etc), or external auth (OpenID, SAML2 etc) methods:
import express from 'express'
import { UserAdminFlagType, UserRoleType } from '@peertube/peertube-models'
import { MOAuthToken, MUser } from '../models/index.js'
export type RegisterServerAuthOptions = RegisterServerAuthPassOptions | RegisterServerAuthExternalOptions
export type AuthenticatedResultUpdaterFieldName = 'displayName' | 'role' | 'adminFlags' | 'videoQuota' | 'videoQuotaDaily'
export interface RegisterServerAuthenticatedResult {
// Update the user profile if it already exists
// Default behaviour is no update
// Introduced in PeerTube >= 5.1
userUpdater?: <T> (options: {
fieldName: AuthenticatedResultUpdaterFieldName
currentValue: T
newValue: T
}) => T
username: string
email: string
role?: UserRoleType
displayName?: string
// PeerTube >= 5.1
adminFlags?: UserAdminFlagType
// PeerTube >= 5.1
videoQuota?: number
// PeerTube >= 5.1
videoQuotaDaily?: number
}
export interface RegisterServerExternalAuthenticatedResult extends RegisterServerAuthenticatedResult {
req: express.Request
res: express.Response
}
interface RegisterServerAuthBase {
// Authentication name (a plugin can register multiple auth strategies)
authName: string
// Called by PeerTube when a user from your plugin logged out
// Returns a redirectUrl sent to the client or nothing
onLogout?(user: MUser, req: express.Request): Promise<string>
// Your plugin can hook PeerTube access/refresh token validity
// So you can control for your plugin the user session lifetime
hookTokenValidity?(options: { token: MOAuthToken, type: 'access' | 'refresh' }): Promise<{ valid: boolean }>
}
export interface RegisterServerAuthPassOptions extends RegisterServerAuthBase {
// Weight of this authentication so PeerTube tries the auth methods in DESC weight order
getWeight(): number
// Used by PeerTube to login a user
// Returns null if the login failed, or { username, email } on success
login(body: {
id: string
password: string
}): Promise<RegisterServerAuthenticatedResult | null>
}
export interface RegisterServerAuthExternalOptions extends RegisterServerAuthBase {
// Will be displayed in a block next to the login form
authDisplayName: () => string
onAuthRequest: (req: express.Request, res: express.Response) => void
}
export interface RegisterServerAuthExternalResult {
userAuthenticated (options: RegisterServerExternalAuthenticatedResult): void
}
Video categories manager API
import { ConstantManager } from '../plugin-constant-manager.model.js'
export interface PluginVideoCategoryManager extends ConstantManager<number> {
/**
* @deprecated use `addConstant` instead
*/
addCategory: (categoryKey: number, categoryLabel: string) => boolean
/**
* @deprecated use `deleteConstant` instead
*/
deleteCategory: (categoryKey: number) => boolean
}
Video languages manager API
import { ConstantManager } from '../plugin-constant-manager.model.js'
export interface PluginVideoLanguageManager extends ConstantManager<string> {
/**
* @deprecated use `addConstant` instead
*/
addLanguage: (languageKey: string, languageLabel: string) => boolean
/**
* @deprecated use `deleteConstant` instead
*/
deleteLanguage: (languageKey: string) => boolean
}
Video licences manager API
import { ConstantManager } from '../plugin-constant-manager.model.js'
export interface PluginVideoLicenceManager extends ConstantManager<number> {
/**
* @deprecated use `addConstant` instead
*/
addLicence: (licenceKey: number, licenceLabel: string) => boolean
/**
* @deprecated use `deleteConstant` instead
*/
deleteLicence: (licenceKey: number) => boolean
}
Video privacy manager API
import { VideoPrivacyType } from '../../../videos/video-privacy.enum.js'
import { ConstantManager } from '../plugin-constant-manager.model.js'
export interface PluginVideoPrivacyManager extends ConstantManager<VideoPrivacyType> {
/**
* PUBLIC = 1,
* UNLISTED = 2,
* PRIVATE = 3
* INTERNAL = 4
* @deprecated use `deleteConstant` instead
*/
deletePrivacy: (privacyKey: VideoPrivacyType) => boolean
}
Video playlist privacy manager API
import { VideoPlaylistPrivacyType } from '../../../videos/playlist/video-playlist-privacy.model.js'
import { ConstantManager } from '../plugin-constant-manager.model.js'
export interface PluginPlaylistPrivacyManager extends ConstantManager<VideoPlaylistPrivacyType> {
/**
* PUBLIC = 1,
* UNLISTED = 2,
* PRIVATE = 3
* @deprecated use `deleteConstant` instead
*/
deletePlaylistPrivacy: (privacyKey: VideoPlaylistPrivacyType) => boolean
}
Video transcoding manager API
To add profile and encoders priority to ffmpeg transcoding jobs (profile needs to be selected by the admin in the PeerTube configuration):
import { EncoderOptionsBuilder } from '../../../videos/transcoding/index.js'
export interface PluginTranscodingManager {
addLiveProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder): boolean
addVODProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder): boolean
addLiveEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number): void
addVODEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number): void
removeAllProfilesAndEncoderPriorities(): void
}
// Types used by plugins and ffmpeg-utils
import { FfprobeData } from 'fluent-ffmpeg'
export type EncoderOptionsBuilderParams = {
input: string
resolution: number
// If PeerTube applies a filter, transcoding profile must not copy input stream
canCopyAudio: boolean
canCopyVideo: boolean
fps: number
// Could be undefined if we could not get input bitrate (some RTMP streams for example)
inputBitrate: number
inputRatio: number
inputProbe: FfprobeData
// For lives
streamNum?: number
}
export type EncoderOptionsBuilder = (params: EncoderOptionsBuilderParams) => Promise<EncoderOptions> | EncoderOptions
export interface EncoderOptions {
copy?: boolean // Copy stream? Default to false
scaleFilter?: {
name: string
}
inputOptions?: string[]
outputOptions?: string[]
}
// All our encoders
export interface EncoderProfile <T> {
[ profile: string ]: T
default: T
}
export type AvailableEncoders = {
available: {
live: {
[ encoder: string ]: EncoderProfile<EncoderOptionsBuilder>
}
vod: {
[ encoder: string ]: EncoderProfile<EncoderOptionsBuilder>
}
}
encodersToTry: {
vod: {
video: string[]
audio: string[]
}
live: {
video: string[]
audio: string[]
}
}
}
Client register
Your client script should export a register
function:
import { RegisterClientOptions } from './register-client-option.model'
export interface ClientScript {
register: (options: RegisterClientOptions) => Promise<any>
}
PeerTube provides different helpers to the register
function:
import {
MyUser,
RegisterClientFormFieldOptions,
RegisterClientHookOptions,
RegisterClientRouteOptions,
RegisterClientSettingsScriptOptions,
RegisterClientVideoFieldOptions,
ServerConfig, SettingEntries
} from '@peertube/peertube-models'
export type RegisterClientOptions = {
registerHook: (options: RegisterClientHookOptions) => void
registerVideoField: (commonOptions: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) => void
registerSettingsScript: (options: RegisterClientSettingsScriptOptions) => void
registerClientRoute: (options: RegisterClientRouteOptions) => void
peertubeHelpers: RegisterClientHelpers
}
export type RegisterClientHelpers = {
getBaseStaticRoute: () => string
getBaseRouterRoute: () => string
// PeerTube >= 5.0
getBaseWebSocketRoute: () => string
getBasePluginClientPath: () => string
isLoggedIn: () => boolean
getAuthHeader: () => { 'Authorization': string } | undefined
getSettings: () => Promise<SettingEntries>
getUser: () => MyUser
getServerConfig: () => Promise<ServerConfig>
notifier: {
info: (text: string, title?: string, timeout?: number) => void
error: (text: string, title?: string, timeout?: number) => void
success: (text: string, title?: string, timeout?: number) => void
}
showModal: (input: {
title: string
content: string
close?: boolean
cancel?: { value: string, action?: () => void }
confirm?: { value: string, action?: () => void }
}) => void
markdownRenderer: {
textMarkdownToHTML: (textMarkdown: string) => Promise<string>
enhancedMarkdownToHTML: (enhancedMarkdown: string) => Promise<string>
}
translate: (toTranslate: string) => Promise<string>
}
Register hook options
To register hook listeners:
import { ClientHookName } from './client-hook.model.js'
export interface RegisterClientHookOptions {
target: ClientHookName
handler: Function
priority?: number
}
Register video form field options
import { RegisterServerSettingOptions } from '../server/index.js'
export interface RegisterClientSettingsScriptOptions {
isSettingHidden (options: {
setting: RegisterServerSettingOptions
formValues: { [name: string]: any }
}): boolean
}
Client plugin selectors
Selector ids are prefixed by plugin-selector-
. For example: plugin-selector-login-form
export type PluginSelectorId =
'login-form' |
'menu-user-dropdown-language-item' |
'about-instance-features' |
'about-instance-statistics' |
'about-instance-moderation' |
'about-menu-instance' |
'about-menu-peertube' |
'about-menu-network' |
'about-instance-other-information'
Client placeholder elements
Element ids are prefixed by plugin-placeholder-
. For example: plugin-placeholder-player-next
export type PluginElementPlaceholder =
'player-next' |
'share-modal-playlist-settings' |
'share-modal-video-settings'