1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 01:39:37 +02:00

Support max FPS configuration

This commit is contained in:
Chocobozzz 2024-08-12 16:17:11 +02:00
parent 0bd2474fed
commit bbaf96d60d
No known key found for this signature in database
GPG key ID: 583A612D890159BE
37 changed files with 736 additions and 623 deletions

View file

@ -31,8 +31,7 @@ import {
VideoRateType,
VideoResolution,
VideoState,
VideoStateType,
VideoTranscodingFPS
VideoStateType
} from '@peertube/peertube-models'
import { isTestInstance, isTestOrDevInstance, root } from '@peertube/peertube-node-utils'
import { RepeatOptions } from 'bullmq'
@ -41,20 +40,20 @@ import { readJsonSync } from 'fs-extra/esm'
import invert from 'lodash-es/invert.js'
import { join } from 'path'
// Do not use barrels, remain constants as independent as possible
import { cpus } from 'os'
import { parseDurationToMs, sanitizeHost, sanitizeUrl } from '../helpers/core-utils.js'
import { CONFIG, registerConfigChangedHandler } from './config.js'
import { cpus } from 'os'
// ---------------------------------------------------------------------------
const LAST_MIGRATION_VERSION = 865
export const LAST_MIGRATION_VERSION = 865
// ---------------------------------------------------------------------------
const API_VERSION = 'v1'
const PEERTUBE_VERSION: string = readJsonSync(join(root(), 'package.json')).version
export const API_VERSION = 'v1'
export const PEERTUBE_VERSION: string = readJsonSync(join(root(), 'package.json')).version
const PAGINATION = {
export const PAGINATION = {
GLOBAL: {
COUNT: {
DEFAULT: 15,
@ -68,7 +67,7 @@ const PAGINATION = {
}
}
const WEBSERVER = {
export const WEBSERVER = {
URL: '',
HOST: '',
SCHEME: '',
@ -84,7 +83,7 @@ const WEBSERVER = {
}
// Sortable columns per schema
const SORTABLE_COLUMNS = {
export const SORTABLE_COLUMNS = {
ADMIN_USERS: [ 'id', 'username', 'videoQuotaUsed', 'createdAt', 'lastLoginDate', 'role' ],
USER_SUBSCRIPTIONS: [ 'id', 'createdAt' ],
ACCOUNTS: [ 'createdAt' ],
@ -149,7 +148,7 @@ const SORTABLE_COLUMNS = {
VIDEO_REDUNDANCIES: [ 'name' ]
}
const ROUTE_CACHE_LIFETIME = {
export const ROUTE_CACHE_LIFETIME = {
FEEDS: '15 minutes',
ROBOTS: '2 hours',
SITEMAP: '1 day',
@ -166,27 +165,27 @@ const ROUTE_CACHE_LIFETIME = {
// ---------------------------------------------------------------------------
// Number of points we add/remove after a successful/bad request
const ACTOR_FOLLOW_SCORE = {
export const ACTOR_FOLLOW_SCORE = {
PENALTY: -10,
BONUS: 10,
BASE: 1000,
MAX: 10000
}
const FOLLOW_STATES: { [ id: string ]: FollowState } = {
export const FOLLOW_STATES: { [ id: string ]: FollowState } = {
PENDING: 'pending',
ACCEPTED: 'accepted',
REJECTED: 'rejected'
}
const REMOTE_SCHEME = {
export const REMOTE_SCHEME = {
HTTP: 'https',
WS: 'wss'
}
// ---------------------------------------------------------------------------
const JOB_ATTEMPTS: { [id in JobType]: number } = {
export const JOB_ATTEMPTS: { [id in JobType]: number } = {
'activitypub-http-broadcast': 1,
'activitypub-http-broadcast-parallel': 1,
'activitypub-http-unicast': 1,
@ -217,7 +216,7 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = {
'video-transcription': 2
}
// Excluded keys are jobs that can be configured by admins
const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-import'>]: number } = {
export const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-import'>]: number } = {
'activitypub-http-broadcast': 1,
'activitypub-http-broadcast-parallel': 30,
'activitypub-http-unicast': 30,
@ -245,7 +244,7 @@ const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-im
'import-user-archive': 1,
'video-transcription': 1
}
const JOB_TTL: { [id in JobType]: number } = {
export const JOB_TTL: { [id in JobType]: number } = {
'activitypub-http-broadcast': 60000 * 10, // 10 minutes
'activitypub-http-broadcast-parallel': 60000 * 10, // 10 minutes
'activitypub-http-unicast': 60000 * 10, // 10 minutes
@ -275,7 +274,7 @@ const JOB_TTL: { [id in JobType]: number } = {
'import-user-archive': 60000 * 60 * 24, // 24 hours
'video-transcription': 1000 * 3600 * 6 // 6 hours
}
const REPEAT_JOBS: { [ id in JobType ]?: RepeatOptions } = {
export const REPEAT_JOBS: { [ id in JobType ]?: RepeatOptions } = {
'videos-views-stats': {
pattern: randomInt(1, 20) + ' * * * *' // Between 1-20 minutes past the hour
},
@ -283,13 +282,13 @@ const REPEAT_JOBS: { [ id in JobType ]?: RepeatOptions } = {
pattern: '30 5 * * ' + randomInt(0, 7) // 1 time per week (random day) at 5:30 AM
}
}
const JOB_PRIORITY = {
export const JOB_PRIORITY = {
TRANSCODING: 100,
VIDEO_STUDIO: 150,
TRANSCRIPTION: 200
}
const JOB_REMOVAL_OPTIONS = {
export const JOB_REMOVAL_OPTIONS = {
COUNT: 10000, // Max jobs to store
SUCCESS: { // Success jobs
@ -306,32 +305,32 @@ const JOB_REMOVAL_OPTIONS = {
}
}
const VIDEO_IMPORT_TIMEOUT = Math.floor(JOB_TTL['video-import'] * 0.9)
export const VIDEO_IMPORT_TIMEOUT = Math.floor(JOB_TTL['video-import'] * 0.9)
const RUNNER_JOBS = {
export const RUNNER_JOBS = {
MAX_FAILURES: 5,
LAST_CONTACT_UPDATE_INTERVAL: 30000
}
// ---------------------------------------------------------------------------
const BROADCAST_CONCURRENCY = 30 // How many requests in parallel we do in activitypub-http-broadcast job
const CRAWL_REQUEST_CONCURRENCY = 1 // How many requests in parallel to fetch remote data (likes, shares...)
export const BROADCAST_CONCURRENCY = 30 // How many requests in parallel we do in activitypub-http-broadcast job
export const CRAWL_REQUEST_CONCURRENCY = 1 // How many requests in parallel to fetch remote data (likes, shares...)
const AP_CLEANER = {
export const AP_CLEANER = {
CONCURRENCY: 10, // How many requests in parallel we do in activitypub-cleaner job
UNAVAILABLE_TRESHOLD: 3, // How many attempts we do before removing an unavailable remote resource
PERIOD: parseDurationToMs('1 week') // /!\ Has to be sync with REPEAT_JOBS
}
const REQUEST_TIMEOUTS = {
export const REQUEST_TIMEOUTS = {
DEFAULT: 7000, // 7 seconds
FILE: 30000, // 30 seconds
VIDEO_FILE: 60000, // 1 minute
REDUNDANCY: JOB_TTL['video-redundancy']
}
const SCHEDULER_INTERVALS_MS = {
export const SCHEDULER_INTERVALS_MS = {
RUNNER_JOB_WATCH_DOG: Math.min(CONFIG.REMOTE_RUNNERS.STALLED_JOBS.VOD, CONFIG.REMOTE_RUNNERS.STALLED_JOBS.LIVE),
ACTOR_FOLLOW_SCORES: 60000 * 60, // 1 hour
REMOVE_OLD_JOBS: 60000 * 60, // 1 hour
@ -352,7 +351,7 @@ const SCHEDULER_INTERVALS_MS = {
// ---------------------------------------------------------------------------
const CONSTRAINTS_FIELDS = {
export const CONSTRAINTS_FIELDS = {
USERS: {
NAME: { min: 1, max: 120 }, // Length
DESCRIPTION: { min: 3, max: 1000 }, // Length
@ -515,40 +514,30 @@ const CONSTRAINTS_FIELDS = {
}
}
const VIEW_LIFETIME = {
export const VIEW_LIFETIME = {
VIEW: CONFIG.VIEWS.VIDEOS.VIEW_EXPIRATION,
VIEWER_COUNTER: 60000 * 2, // 2 minutes
VIEWER_STATS: 60000 * 60 // 1 hour
}
let VIEWER_SYNC_REDIS = 30000 // Sync viewer into redis
export let VIEWER_SYNC_REDIS = 30000 // Sync viewer into redis
const MAX_LOCAL_VIEWER_WATCH_SECTIONS = 100
export const MAX_LOCAL_VIEWER_WATCH_SECTIONS = 100
let CONTACT_FORM_LIFETIME = 60000 * 60 // 1 hour
export let CONTACT_FORM_LIFETIME = 60000 * 60 // 1 hour
const VIDEO_TRANSCODING_FPS: VideoTranscodingFPS = {
HARD_MIN: 0.1,
SOFT_MIN: 1,
STANDARD: [ 24, 25, 30 ],
HD_STANDARD: [ 50, 60 ],
AUDIO_MERGE: 25,
AVERAGE: 30,
SOFT_MAX: 60,
KEEP_ORIGIN_FPS_RESOLUTION_MIN: 720 // We keep the original FPS on high resolutions (720 minimum)
}
export const DEFAULT_AUDIO_RESOLUTION = VideoResolution.H_480P
export const DEFAULT_AUDIO_MERGE_RESOLUTION = 25
const DEFAULT_AUDIO_RESOLUTION = VideoResolution.H_480P
const VIDEO_RATE_TYPES: { [ id: string ]: VideoRateType } = {
export const VIDEO_RATE_TYPES: { [ id: string ]: VideoRateType } = {
LIKE: 'like',
DISLIKE: 'dislike'
}
const USER_IMPORT = {
export const USER_IMPORT = {
MAX_PLAYLIST_ELEMENTS: 1000
}
const FFMPEG_NICE = {
export const FFMPEG_NICE = {
// parent process defaults to niceness = 0
// reminder: lower = higher priority, max value is 19, lowest is -20
LIVE: 5, // prioritize over VOD and THUMBNAIL
@ -556,7 +545,7 @@ const FFMPEG_NICE = {
VOD: 15
}
const VIDEO_CATEGORIES = {
export const VIDEO_CATEGORIES = {
1: 'Music',
2: 'Films',
3: 'Vehicles',
@ -578,7 +567,7 @@ const VIDEO_CATEGORIES = {
}
// See https://creativecommons.org/licenses/?lang=en
const VIDEO_LICENCES = {
export const VIDEO_LICENCES = {
1: 'Attribution',
2: 'Attribution - Share Alike',
3: 'Attribution - No Derivatives',
@ -588,9 +577,9 @@ const VIDEO_LICENCES = {
7: 'Public Domain Dedication'
}
const VIDEO_LANGUAGES: { [id: string]: string } = {}
export const VIDEO_LANGUAGES: { [id: string]: string } = {}
const VIDEO_PRIVACIES: { [ id in VideoPrivacyType ]: string } = {
export const VIDEO_PRIVACIES: { [ id in VideoPrivacyType ]: string } = {
[VideoPrivacy.PUBLIC]: 'Public',
[VideoPrivacy.UNLISTED]: 'Unlisted',
[VideoPrivacy.PRIVATE]: 'Private',
@ -598,7 +587,7 @@ const VIDEO_PRIVACIES: { [ id in VideoPrivacyType ]: string } = {
[VideoPrivacy.PASSWORD_PROTECTED]: 'Password protected'
}
const VIDEO_STATES: { [ id in VideoStateType ]: string } = {
export const VIDEO_STATES: { [ id in VideoStateType ]: string } = {
[VideoState.PUBLISHED]: 'Published',
[VideoState.TO_TRANSCODE]: 'To transcode',
[VideoState.TO_IMPORT]: 'To import',
@ -612,7 +601,7 @@ const VIDEO_STATES: { [ id in VideoStateType ]: string } = {
[VideoState.TO_MOVE_TO_FILE_SYSTEM_FAILED]: 'Move to file system failed'
}
const VIDEO_IMPORT_STATES: { [ id in VideoImportStateType ]: string } = {
export const VIDEO_IMPORT_STATES: { [ id in VideoImportStateType ]: string } = {
[VideoImportState.FAILED]: 'Failed',
[VideoImportState.PENDING]: 'Pending',
[VideoImportState.SUCCESS]: 'Success',
@ -621,37 +610,37 @@ const VIDEO_IMPORT_STATES: { [ id in VideoImportStateType ]: string } = {
[VideoImportState.PROCESSING]: 'Processing'
}
const VIDEO_CHANNEL_SYNC_STATE: { [ id in VideoChannelSyncStateType ]: string } = {
export const VIDEO_CHANNEL_SYNC_STATE: { [ id in VideoChannelSyncStateType ]: string } = {
[VideoChannelSyncState.FAILED]: 'Failed',
[VideoChannelSyncState.SYNCED]: 'Synchronized',
[VideoChannelSyncState.PROCESSING]: 'Processing',
[VideoChannelSyncState.WAITING_FIRST_RUN]: 'Waiting first run'
}
const ABUSE_STATES: { [ id in AbuseStateType ]: string } = {
export const ABUSE_STATES: { [ id in AbuseStateType ]: string } = {
[AbuseState.PENDING]: 'Pending',
[AbuseState.REJECTED]: 'Rejected',
[AbuseState.ACCEPTED]: 'Accepted'
}
const USER_REGISTRATION_STATES: { [ id in UserRegistrationStateType ]: string } = {
export const USER_REGISTRATION_STATES: { [ id in UserRegistrationStateType ]: string } = {
[UserRegistrationState.PENDING]: 'Pending',
[UserRegistrationState.REJECTED]: 'Rejected',
[UserRegistrationState.ACCEPTED]: 'Accepted'
}
const VIDEO_PLAYLIST_PRIVACIES: { [ id in VideoPlaylistPrivacyType ]: string } = {
export const VIDEO_PLAYLIST_PRIVACIES: { [ id in VideoPlaylistPrivacyType ]: string } = {
[VideoPlaylistPrivacy.PUBLIC]: 'Public',
[VideoPlaylistPrivacy.UNLISTED]: 'Unlisted',
[VideoPlaylistPrivacy.PRIVATE]: 'Private'
}
const VIDEO_PLAYLIST_TYPES: { [ id in VideoPlaylistType_Type ]: string } = {
export const VIDEO_PLAYLIST_TYPES: { [ id in VideoPlaylistType_Type ]: string } = {
[VideoPlaylistType.REGULAR]: 'Regular',
[VideoPlaylistType.WATCH_LATER]: 'Watch later'
}
const RUNNER_JOB_STATES: { [ id in RunnerJobStateType ]: string } = {
export const RUNNER_JOB_STATES: { [ id in RunnerJobStateType ]: string } = {
[RunnerJobState.PROCESSING]: 'Processing',
[RunnerJobState.COMPLETED]: 'Completed',
[RunnerJobState.COMPLETING]: 'Completing',
@ -663,27 +652,27 @@ const RUNNER_JOB_STATES: { [ id in RunnerJobStateType ]: string } = {
[RunnerJobState.PARENT_CANCELLED]: 'Parent job cancelled'
}
const USER_EXPORT_STATES: { [ id in UserExportStateType ]: string } = {
export const USER_EXPORT_STATES: { [ id in UserExportStateType ]: string } = {
[UserExportState.PENDING]: 'Pending',
[UserExportState.PROCESSING]: 'Processing',
[UserExportState.COMPLETED]: 'Completed',
[UserExportState.ERRORED]: 'Failed'
}
const USER_IMPORT_STATES: { [ id in UserImportStateType ]: string } = {
export const USER_IMPORT_STATES: { [ id in UserImportStateType ]: string } = {
[UserImportState.PENDING]: 'Pending',
[UserImportState.PROCESSING]: 'Processing',
[UserImportState.COMPLETED]: 'Completed',
[UserImportState.ERRORED]: 'Failed'
}
const VIDEO_COMMENTS_POLICY: { [ id in VideoCommentPolicyType ]: string } = {
export const VIDEO_COMMENTS_POLICY: { [ id in VideoCommentPolicyType ]: string } = {
[VideoCommentPolicy.DISABLED]: 'Disabled',
[VideoCommentPolicy.ENABLED]: 'Enabled',
[VideoCommentPolicy.REQUIRES_APPROVAL]: 'Requires approval'
}
const MIMETYPES = {
export const MIMETYPES = {
AUDIO: {
MIMETYPE_EXT: {
'audio/mpeg': '.mp3',
@ -769,7 +758,7 @@ MIMETYPES.AUDIO.EXT_MIMETYPE = invert(MIMETYPES.AUDIO.MIMETYPE_EXT)
MIMETYPES.IMAGE.EXT_MIMETYPE = invert(MIMETYPES.IMAGE.MIMETYPE_EXT)
MIMETYPES.VIDEO_CAPTIONS.EXT_MIMETYPE = invert(MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT)
const BINARY_CONTENT_TYPES = new Set([
export const BINARY_CONTENT_TYPES = new Set([
'binary/octet-stream',
'application/octet-stream',
'application/x-binary'
@ -777,7 +766,7 @@ const BINARY_CONTENT_TYPES = new Set([
// ---------------------------------------------------------------------------
const OVERVIEWS = {
export const OVERVIEWS = {
VIDEOS: {
SAMPLE_THRESHOLD: 6,
SAMPLES_COUNT: 20
@ -786,9 +775,9 @@ const OVERVIEWS = {
// ---------------------------------------------------------------------------
const SERVER_ACTOR_NAME = 'peertube'
export const SERVER_ACTOR_NAME = 'peertube'
const ACTIVITY_PUB = {
export const ACTIVITY_PUB = {
POTENTIAL_ACCEPT_HEADERS: [
'application/activity+json',
'application/ld+json',
@ -803,7 +792,7 @@ const ACTIVITY_PUB = {
VIDEO_PLAYLIST_REFRESH_INTERVAL: 3600 * 24 * 1000 * 2 // 2 days
}
const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = {
export const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = {
GROUP: 'Group',
PERSON: 'Person',
APPLICATION: 'Application',
@ -811,7 +800,7 @@ const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = {
SERVICE: 'Service'
}
const HTTP_SIGNATURE = {
export const HTTP_SIGNATURE = {
HEADER_NAME: 'signature',
ALGORITHM: 'rsa-sha256',
HEADERS_TO_SIGN_WITH_PAYLOAD: [ '(request-target)', 'host', 'date', 'digest' ],
@ -821,27 +810,27 @@ const HTTP_SIGNATURE = {
// ---------------------------------------------------------------------------
let PRIVATE_RSA_KEY_SIZE = 2048
export let PRIVATE_RSA_KEY_SIZE = 2048
// Password encryption
const BCRYPT_SALT_SIZE = 10
export const BCRYPT_SALT_SIZE = 10
const ENCRYPTION = {
export const ENCRYPTION = {
ALGORITHM: 'aes-256-cbc',
IV: 16,
SALT: 'peertube',
ENCODING: 'hex' as Encoding
}
const USER_PASSWORD_RESET_LIFETIME = 60000 * 60 // 60 minutes
const USER_PASSWORD_CREATE_LIFETIME = 60000 * 60 * 24 * 7 // 7 days
export const USER_PASSWORD_RESET_LIFETIME = 60000 * 60 // 60 minutes
export const USER_PASSWORD_CREATE_LIFETIME = 60000 * 60 * 24 * 7 // 7 days
const TWO_FACTOR_AUTH_REQUEST_TOKEN_LIFETIME = 60000 * 10 // 10 minutes
let JWT_TOKEN_USER_EXPORT_FILE_LIFETIME = '15 minutes'
export const TWO_FACTOR_AUTH_REQUEST_TOKEN_LIFETIME = 60000 * 10 // 10 minutes
export let JWT_TOKEN_USER_EXPORT_FILE_LIFETIME = '15 minutes'
const EMAIL_VERIFY_LIFETIME = 60000 * 60 // 60 minutes
export const EMAIL_VERIFY_LIFETIME = 60000 * 60 // 60 minutes
const NSFW_POLICY_TYPES: { [ id: string ]: NSFWPolicyType } = {
export const NSFW_POLICY_TYPES: { [ id: string ]: NSFWPolicyType } = {
DO_NOT_LIST: 'do_not_list',
BLUR: 'blur',
DISPLAY: 'display'
@ -849,13 +838,13 @@ const NSFW_POLICY_TYPES: { [ id: string ]: NSFWPolicyType } = {
// ---------------------------------------------------------------------------
const USER_EXPORT_MAX_ITEMS = 1000
const USER_EXPORT_FILE_PREFIX = 'user-export-'
export const USER_EXPORT_MAX_ITEMS = 1000
export const USER_EXPORT_FILE_PREFIX = 'user-export-'
// ---------------------------------------------------------------------------
// Express static paths (router)
const STATIC_PATHS = {
export const STATIC_PATHS = {
// TODO: deprecated in v6, to remove
THUMBNAILS: '/static/thumbnails/',
@ -874,7 +863,7 @@ const STATIC_PATHS = {
PRIVATE_HLS: '/static/streaming-playlists/hls/private/'
}
}
const DOWNLOAD_PATHS = {
export const DOWNLOAD_PATHS = {
TORRENTS: '/download/torrents/',
GENERATE_VIDEO: '/download/videos/generate/',
WEB_VIDEOS: '/download/web-videos/',
@ -882,7 +871,7 @@ const DOWNLOAD_PATHS = {
USER_EXPORTS: '/download/user-exports/',
ORIGINAL_VIDEO_FILE: '/download/original-video-files/'
}
const LAZY_STATIC_PATHS = {
export const LAZY_STATIC_PATHS = {
THUMBNAILS: '/lazy-static/thumbnails/',
BANNERS: '/lazy-static/banners/',
AVATARS: '/lazy-static/avatars/',
@ -891,7 +880,7 @@ const LAZY_STATIC_PATHS = {
TORRENTS: '/lazy-static/torrents/',
STORYBOARDS: '/lazy-static/storyboards/'
}
const OBJECT_STORAGE_PROXY_PATHS = {
export const OBJECT_STORAGE_PROXY_PATHS = {
// Need to keep this legacy path for previously generated torrents
LEGACY_PRIVATE_WEB_VIDEOS: '/object-storage-proxy/webseed/private/',
PRIVATE_WEB_VIDEOS: '/object-storage-proxy/web-videos/private/',
@ -902,24 +891,24 @@ const OBJECT_STORAGE_PROXY_PATHS = {
}
// Cache control
const STATIC_MAX_AGE = {
export const STATIC_MAX_AGE = {
SERVER: '2h',
LAZY_SERVER: '2d',
CLIENT: '30d'
}
// Videos thumbnail size
const THUMBNAILS_SIZE = {
export const THUMBNAILS_SIZE = {
width: minBy(CONFIG.THUMBNAILS.SIZES, 'width').width,
height: minBy(CONFIG.THUMBNAILS.SIZES, 'width').height,
minRemoteWidth: 150
}
const PREVIEWS_SIZE = {
export const PREVIEWS_SIZE = {
width: maxBy(CONFIG.THUMBNAILS.SIZES, 'width').width,
height: maxBy(CONFIG.THUMBNAILS.SIZES, 'width').height,
minRemoteWidth: 400
}
const ACTOR_IMAGES_SIZE: { [key in ActorImageType_Type]: { width: number, height: number }[] } = {
export const ACTOR_IMAGES_SIZE: { [key in ActorImageType_Type]: { width: number, height: number }[] } = {
[ActorImageType.AVATAR]: [ // 1/1 ratio
{
width: 1500,
@ -950,18 +939,18 @@ const ACTOR_IMAGES_SIZE: { [key in ActorImageType_Type]: { width: number, height
]
}
const STORYBOARD = {
export const STORYBOARD = {
SPRITE_MAX_SIZE: 192,
SPRITES_MAX_EDGE_COUNT: 10
}
const EMBED_SIZE = {
export const EMBED_SIZE = {
width: 560,
height: 315
}
// Sub folders of cache directory
const FILES_CACHE = {
export const FILES_CACHE = {
PREVIEWS: {
DIRECTORY: join(CONFIG.STORAGE.CACHE_DIR, 'previews'),
MAX_AGE: 1000 * 3600 * 3 // 3 hours
@ -980,7 +969,7 @@ const FILES_CACHE = {
}
}
const LRU_CACHE = {
export const LRU_CACHE = {
USER_TOKENS: {
MAX_SIZE: 1000
},
@ -1004,7 +993,7 @@ const LRU_CACHE = {
}
}
const DIRECTORIES = {
export const DIRECTORIES = {
RESUMABLE_UPLOAD: join(CONFIG.STORAGE.TMP_DIR, 'resumable-uploads'),
HLS_STREAMING_PLAYLIST: {
@ -1024,9 +1013,9 @@ const DIRECTORIES = {
LOCAL_PIP_DIRECTORY: join(CONFIG.STORAGE.BIN_DIR, 'pip')
}
const RESUMABLE_UPLOAD_SESSION_LIFETIME = SCHEDULER_INTERVALS_MS.REMOVE_DANGLING_RESUMABLE_UPLOADS
export const RESUMABLE_UPLOAD_SESSION_LIFETIME = SCHEDULER_INTERVALS_MS.REMOVE_DANGLING_RESUMABLE_UPLOADS
const VIDEO_LIVE = {
export const VIDEO_LIVE = {
EXTENSION: '.ts',
CLEANUP_DELAY: 1000 * 60 * 5, // 5 minutes
SEGMENT_TIME_SECONDS: {
@ -1046,7 +1035,7 @@ const VIDEO_LIVE = {
}
}
const MEMOIZE_TTL = {
export const MEMOIZE_TTL = {
OVERVIEWS_SAMPLE: 1000 * 3600 * 4, // 4 hours
INFO_HASH_EXISTS: 1000 * 60, // 1 minute
VIDEO_DURATION: 1000 * 10, // 10 seconds
@ -1056,14 +1045,14 @@ const MEMOIZE_TTL = {
EMBED_HTML: 1000 * 10 // 10 seconds
}
const MEMOIZE_LENGTH = {
export const MEMOIZE_LENGTH = {
INFO_HASH_EXISTS: 200,
VIDEO_DURATION: 200
}
const totalCPUs = Math.max(cpus().length, 1)
export const totalCPUs = Math.max(cpus().length, 1)
const WORKER_THREADS = {
export const WORKER_THREADS = {
DOWNLOAD_IMAGE: {
CONCURRENCY: 3,
MAX_THREADS: 1
@ -1086,26 +1075,26 @@ const WORKER_THREADS = {
}
}
const REDUNDANCY = {
export const REDUNDANCY = {
VIDEOS: {
RANDOMIZED_FACTOR: 5
}
}
const ACCEPT_HEADERS = [ 'html', 'application/json' ].concat(ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS)
const OTP = {
export const ACCEPT_HEADERS = [ 'html', 'application/json' ].concat(ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS)
export const OTP = {
HEADER_NAME: 'x-peertube-otp',
HEADER_REQUIRED_VALUE: 'required; app'
}
const ASSETS_PATH = {
export const ASSETS_PATH = {
DEFAULT_AUDIO_BACKGROUND: join(root(), 'dist', 'core', 'assets', 'default-audio-background.jpg'),
DEFAULT_LIVE_BACKGROUND: join(root(), 'dist', 'core', 'assets', 'default-live-background.jpg')
}
// ---------------------------------------------------------------------------
const CUSTOM_HTML_TAG_COMMENTS = {
export const CUSTOM_HTML_TAG_COMMENTS = {
TITLE: '<!-- title tag -->',
DESCRIPTION: '<!-- description tag -->',
CUSTOM_CSS: '<!-- custom css tag -->',
@ -1113,34 +1102,34 @@ const CUSTOM_HTML_TAG_COMMENTS = {
SERVER_CONFIG: '<!-- server config -->'
}
const MAX_LOGS_OUTPUT_CHARACTERS = 10 * 1000 * 1000
const LOG_FILENAME = 'peertube.log'
const AUDIT_LOG_FILENAME = 'peertube-audit.log'
export const MAX_LOGS_OUTPUT_CHARACTERS = 10 * 1000 * 1000
export const LOG_FILENAME = 'peertube.log'
export const AUDIT_LOG_FILENAME = 'peertube-audit.log'
// ---------------------------------------------------------------------------
const TRACKER_RATE_LIMITS = {
export const TRACKER_RATE_LIMITS = {
INTERVAL: 60000 * 5, // 5 minutes
ANNOUNCES_PER_IP_PER_INFOHASH: 15, // maximum announces per torrent in the interval
ANNOUNCES_PER_IP: 30, // maximum announces for all our torrents in the interval
BLOCK_IP_LIFETIME: parseDurationToMs('3 minutes')
}
const P2P_MEDIA_LOADER_PEER_VERSION = 2
export const P2P_MEDIA_LOADER_PEER_VERSION = 2
// ---------------------------------------------------------------------------
const PLUGIN_GLOBAL_CSS_FILE_NAME = 'plugins-global.css'
const PLUGIN_GLOBAL_CSS_PATH = join(CONFIG.STORAGE.TMP_DIR, PLUGIN_GLOBAL_CSS_FILE_NAME)
export const PLUGIN_GLOBAL_CSS_FILE_NAME = 'plugins-global.css'
export const PLUGIN_GLOBAL_CSS_PATH = join(CONFIG.STORAGE.TMP_DIR, PLUGIN_GLOBAL_CSS_FILE_NAME)
let PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME = 1000 * 60 * 5 // 5 minutes
export let PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME = 1000 * 60 * 5 // 5 minutes
const DEFAULT_THEME_NAME = 'default'
const DEFAULT_USER_THEME_NAME = 'instance-default'
export const DEFAULT_THEME_NAME = 'default'
export const DEFAULT_USER_THEME_NAME = 'instance-default'
// ---------------------------------------------------------------------------
const SEARCH_INDEX = {
export const SEARCH_INDEX = {
ROUTES: {
VIDEOS: '/api/v1/search/videos',
VIDEO_CHANNELS: '/api/v1/search/video-channels'
@ -1149,7 +1138,7 @@ const SEARCH_INDEX = {
// ---------------------------------------------------------------------------
const STATS_TIMESERIE = {
export const STATS_TIMESERIE = {
MAX_DAYS: 365 * 10 // Around 10 years
}
@ -1231,9 +1220,15 @@ registerConfigChangedHandler(() => {
updateWebserverConfig()
})
export async function loadLanguages () {
if (Object.keys(VIDEO_LANGUAGES).length !== 0) return
Object.assign(VIDEO_LANGUAGES, await buildLanguages())
}
// ---------------------------------------------------------------------------
const FILES_CONTENT_HASH = {
export const FILES_CONTENT_HASH = {
MANIFEST: generateContentHash(),
FAVICON: generateContentHash(),
LOGO: generateContentHash()
@ -1241,7 +1236,7 @@ const FILES_CONTENT_HASH = {
// ---------------------------------------------------------------------------
const VIDEO_FILTERS = {
export const VIDEO_FILTERS = {
WATERMARK: {
SIZE_RATIO: 1 / 10,
HORIZONTAL_MARGIN_RATIO: 1 / 20,
@ -1250,116 +1245,7 @@ const VIDEO_FILTERS = {
}
// ---------------------------------------------------------------------------
export {
WEBSERVER,
API_VERSION,
ENCRYPTION,
VIDEO_LIVE,
PEERTUBE_VERSION,
LAZY_STATIC_PATHS,
OBJECT_STORAGE_PROXY_PATHS,
SEARCH_INDEX,
DIRECTORIES,
RESUMABLE_UPLOAD_SESSION_LIFETIME,
RUNNER_JOB_STATES,
USER_EXPORT_STATES,
USER_IMPORT_STATES,
P2P_MEDIA_LOADER_PEER_VERSION,
STORYBOARD,
ACTOR_IMAGES_SIZE,
ACCEPT_HEADERS,
BCRYPT_SALT_SIZE,
TRACKER_RATE_LIMITS,
VIDEO_COMMENTS_POLICY,
FILES_CACHE,
LOG_FILENAME,
CONSTRAINTS_FIELDS,
EMBED_SIZE,
REDUNDANCY,
USER_EXPORT_FILE_PREFIX,
JOB_CONCURRENCY,
JOB_ATTEMPTS,
AP_CLEANER,
LAST_MIGRATION_VERSION,
CUSTOM_HTML_TAG_COMMENTS,
STATS_TIMESERIE,
BROADCAST_CONCURRENCY,
AUDIT_LOG_FILENAME,
USER_IMPORT,
PAGINATION,
ACTOR_FOLLOW_SCORE,
PREVIEWS_SIZE,
REMOTE_SCHEME,
FOLLOW_STATES,
DEFAULT_USER_THEME_NAME,
SERVER_ACTOR_NAME,
TWO_FACTOR_AUTH_REQUEST_TOKEN_LIFETIME,
JWT_TOKEN_USER_EXPORT_FILE_LIFETIME,
PLUGIN_GLOBAL_CSS_FILE_NAME,
PLUGIN_GLOBAL_CSS_PATH,
PRIVATE_RSA_KEY_SIZE,
VIDEO_FILTERS,
ROUTE_CACHE_LIFETIME,
SORTABLE_COLUMNS,
JOB_TTL,
DEFAULT_THEME_NAME,
NSFW_POLICY_TYPES,
STATIC_MAX_AGE,
VIEWER_SYNC_REDIS,
STATIC_PATHS,
USER_EXPORT_MAX_ITEMS,
VIDEO_IMPORT_TIMEOUT,
VIDEO_PLAYLIST_TYPES,
MAX_LOGS_OUTPUT_CHARACTERS,
ACTIVITY_PUB,
ACTIVITY_PUB_ACTOR_TYPES,
THUMBNAILS_SIZE,
VIDEO_CATEGORIES,
MEMOIZE_LENGTH,
VIDEO_LANGUAGES,
VIDEO_PRIVACIES,
VIDEO_LICENCES,
VIDEO_STATES,
WORKER_THREADS,
VIDEO_RATE_TYPES,
JOB_PRIORITY,
VIDEO_TRANSCODING_FPS,
FFMPEG_NICE,
ABUSE_STATES,
USER_REGISTRATION_STATES,
LRU_CACHE,
REQUEST_TIMEOUTS,
RUNNER_JOBS,
MAX_LOCAL_VIEWER_WATCH_SECTIONS,
USER_PASSWORD_RESET_LIFETIME,
USER_PASSWORD_CREATE_LIFETIME,
MEMOIZE_TTL,
EMAIL_VERIFY_LIFETIME,
OVERVIEWS,
SCHEDULER_INTERVALS_MS,
REPEAT_JOBS,
DOWNLOAD_PATHS,
MIMETYPES,
CRAWL_REQUEST_CONCURRENCY,
DEFAULT_AUDIO_RESOLUTION,
BINARY_CONTENT_TYPES,
JOB_REMOVAL_OPTIONS,
HTTP_SIGNATURE,
VIDEO_IMPORT_STATES,
VIDEO_CHANNEL_SYNC_STATE,
VIEW_LIFETIME,
CONTACT_FORM_LIFETIME,
VIDEO_PLAYLIST_PRIVACIES,
PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME,
ASSETS_PATH,
FILES_CONTENT_HASH,
OTP,
loadLanguages,
buildLanguages,
generateContentHash
}
// Private
// ---------------------------------------------------------------------------
function buildVideoMimetypeExt () {
@ -1480,12 +1366,6 @@ function buildMimetypesRegex (obj: { [id: string]: string | string[] }) {
.join('|')
}
async function loadLanguages () {
if (Object.keys(VIDEO_LANGUAGES).length !== 0) return
Object.assign(VIDEO_LANGUAGES, await buildLanguages())
}
async function buildLanguages () {
const { iso6393 } = await import('iso-639-3')