148 lines
5.0 KiB
TypeScript
148 lines
5.0 KiB
TypeScript
/**
|
|
* FFmpeg utilities for video concatenation and section-based speed manipulation.
|
|
*
|
|
* Both functions use a single ffmpeg filter_complex pass: trim segments from
|
|
* the input, apply setpts for speed, normalize fps/scale, then concat.
|
|
* No intermediate files, no multi-pass.
|
|
*/
|
|
/** Seconds of normal-speed buffer kept before and after each execution */
|
|
export declare const INTERACTION_BUFFER_SECONDS = 1;
|
|
interface EncoderInfo {
|
|
/** Encoder name for `-c:v`, e.g. "h264_videotoolbox" or "libx264" */
|
|
codec: string;
|
|
/** true when using a hardware encoder */
|
|
isHardware: boolean;
|
|
}
|
|
/**
|
|
* Detect the best available H.264 encoder.
|
|
* Tries platform-specific hardware encoders first, falls back to libx264.
|
|
* Result is cached for the lifetime of the process.
|
|
*/
|
|
export declare function detectEncoder(): Promise<EncoderInfo>;
|
|
export interface InputFile {
|
|
path: string;
|
|
start?: number;
|
|
end?: number;
|
|
}
|
|
export interface ConcatenateOptions {
|
|
inputFiles: InputFile[];
|
|
outputFile: string;
|
|
outputDimensions: {
|
|
width: number;
|
|
height: number;
|
|
};
|
|
frameRate: number;
|
|
signal?: AbortSignal;
|
|
}
|
|
export interface SpeedSection {
|
|
/** Start time in seconds */
|
|
start: number;
|
|
/** End time in seconds */
|
|
end: number;
|
|
/** Speed multiplier, e.g. 2 = 2x faster, 0.5 = 2x slower */
|
|
speed: number;
|
|
}
|
|
export interface SpeedUpSectionsOptions {
|
|
inputFile: string;
|
|
/** Defaults to inputFile with `-fast` suffix before extension */
|
|
outputFile?: string;
|
|
sections: SpeedSection[];
|
|
/** Defaults to input video dimensions (probed via ffprobe) */
|
|
outputDimensions?: {
|
|
width: number;
|
|
height: number;
|
|
};
|
|
/** Defaults to input video frame rate (probed via ffprobe) */
|
|
frameRate?: number;
|
|
signal?: AbortSignal;
|
|
}
|
|
export interface VideoInfo {
|
|
width: number;
|
|
height: number;
|
|
frameRate: number;
|
|
}
|
|
/** Probe input video for dimensions and frame rate via ffprobe. */
|
|
export declare function probeVideo(filePath: string): Promise<VideoInfo>;
|
|
export declare function concatenateVideos(options: ConcatenateOptions): Promise<void>;
|
|
/**
|
|
* Speed up (or slow down) sections of a video by timestamp ranges.
|
|
*
|
|
* Sections not covered by any SpeedSection play at normal speed.
|
|
* Uses a single ffmpeg filter_complex: trim each segment, apply setpts
|
|
* speed, normalize fps/scale, then concat — no intermediate files.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* await speedUpSections({
|
|
* inputFile: 'recording.mp4',
|
|
* sections: [
|
|
* { start: 10, end: 20, speed: 4 }, // 4x between 10s-20s
|
|
* { start: 30, end: 40, speed: 2 }, // 2x between 30s-40s
|
|
* ],
|
|
* })
|
|
* // → outputs recording-fast.mp4
|
|
* ```
|
|
*/
|
|
export declare function speedUpSections(options: SpeedUpSectionsOptions): Promise<string>;
|
|
export interface ExecutionTimestamp {
|
|
/** Start time in seconds relative to recording start */
|
|
start: number;
|
|
/** End time in seconds relative to recording start */
|
|
end: number;
|
|
}
|
|
/**
|
|
* Compute which parts of a recording are "idle" (no execute() calls)
|
|
* and return them as SpeedSections that can be passed to speedUpSections().
|
|
*
|
|
* A buffer of INTERACTION_BUFFER_SECONDS is kept around each execution
|
|
* at normal speed so the viewer sees context before/after each action.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const { executionTimestamps, duration } = await stopRecording()
|
|
* const idleSections = computeIdleSections({
|
|
* executionTimestamps,
|
|
* totalDurationMs: duration,
|
|
* })
|
|
* await speedUpSections({
|
|
* inputFile: recordingPath,
|
|
* sections: idleSections,
|
|
* })
|
|
* ```
|
|
*/
|
|
export declare function computeIdleSections({ executionTimestamps, totalDurationMs, speed, bufferSeconds, }: {
|
|
executionTimestamps: ExecutionTimestamp[];
|
|
/** Total recording duration in milliseconds (from stopRecording result) */
|
|
totalDurationMs: number;
|
|
/** Speed multiplier for idle sections (default 5) */
|
|
speed?: number;
|
|
/** Override the default buffer around each execution (seconds) */
|
|
bufferSeconds?: number;
|
|
}): SpeedSection[];
|
|
export interface CreateDemoVideoOptions {
|
|
/** Path to the raw recording file */
|
|
recordingPath: string;
|
|
/** Total recording duration in milliseconds (from stopRecording result) */
|
|
durationMs: number;
|
|
/** Execution timestamps (from stopRecording result) */
|
|
executionTimestamps: ExecutionTimestamp[];
|
|
/** Speed multiplier for idle sections (default 5) */
|
|
speed?: number;
|
|
/** Output file path (defaults to recordingPath with `-demo` suffix) */
|
|
outputFile?: string;
|
|
signal?: AbortSignal;
|
|
}
|
|
/**
|
|
* Create a demo video from a recording by speeding up idle sections
|
|
* (gaps between execute() calls) while keeping interactions at normal speed.
|
|
*
|
|
* A 1-second buffer (INTERACTION_BUFFER_SECONDS) is preserved around each
|
|
* interaction so viewers see context before and after each action.
|
|
*
|
|
* Requires `ffmpeg` and `ffprobe` installed on the system.
|
|
*
|
|
* @returns The output file path
|
|
*/
|
|
export declare function createDemoVideo(options: CreateDemoVideoOptions): Promise<string>;
|
|
export {};
|
|
//# sourceMappingURL=ffmpeg.d.ts.map
|