mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-05-17 04:12:40 +00:00
3a4992633e
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)
202 lines
5.9 KiB
TypeScript
202 lines
5.9 KiB
TypeScript
import { remove } from 'fs-extra/esm'
|
|
import { join } from 'path'
|
|
import {
|
|
RunnerJobVODAudioMergeTranscodingPayload,
|
|
RunnerJobVODHLSTranscodingPayload,
|
|
RunnerJobVODWebVideoTranscodingPayload,
|
|
VODAudioMergeTranscodingSuccess,
|
|
VODHLSTranscodingSuccess,
|
|
VODWebVideoTranscodingSuccess
|
|
} from '@peertube/peertube-models'
|
|
import { buildUUID } from '@peertube/peertube-node-utils'
|
|
import { ConfigManager } from '../../../shared/config-manager.js'
|
|
import { logger } from '../../../shared/index.js'
|
|
import { buildFFmpegVOD, downloadInputFile, ProcessOptions, scheduleTranscodingProgress } from './common.js'
|
|
|
|
export async function processWebVideoTranscoding (options: ProcessOptions<RunnerJobVODWebVideoTranscodingPayload>) {
|
|
const { server, job, runnerToken } = options
|
|
|
|
const payload = job.payload
|
|
|
|
let ffmpegProgress: number
|
|
let inputPath: string
|
|
|
|
const outputPath = join(ConfigManager.Instance.getTranscodingDirectory(), `output-${buildUUID()}.mp4`)
|
|
|
|
const updateProgressInterval = scheduleTranscodingProgress({
|
|
job,
|
|
server,
|
|
runnerToken,
|
|
progressGetter: () => ffmpegProgress
|
|
})
|
|
|
|
try {
|
|
logger.info(`Downloading input file ${payload.input.videoFileUrl} for web video transcoding job ${job.jobToken}`)
|
|
|
|
inputPath = await downloadInputFile({ url: payload.input.videoFileUrl, runnerToken, job })
|
|
|
|
logger.info(`Downloaded input file ${payload.input.videoFileUrl} for job ${job.jobToken}. Running web video transcoding.`)
|
|
|
|
const ffmpegVod = buildFFmpegVOD({
|
|
onJobProgress: progress => { ffmpegProgress = progress }
|
|
})
|
|
|
|
await ffmpegVod.transcode({
|
|
type: 'video',
|
|
|
|
inputPath,
|
|
|
|
outputPath,
|
|
|
|
inputFileMutexReleaser: () => {},
|
|
|
|
resolution: payload.output.resolution,
|
|
fps: payload.output.fps
|
|
})
|
|
|
|
const successBody: VODWebVideoTranscodingSuccess = {
|
|
videoFile: outputPath
|
|
}
|
|
|
|
await server.runnerJobs.success({
|
|
jobToken: job.jobToken,
|
|
jobUUID: job.uuid,
|
|
runnerToken,
|
|
payload: successBody
|
|
})
|
|
} finally {
|
|
if (inputPath) await remove(inputPath)
|
|
if (outputPath) await remove(outputPath)
|
|
if (updateProgressInterval) clearInterval(updateProgressInterval)
|
|
}
|
|
}
|
|
|
|
export async function processHLSTranscoding (options: ProcessOptions<RunnerJobVODHLSTranscodingPayload>) {
|
|
const { server, job, runnerToken } = options
|
|
const payload = job.payload
|
|
|
|
let ffmpegProgress: number
|
|
let inputPath: string
|
|
|
|
const uuid = buildUUID()
|
|
const outputPath = join(ConfigManager.Instance.getTranscodingDirectory(), `${uuid}-${payload.output.resolution}.m3u8`)
|
|
const videoFilename = `${uuid}-${payload.output.resolution}-fragmented.mp4`
|
|
const videoPath = join(join(ConfigManager.Instance.getTranscodingDirectory(), videoFilename))
|
|
|
|
const updateProgressInterval = scheduleTranscodingProgress({
|
|
job,
|
|
server,
|
|
runnerToken,
|
|
progressGetter: () => ffmpegProgress
|
|
})
|
|
|
|
try {
|
|
logger.info(`Downloading input file ${payload.input.videoFileUrl} for HLS transcoding job ${job.jobToken}`)
|
|
|
|
inputPath = await downloadInputFile({ url: payload.input.videoFileUrl, runnerToken, job })
|
|
|
|
logger.info(`Downloaded input file ${payload.input.videoFileUrl} for job ${job.jobToken}. Running HLS transcoding.`)
|
|
|
|
const ffmpegVod = buildFFmpegVOD({
|
|
onJobProgress: progress => { ffmpegProgress = progress }
|
|
})
|
|
|
|
await ffmpegVod.transcode({
|
|
type: 'hls',
|
|
copyCodecs: false,
|
|
inputPath,
|
|
hlsPlaylist: { videoFilename },
|
|
outputPath,
|
|
|
|
inputFileMutexReleaser: () => {},
|
|
|
|
resolution: payload.output.resolution,
|
|
fps: payload.output.fps
|
|
})
|
|
|
|
const successBody: VODHLSTranscodingSuccess = {
|
|
resolutionPlaylistFile: outputPath,
|
|
videoFile: videoPath
|
|
}
|
|
|
|
await server.runnerJobs.success({
|
|
jobToken: job.jobToken,
|
|
jobUUID: job.uuid,
|
|
runnerToken,
|
|
payload: successBody
|
|
})
|
|
} finally {
|
|
if (inputPath) await remove(inputPath)
|
|
if (outputPath) await remove(outputPath)
|
|
if (videoPath) await remove(videoPath)
|
|
if (updateProgressInterval) clearInterval(updateProgressInterval)
|
|
}
|
|
}
|
|
|
|
export async function processAudioMergeTranscoding (options: ProcessOptions<RunnerJobVODAudioMergeTranscodingPayload>) {
|
|
const { server, job, runnerToken } = options
|
|
const payload = job.payload
|
|
|
|
let ffmpegProgress: number
|
|
let audioPath: string
|
|
let inputPath: string
|
|
|
|
const outputPath = join(ConfigManager.Instance.getTranscodingDirectory(), `output-${buildUUID()}.mp4`)
|
|
|
|
const updateProgressInterval = scheduleTranscodingProgress({
|
|
job,
|
|
server,
|
|
runnerToken,
|
|
progressGetter: () => ffmpegProgress
|
|
})
|
|
|
|
try {
|
|
logger.info(
|
|
`Downloading input files ${payload.input.audioFileUrl} and ${payload.input.previewFileUrl} ` +
|
|
`for audio merge transcoding job ${job.jobToken}`
|
|
)
|
|
|
|
audioPath = await downloadInputFile({ url: payload.input.audioFileUrl, runnerToken, job })
|
|
inputPath = await downloadInputFile({ url: payload.input.previewFileUrl, runnerToken, job })
|
|
|
|
logger.info(
|
|
`Downloaded input files ${payload.input.audioFileUrl} and ${payload.input.previewFileUrl} ` +
|
|
`for job ${job.jobToken}. Running audio merge transcoding.`
|
|
)
|
|
|
|
const ffmpegVod = buildFFmpegVOD({
|
|
onJobProgress: progress => { ffmpegProgress = progress }
|
|
})
|
|
|
|
await ffmpegVod.transcode({
|
|
type: 'merge-audio',
|
|
|
|
audioPath,
|
|
inputPath,
|
|
|
|
outputPath,
|
|
|
|
inputFileMutexReleaser: () => {},
|
|
|
|
resolution: payload.output.resolution,
|
|
fps: payload.output.fps
|
|
})
|
|
|
|
const successBody: VODAudioMergeTranscodingSuccess = {
|
|
videoFile: outputPath
|
|
}
|
|
|
|
await server.runnerJobs.success({
|
|
jobToken: job.jobToken,
|
|
jobUUID: job.uuid,
|
|
runnerToken,
|
|
payload: successBody
|
|
})
|
|
} finally {
|
|
if (audioPath) await remove(audioPath)
|
|
if (inputPath) await remove(inputPath)
|
|
if (outputPath) await remove(outputPath)
|
|
if (updateProgressInterval) clearInterval(updateProgressInterval)
|
|
}
|
|
}
|