aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/live/shared/transcoding-wrapper
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/lib/live/shared/transcoding-wrapper
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
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)
Diffstat (limited to 'server/lib/live/shared/transcoding-wrapper')
-rw-r--r--server/lib/live/shared/transcoding-wrapper/abstract-transcoding-wrapper.ts110
-rw-r--r--server/lib/live/shared/transcoding-wrapper/ffmpeg-transcoding-wrapper.ts107
-rw-r--r--server/lib/live/shared/transcoding-wrapper/index.ts3
-rw-r--r--server/lib/live/shared/transcoding-wrapper/remote-transcoding-wrapper.ts21
4 files changed, 0 insertions, 241 deletions
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 @@
1import EventEmitter from 'events'
2import { LoggerTagsFn } from '@server/helpers/logger'
3import { MStreamingPlaylistVideo, MVideoLiveVideo } from '@server/types/models'
4import { LiveVideoError } from '@shared/models'
5
6interface TranscodingWrapperEvents {
7 'end': () => void
8
9 'error': (options: { err: Error }) => void
10}
11
12declare interface AbstractTranscodingWrapper {
13 on<U extends keyof TranscodingWrapperEvents>(
14 event: U, listener: TranscodingWrapperEvents[U]
15 ): this
16
17 emit<U extends keyof TranscodingWrapperEvents>(
18 event: U, ...args: Parameters<TranscodingWrapperEvents[U]>
19 ): boolean
20}
21
22interface AbstractTranscodingWrapperOptions {
23 streamingPlaylist: MStreamingPlaylistVideo
24 videoLive: MVideoLiveVideo
25
26 lTags: LoggerTagsFn
27
28 sessionId: string
29 inputLocalUrl: string
30 inputPublicUrl: string
31
32 fps: number
33 toTranscode: {
34 resolution: number
35 fps: number
36 }[]
37
38 bitrate: number
39 ratio: number
40 hasAudio: boolean
41
42 segmentListSize: number
43 segmentDuration: number
44
45 outDirectory: string
46}
47
48abstract class AbstractTranscodingWrapper extends EventEmitter {
49 protected readonly videoLive: MVideoLiveVideo
50
51 protected readonly toTranscode: {
52 resolution: number
53 fps: number
54 }[]
55
56 protected readonly sessionId: string
57 protected readonly inputLocalUrl: string
58 protected readonly inputPublicUrl: string
59
60 protected readonly fps: number
61 protected readonly bitrate: number
62 protected readonly ratio: number
63 protected readonly hasAudio: boolean
64
65 protected readonly segmentListSize: number
66 protected readonly segmentDuration: number
67
68 protected readonly videoUUID: string
69
70 protected readonly outDirectory: string
71
72 protected readonly lTags: LoggerTagsFn
73
74 protected readonly streamingPlaylist: MStreamingPlaylistVideo
75
76 constructor (options: AbstractTranscodingWrapperOptions) {
77 super()
78
79 this.lTags = options.lTags
80
81 this.videoLive = options.videoLive
82 this.videoUUID = options.videoLive.Video.uuid
83 this.streamingPlaylist = options.streamingPlaylist
84
85 this.sessionId = options.sessionId
86 this.inputLocalUrl = options.inputLocalUrl
87 this.inputPublicUrl = options.inputPublicUrl
88
89 this.fps = options.fps
90 this.toTranscode = options.toTranscode
91
92 this.bitrate = options.bitrate
93 this.ratio = options.ratio
94 this.hasAudio = options.hasAudio
95
96 this.segmentListSize = options.segmentListSize
97 this.segmentDuration = options.segmentDuration
98
99 this.outDirectory = options.outDirectory
100 }
101
102 abstract run (): Promise<void>
103
104 abstract abort (error?: LiveVideoError): void
105}
106
107export {
108 AbstractTranscodingWrapper,
109 AbstractTranscodingWrapperOptions
110}
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 @@
1import { FfmpegCommand } from 'fluent-ffmpeg'
2import { getFFmpegCommandWrapperOptions } from '@server/helpers/ffmpeg'
3import { logger } from '@server/helpers/logger'
4import { CONFIG } from '@server/initializers/config'
5import { VIDEO_LIVE } from '@server/initializers/constants'
6import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles'
7import { FFmpegLive } from '@shared/ffmpeg'
8import { getLiveSegmentTime } from '../../live-utils'
9import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper'
10
11export class FFmpegTranscodingWrapper extends AbstractTranscodingWrapper {
12 private ffmpegCommand: FfmpegCommand
13
14 private aborted = false
15 private errored = false
16 private ended = false
17
18 async run () {
19 this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED
20 ? await this.buildFFmpegLive().getLiveTranscodingCommand({
21 inputUrl: this.inputLocalUrl,
22
23 outPath: this.outDirectory,
24 masterPlaylistName: this.streamingPlaylist.playlistFilename,
25
26 segmentListSize: this.segmentListSize,
27 segmentDuration: this.segmentDuration,
28
29 toTranscode: this.toTranscode,
30
31 bitrate: this.bitrate,
32 ratio: this.ratio,
33
34 hasAudio: this.hasAudio
35 })
36 : this.buildFFmpegLive().getLiveMuxingCommand({
37 inputUrl: this.inputLocalUrl,
38 outPath: this.outDirectory,
39
40 masterPlaylistName: this.streamingPlaylist.playlistFilename,
41
42 segmentListSize: VIDEO_LIVE.SEGMENTS_LIST_SIZE,
43 segmentDuration: getLiveSegmentTime(this.videoLive.latencyMode)
44 })
45
46 logger.info('Running local live muxing/transcoding for %s.', this.videoUUID, this.lTags())
47
48 let ffmpegShellCommand: string
49 this.ffmpegCommand.on('start', cmdline => {
50 ffmpegShellCommand = cmdline
51
52 logger.debug('Running ffmpeg command for live', { ffmpegShellCommand, ...this.lTags() })
53 })
54
55 this.ffmpegCommand.on('error', (err, stdout, stderr) => {
56 this.onFFmpegError({ err, stdout, stderr, ffmpegShellCommand })
57 })
58
59 this.ffmpegCommand.on('end', () => {
60 this.onFFmpegEnded()
61 })
62
63 this.ffmpegCommand.run()
64 }
65
66 abort () {
67 if (this.ended || this.errored || this.aborted) return
68
69 logger.debug('Killing ffmpeg after live abort of ' + this.videoUUID, this.lTags())
70
71 this.ffmpegCommand.kill('SIGINT')
72
73 this.aborted = true
74 this.emit('end')
75 }
76
77 private onFFmpegError (options: {
78 err: any
79 stdout: string
80 stderr: string
81 ffmpegShellCommand: string
82 }) {
83 const { err, stdout, stderr, ffmpegShellCommand } = options
84
85 // Don't care that we killed the ffmpeg process
86 if (err?.message?.includes('Exiting normally')) return
87 if (this.ended || this.errored || this.aborted) return
88
89 logger.error('FFmpeg transcoding error.', { err, stdout, stderr, ffmpegShellCommand, ...this.lTags() })
90
91 this.errored = true
92 this.emit('error', { err })
93 }
94
95 private onFFmpegEnded () {
96 if (this.ended || this.errored || this.aborted) return
97
98 logger.debug('Live ffmpeg transcoding ended for ' + this.videoUUID, this.lTags())
99
100 this.ended = true
101 this.emit('end')
102 }
103
104 private buildFFmpegLive () {
105 return new FFmpegLive(getFFmpegCommandWrapperOptions('live', VideoTranscodingProfilesManager.Instance.getAvailableEncoders()))
106 }
107}
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 @@
1export * from './abstract-transcoding-wrapper'
2export * from './ffmpeg-transcoding-wrapper'
3export * 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 @@
1import { LiveRTMPHLSTranscodingJobHandler } from '@server/lib/runners'
2import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper'
3
4export class RemoteTranscodingWrapper extends AbstractTranscodingWrapper {
5 async run () {
6 await new LiveRTMPHLSTranscodingJobHandler().create({
7 rtmpUrl: this.inputPublicUrl,
8 sessionId: this.sessionId,
9 toTranscode: this.toTranscode,
10 video: this.videoLive.Video,
11 outputDirectory: this.outDirectory,
12 playlist: this.streamingPlaylist,
13 segmentListSize: this.segmentListSize,
14 segmentDuration: this.segmentDuration
15 })
16 }
17
18 abort () {
19 this.emit('end')
20 }
21}