1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
import { remove } from 'fs-extra/esm'
import { join } from 'path'
import { FFmpegEdition, FFmpegLive, FFmpegVOD, getDefaultAvailableEncoders, getDefaultEncodersToTry } from '@peertube/peertube-ffmpeg'
import { RunnerJob, RunnerJobPayload } from '@peertube/peertube-models'
import { buildUUID } from '@peertube/peertube-node-utils'
import { PeerTubeServer } from '@peertube/peertube-server-commands'
import { ConfigManager, downloadFile, logger } from '../../../shared/index.js'
import { getTranscodingLogger } from './transcoding-logger.js'
export type JobWithToken <T extends RunnerJobPayload = RunnerJobPayload> = RunnerJob<T> & { jobToken: string }
export type ProcessOptions <T extends RunnerJobPayload = RunnerJobPayload> = {
server: PeerTubeServer
job: JobWithToken<T>
runnerToken: string
}
export async function downloadInputFile (options: {
url: string
job: JobWithToken
runnerToken: string
}) {
const { url, job, runnerToken } = options
const destination = join(ConfigManager.Instance.getTranscodingDirectory(), buildUUID())
try {
await downloadFile({ url, jobToken: job.jobToken, runnerToken, destination })
} catch (err) {
remove(destination)
.catch(err => logger.error({ err }, `Cannot remove ${destination}`))
throw err
}
return destination
}
export function scheduleTranscodingProgress (options: {
server: PeerTubeServer
runnerToken: string
job: JobWithToken
progressGetter: () => number
}) {
const { job, server, progressGetter, runnerToken } = options
const updateInterval = ConfigManager.Instance.isTestInstance()
? 500
: 60000
const update = () => {
server.runnerJobs.update({ jobToken: job.jobToken, jobUUID: job.uuid, runnerToken, progress: progressGetter() })
.catch(err => logger.error({ err }, 'Cannot send job progress'))
}
const interval = setInterval(() => {
update()
}, updateInterval)
update()
return interval
}
// ---------------------------------------------------------------------------
export function buildFFmpegVOD (options: {
onJobProgress: (progress: number) => void
}) {
const { onJobProgress } = options
return new FFmpegVOD({
...getCommonFFmpegOptions(),
updateJobProgress: arg => {
const progress = arg < 0 || arg > 100
? undefined
: arg
onJobProgress(progress)
}
})
}
export function buildFFmpegLive () {
return new FFmpegLive(getCommonFFmpegOptions())
}
export function buildFFmpegEdition () {
return new FFmpegEdition(getCommonFFmpegOptions())
}
function getCommonFFmpegOptions () {
const config = ConfigManager.Instance.getConfig()
return {
niceness: config.ffmpeg.nice,
threads: config.ffmpeg.threads,
tmpDirectory: ConfigManager.Instance.getTranscodingDirectory(),
profile: 'default',
availableEncoders: {
available: getDefaultAvailableEncoders(),
encodersToTry: getDefaultEncodersToTry()
},
logger: getTranscodingLogger()
}
}
|