Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 107 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 3x 1x 1x 2x 2x 2x 4x 5x 4x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 4x 1x 1x 3x 4x 4x 5x 5x 3x 3x 3x 5x 5x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 5x 5x 5x | import { Readable, Writable } from 'node:stream'
import { FfmpegInput, InputDefinition } from './input'
import { FfmpegOutput, OutputDefinition } from './output'
import { FfmpegProcess, RunResult, RunOptions, ProcessOptions } from './process'
import { FilterGraph, generateFilterGraph } from './utils/filters'
export type CommandOptions = {
input?: InputDefinition
inputs?: InputDefinition[]
output?: OutputDefinition
outputs?: OutputDefinition[]
complexFilters?: FilterGraph
customArgs?: string[]
}
export class FfmpegCommand implements CommandOptions {
inputs: FfmpegInput[]
outputs: FfmpegOutput[]
complexFilters?: FilterGraph
customArgs: string[]
constructor(options: CommandOptions) {
if (options.input) {
if (options.inputs) {
throw new Error("Cannot specify both 'input' and 'inputs'")
}
options.inputs = [options.input]
}
if (options.output) {
if (options.outputs) {
throw new Error("Cannot specify both 'output' and 'outputs'")
}
options.outputs = [options.output]
}
this.inputs = (options.inputs || []).map(
(inputOptions) => new FfmpegInput(inputOptions)
)
this.outputs = (options.outputs || []).map(
(outputOptions) => new FfmpegOutput(outputOptions)
)
this.complexFilters = options.complexFilters
this.customArgs = options.customArgs || []
this.#validateIO()
}
#validateIO(): void {
if (this.inputs.filter((i) => i.isStream).length > 1) {
throw new Error(`At most one stream input is supported`)
}
if (this.outputs.filter((o) => o.isStream).length > 1) {
throw new Error(`At most one stream output is supported`)
}
}
getFfmpegArguments(): string[] {
let args: string[] = []
for (let input of this.inputs) {
args.push(...input.getFfmpegArguments())
}
args.push(...this.customArgs)
if (this.complexFilters) {
args.push('-filter_complex', generateFilterGraph(this.complexFilters))
}
if (this.outputs.some((o) => o.isLocalFile)) {
// Force overwrite outputs
args.push('-y')
}
for (let output of this.outputs) {
args.push(...output.getFfmpegArguments())
}
return args
}
run(options: RunOptions): Promise<RunResult> {
let procOtions: ProcessOptions = {
args: this.getFfmpegArguments(),
...options
}
let streamInput = this.inputs.find((i) => i.isStream)
if (streamInput) {
procOtions.inputStream = streamInput.source as Readable
}
let streamOutput = this.outputs.find((i) => i.isStream)
if (streamOutput) {
procOtions.outputStream = streamOutput.target as Writable
}
return new FfmpegProcess(procOtions).run()
}
}
|