109 lines
2.3 KiB
JavaScript

import fs from "node:fs"
import path from "node:path"
import { FFMPEGLib, Utils } from "../FFMPEGLib"
export default class SegmentedAudioMPDJob extends FFMPEGLib {
constructor(params = {}) {
super()
this.params = {
outputMasterName: "master.mpd",
audioCodec: "libopus",
audioBitrate: "320k",
audioSampleRate: "48000",
segmentTime: 10,
includeMetadata: true,
...params,
}
}
buildSegmentationArgs = () => {
const args = [
//`-threads 1`, // limits to one thread
`-v error -hide_banner -progress pipe:1`,
`-i ${this.params.input}`,
`-c:a ${this.params.audioCodec}`,
`-map 0:a`,
`-f dash`,
`-dash_segment_type mp4`,
`-segment_time ${this.params.segmentTime}`,
`-use_template 1`,
`-use_timeline 1`,
`-init_seg_name "init.m4s"`,
]
if (this.params.includeMetadata === false) {
args.push(`-map_metadata -1`)
}
if (
typeof this.params.audioBitrate === "string" &&
this.params.audioBitrate !== "default"
) {
args.push(`-b:a ${this.params.audioBitrate}`)
}
if (
typeof this.params.audioSampleRate !== "undefined" &&
this.params.audioSampleRate !== "default"
) {
args.push(`-ar ${this.params.audioSampleRate}`)
}
args.push(this.params.outputMasterName)
return args
}
run = async () => {
const segmentationCmd = this.buildSegmentationArgs()
const outputPath =
this.params.outputDir ?? `${path.dirname(this.params.input)}/dash`
const outputFile = path.join(outputPath, this.params.outputMasterName)
this.emit("start", {
input: this.params.input,
output: outputPath,
params: this.params,
})
if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath, { recursive: true })
}
const inputProbe = await Utils.probe(this.params.input)
try {
const result = await this.ffmpeg({
args: segmentationCmd,
onProcess: (process) => {
this.handleProgress(
process.stdout,
parseFloat(inputProbe.format.duration),
(progress) => {
this.emit("progress", progress)
},
)
},
cwd: outputPath,
})
let outputProbe = await Utils.probe(outputFile)
this.emit("end", {
probe: {
input: inputProbe,
output: outputProbe,
},
outputPath: outputPath,
outputFile: outputFile,
})
return result
} catch (err) {
return this.emit("error", err)
}
}
}