PeerTube/packages/peertube-runner/server/process/shared/process-vod.ts

202 lines
5.9 KiB
TypeScript
Raw Normal View History

2023-04-21 08:05:27 -05:00
import { remove } from 'fs-extra'
import { logger } from 'packages/peertube-runner/shared'
2023-04-21 08:05:27 -05:00
import { join } from 'path'
import { buildUUID } from '@shared/extra-utils'
import {
RunnerJobVODAudioMergeTranscodingPayload,
RunnerJobVODHLSTranscodingPayload,
RunnerJobVODWebVideoTranscodingPayload,
VODAudioMergeTranscodingSuccess,
VODHLSTranscodingSuccess,
VODWebVideoTranscodingSuccess
} from '@shared/models'
import { ConfigManager } from '../../../shared/config-manager'
2023-06-22 08:25:39 -05:00
import { buildFFmpegVOD, downloadInputFile, ProcessOptions, scheduleTranscodingProgress } from './common'
2023-04-21 08:05:27 -05:00
export async function processWebVideoTranscoding (options: ProcessOptions<RunnerJobVODWebVideoTranscodingPayload>) {
const { server, job, runnerToken } = options
2023-06-22 08:25:39 -05:00
2023-04-21 08:05:27 -05:00
const payload = job.payload
2023-06-22 08:25:39 -05:00
let ffmpegProgress: number
let inputPath: string
const outputPath = join(ConfigManager.Instance.getTranscodingDirectory(), `output-${buildUUID()}.mp4`)
2023-06-22 08:25:39 -05:00
const updateProgressInterval = scheduleTranscodingProgress({
job,
server,
runnerToken,
progressGetter: () => ffmpegProgress
})
2023-04-21 08:05:27 -05:00
2023-06-22 08:25:39 -05:00
try {
logger.info(`Downloading input file ${payload.input.videoFileUrl} for web video transcoding job ${job.jobToken}`)
2023-06-22 08:25:39 -05:00
inputPath = await downloadInputFile({ url: payload.input.videoFileUrl, runnerToken, job })
2023-04-21 08:05:27 -05:00
2023-06-22 08:25:39 -05:00
logger.info(`Downloaded input file ${payload.input.videoFileUrl} for job ${job.jobToken}. Running web video transcoding.`)
const ffmpegVod = buildFFmpegVOD({
onJobProgress: progress => { ffmpegProgress = progress }
})
2023-04-21 08:05:27 -05:00
await ffmpegVod.transcode({
type: 'video',
2023-04-21 08:05:27 -05:00
inputPath,
2023-04-21 08:05:27 -05:00
outputPath,
2023-04-21 08:05:27 -05:00
inputFileMutexReleaser: () => {},
2023-04-21 08:05:27 -05:00
resolution: payload.output.resolution,
fps: payload.output.fps
})
2023-04-21 08:05:27 -05:00
const successBody: VODWebVideoTranscodingSuccess = {
videoFile: outputPath
}
2023-04-21 08:05:27 -05:00
await server.runnerJobs.success({
jobToken: job.jobToken,
jobUUID: job.uuid,
runnerToken,
payload: successBody
})
} finally {
2023-06-22 08:25:39 -05:00
if (inputPath) await remove(inputPath)
if (outputPath) await remove(outputPath)
if (updateProgressInterval) clearInterval(updateProgressInterval)
}
2023-04-21 08:05:27 -05:00
}
export async function processHLSTranscoding (options: ProcessOptions<RunnerJobVODHLSTranscodingPayload>) {
const { server, job, runnerToken } = options
const payload = job.payload
2023-06-22 08:25:39 -05:00
let ffmpegProgress: number
let inputPath: string
2023-04-21 08:05:27 -05:00
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))
2023-06-22 08:25:39 -05:00
const updateProgressInterval = scheduleTranscodingProgress({
job,
server,
runnerToken,
progressGetter: () => ffmpegProgress
})
2023-04-21 08:05:27 -05:00
try {
2023-06-22 08:25:39 -05:00
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 {
2023-06-22 08:25:39 -05:00
if (inputPath) await remove(inputPath)
if (outputPath) await remove(outputPath)
if (videoPath) await remove(videoPath)
if (updateProgressInterval) clearInterval(updateProgressInterval)
2023-04-21 08:05:27 -05:00
}
}
export async function processAudioMergeTranscoding (options: ProcessOptions<RunnerJobVODAudioMergeTranscodingPayload>) {
const { server, job, runnerToken } = options
const payload = job.payload
2023-06-22 08:25:39 -05:00
let ffmpegProgress: number
let audioPath: string
let inputPath: string
2023-04-21 08:05:27 -05:00
const outputPath = join(ConfigManager.Instance.getTranscodingDirectory(), `output-${buildUUID()}.mp4`)
2023-06-22 08:25:39 -05:00
const updateProgressInterval = scheduleTranscodingProgress({
job,
server,
runnerToken,
progressGetter: () => ffmpegProgress
})
2023-04-21 08:05:27 -05:00
try {
2023-06-22 08:25:39 -05:00
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',
2023-04-21 08:05:27 -05:00
audioPath,
inputPath,
2023-04-21 08:05:27 -05:00
outputPath,
2023-04-21 08:05:27 -05:00
inputFileMutexReleaser: () => {},
2023-04-21 08:05:27 -05:00
resolution: payload.output.resolution,
fps: payload.output.fps
})
2023-04-21 08:05:27 -05:00
const successBody: VODAudioMergeTranscodingSuccess = {
videoFile: outputPath
}
2023-04-21 08:05:27 -05:00
await server.runnerJobs.success({
jobToken: job.jobToken,
jobUUID: job.uuid,
runnerToken,
payload: successBody
})
} finally {
2023-06-22 08:25:39 -05:00
if (audioPath) await remove(audioPath)
if (inputPath) await remove(inputPath)
if (outputPath) await remove(outputPath)
if (updateProgressInterval) clearInterval(updateProgressInterval)
}
2023-04-21 08:05:27 -05:00
}