mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-04 18:29:27 +02:00
server/server -> server/core
This commit is contained in:
parent
114327d4ce
commit
5a3d0650c9
838 changed files with 111 additions and 111 deletions
|
@ -0,0 +1,111 @@
|
|||
import { LiveVideoErrorType } from '@peertube/peertube-models'
|
||||
import { LoggerTagsFn } from '@server/helpers/logger.js'
|
||||
import { MStreamingPlaylistVideo, MVideoLiveVideo } from '@server/types/models/index.js'
|
||||
import EventEmitter from 'events'
|
||||
|
||||
interface TranscodingWrapperEvents {
|
||||
'end': () => void
|
||||
|
||||
'error': (options: { err: Error }) => void
|
||||
}
|
||||
|
||||
declare interface AbstractTranscodingWrapper {
|
||||
on<U extends keyof TranscodingWrapperEvents>(
|
||||
event: U, listener: TranscodingWrapperEvents[U]
|
||||
): this
|
||||
|
||||
emit<U extends keyof TranscodingWrapperEvents>(
|
||||
event: U, ...args: Parameters<TranscodingWrapperEvents[U]>
|
||||
): 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<void>
|
||||
|
||||
abstract abort (error?: LiveVideoErrorType): void
|
||||
}
|
||||
|
||||
export {
|
||||
type AbstractTranscodingWrapperOptions,
|
||||
|
||||
AbstractTranscodingWrapper
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
import { FfmpegCommand } from 'fluent-ffmpeg'
|
||||
import { getFFmpegCommandWrapperOptions } from '@server/helpers/ffmpeg/index.js'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
import { VIDEO_LIVE } from '@server/initializers/constants.js'
|
||||
import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles.js'
|
||||
import { FFmpegLive } from '@peertube/peertube-ffmpeg'
|
||||
import { getLiveSegmentTime } from '../../live-utils.js'
|
||||
import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper.js'
|
||||
|
||||
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()))
|
||||
}
|
||||
}
|
3
server/core/lib/live/shared/transcoding-wrapper/index.ts
Normal file
3
server/core/lib/live/shared/transcoding-wrapper/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from './abstract-transcoding-wrapper.js'
|
||||
export * from './ffmpeg-transcoding-wrapper.js'
|
||||
export * from './remote-transcoding-wrapper.js'
|
|
@ -0,0 +1,21 @@
|
|||
import { LiveRTMPHLSTranscodingJobHandler } from '@server/lib/runners/index.js'
|
||||
import { AbstractTranscodingWrapper } from './abstract-transcoding-wrapper.js'
|
||||
|
||||
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')
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue