From 3a4992633ee62d5edfbb484d9c6bcb3cf158489d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 31 Jul 2023 14:34:36 +0200 Subject: Migrate server to ESM Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports) --- .../abstract-transcoding-wrapper.ts | 110 --------------------- .../ffmpeg-transcoding-wrapper.ts | 107 -------------------- .../lib/live/shared/transcoding-wrapper/index.ts | 3 - .../remote-transcoding-wrapper.ts | 21 ---- 4 files changed, 241 deletions(-) delete mode 100644 server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts delete mode 100644 server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts delete mode 100644 server/lib/live/shared/transcoding-wrapper/index.ts delete mode 100644 server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts (limited to 'server/lib/live/shared/transcoding-wrapper') diff --git a/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts b/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts deleted file mode 100644 index 95168745d..000000000 --- a/server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts +++ /dev/null @@ -1,110 +0,0 @@ -import EventEmitter from 'events' -import { LoggerTagsFn } from '@server/helpers/logger' -import { MStreamingPlaylistVideo, MVideoLiveVideo } from '@server/types/models' -import { LiveVideoError } from '@shared/models' - -interface TranscodingWrapperEvents { - 'end': () => void - - 'error': (options: { err: Error }) => void -} - -declare interface AbstractTranscodingWrapper { - on( - event: U, listener: TranscodingWrapperEvents[U] - ): this - - emit( - event: U, ...args: Parameters - ): boolean -} - -interface AbstractTranscodingWrapperOptions { - streamingPlaylist: MStreamingPlaylistVideo - videoLive: MVideoLiveVideo - - lTags: LoggerTagsFn - - sessionId: string - inputLocalUrl: string - inputPublicUrl: string - - fps: number - toTranscode: { - resolution: number - fps: number - }[] - - bitrate: number - ratio: number - hasAudio: boolean - - segmentListSize: number - segmentDuration: number - - outDirectory: string -} - -abstract class AbstractTranscodingWrapper extends EventEmitter { - protected readonly videoLive: MVideoLiveVideo - - protected readonly toTranscode: { - resolution: number - fps: number - }[] - - protected readonly sessionId: string - protected readonly inputLocalUrl: string - protected readonly inputPublicUrl: string - - protected readonly fps: number - protected readonly bitrate: number - protected readonly ratio: number - protected readonly hasAudio: boolean - - protected readonly segmentListSize: number - protected readonly segmentDuration: number - - protected readonly videoUUID: string - - protected readonly outDirectory: string - - protected readonly lTags: LoggerTagsFn - - protected readonly streamingPlaylist: MStreamingPlaylistVideo - - constructor (options: AbstractTranscodingWrapperOptions) { - super() - - this.lTags = options.lTags - - this.videoLive = options.videoLive - this.videoUUID = options.videoLive.Video.uuid - this.streamingPlaylist = options.streamingPlaylist - - this.sessionId = options.sessionId - this.inputLocalUrl = options.inputLocalUrl - this.inputPublicUrl = options.inputPublicUrl - - this.fps = options.fps - this.toTranscode = options.toTranscode - - this.bitrate = options.bitrate - this.ratio = options.ratio - this.hasAudio = options.hasAudio - - this.segmentListSize = options.segmentListSize - this.segmentDuration = options.segmentDuration - - this.outDirectory = options.outDirectory - } - - abstract run (): Promise - - abstract abort (error?: LiveVideoError): void -} - -export { - AbstractTranscodingWrapper, - AbstractTranscodingWrapperOptions -} diff --git a/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts b/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts deleted file mode 100644 index c6ee8ebf1..000000000 --- a/server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { FfmpegCommand } from 'fluent-ffmpeg' -import { getFFmpegCommandWrapperOptions } from '@server/helpers/ffmpeg' -import { logger } from '@server/helpers/logger' -import { CONFIG } from '@server/initializers/config' -import { VIDEO_LIVE } from '@server/initializers/constants' -import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles' -import { FFmpegLive } from '@shared/ffmpeg' -import { getLiveSegmentTime } from '../../live-utils' -import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper' - -export class FFmpegTranscodingWrapper extends AbstractTranscodingWrapper { - private ffmpegCommand: FfmpegCommand - - private aborted = false - private errored = false - private ended = false - - async run () { - this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED - ? await this.buildFFmpegLive().getLiveTranscodingCommand({ - inputUrl: this.inputLocalUrl, - - outPath: this.outDirectory, - masterPlaylistName: this.streamingPlaylist.playlistFilename, - - segmentListSize: this.segmentListSize, - segmentDuration: this.segmentDuration, - - toTranscode: this.toTranscode, - - bitrate: this.bitrate, - ratio: this.ratio, - - hasAudio: this.hasAudio - }) - : this.buildFFmpegLive().getLiveMuxingCommand({ - inputUrl: this.inputLocalUrl, - outPath: this.outDirectory, - - masterPlaylistName: this.streamingPlaylist.playlistFilename, - - segmentListSize: VIDEO_LIVE.SEGMENTS_LIST_SIZE, - segmentDuration: getLiveSegmentTime(this.videoLive.latencyMode) - }) - - logger.info('Running local live muxing/transcoding for %s.', this.videoUUID, this.lTags()) - - let ffmpegShellCommand: string - this.ffmpegCommand.on('start', cmdline => { - ffmpegShellCommand = cmdline - - logger.debug('Running ffmpeg command for live', { ffmpegShellCommand, ...this.lTags() }) - }) - - this.ffmpegCommand.on('error', (err, stdout, stderr) => { - this.onFFmpegError({ err, stdout, stderr, ffmpegShellCommand }) - }) - - this.ffmpegCommand.on('end', () => { - this.onFFmpegEnded() - }) - - this.ffmpegCommand.run() - } - - abort () { - if (this.ended || this.errored || this.aborted) return - - logger.debug('Killing ffmpeg after live abort of ' + this.videoUUID, this.lTags()) - - this.ffmpegCommand.kill('SIGINT') - - this.aborted = true - this.emit('end') - } - - private onFFmpegError (options: { - err: any - stdout: string - stderr: string - ffmpegShellCommand: string - }) { - const { err, stdout, stderr, ffmpegShellCommand } = options - - // Don't care that we killed the ffmpeg process - if (err?.message?.includes('Exiting normally')) return - if (this.ended || this.errored || this.aborted) return - - logger.error('FFmpeg transcoding error.', { err, stdout, stderr, ffmpegShellCommand, ...this.lTags() }) - - this.errored = true - this.emit('error', { err }) - } - - private onFFmpegEnded () { - if (this.ended || this.errored || this.aborted) return - - logger.debug('Live ffmpeg transcoding ended for ' + this.videoUUID, this.lTags()) - - this.ended = true - this.emit('end') - } - - private buildFFmpegLive () { - return new FFmpegLive(getFFmpegCommandWrapperOptions('live', VideoTranscodingProfilesManager.Instance.getAvailableEncoders())) - } -} diff --git a/server/lib/live/shared/transcoding-wrapper/index.ts b/server/lib/live/shared/transcoding-wrapper/index.ts deleted file mode 100644 index ae28fa1ca..000000000 --- a/server/lib/live/shared/transcoding-wrapper/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './abstract-transcoding-wrapper' -export * from './ffmpeg-transcoding-wrapper' -export * from './remote-transcoding-wrapper' diff --git a/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts b/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts deleted file mode 100644 index 2aeeb31fb..000000000 --- a/server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { LiveRTMPHLSTranscodingJobHandler } from '@server/lib/runners' -import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper' - -export class RemoteTranscodingWrapper extends AbstractTranscodingWrapper { - async run () { - await new LiveRTMPHLSTranscodingJobHandler().create({ - rtmpUrl: this.inputPublicUrl, - sessionId: this.sessionId, - toTranscode: this.toTranscode, - video: this.videoLive.Video, - outputDirectory: this.outDirectory, - playlist: this.streamingPlaylist, - segmentListSize: this.segmentListSize, - segmentDuration: this.segmentDuration - }) - } - - abort () { - this.emit('end') - } -} -- cgit v1.2.3