mirror of https://github.com/mifi/lossless-cut
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.9 KiB
TypeScript
107 lines
2.9 KiB
TypeScript
|
2 years ago
|
import assert from 'assert';
|
||
|
3 years ago
|
|
||
|
2 years ago
|
import logger from './logger.js';
|
||
|
|
import { createMediaSourceProcess, readOneJpegFrame as readOneJpegFrameRaw } from './ffmpeg.js';
|
||
|
3 years ago
|
|
||
|
2 years ago
|
|
||
|
|
export function createMediaSourceStream({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps }: {
|
||
|
|
path: string, videoStreamIndex?: number | undefined, audioStreamIndex?: number | undefined, seekTo: number, size?: number | undefined, fps?: number | undefined,
|
||
|
|
}) {
|
||
|
3 years ago
|
const abortController = new AbortController();
|
||
|
|
logger.info('Starting preview process', { videoStreamIndex, audioStreamIndex, seekTo });
|
||
|
|
const process = createMediaSourceProcess({ path, videoStreamIndex, audioStreamIndex, seekTo, size, fps });
|
||
|
3 years ago
|
|
||
|
2 years ago
|
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
||
|
3 years ago
|
abortController.signal.onabort = () => {
|
||
|
|
logger.info('Aborting preview process', { videoStreamIndex, audioStreamIndex, seekTo });
|
||
|
|
process.kill('SIGKILL');
|
||
|
|
};
|
||
|
3 years ago
|
|
||
|
2 years ago
|
const { stdout } = process;
|
||
|
|
assert(stdout != null);
|
||
|
|
|
||
|
|
stdout.pause();
|
||
|
|
|
||
|
|
const readChunk = async () => new Promise((resolve, reject) => {
|
||
|
|
let cleanup: () => void;
|
||
|
|
|
||
|
|
const onClose = () => {
|
||
|
|
cleanup();
|
||
|
|
resolve(null);
|
||
|
|
};
|
||
|
|
const onData = (chunk: Buffer) => {
|
||
|
|
stdout.pause();
|
||
|
|
cleanup();
|
||
|
|
resolve(chunk);
|
||
|
|
};
|
||
|
|
const onError = (err: Error) => {
|
||
|
|
cleanup();
|
||
|
|
reject(err);
|
||
|
|
};
|
||
|
|
cleanup = () => {
|
||
|
|
stdout.off('data', onData);
|
||
|
|
stdout.off('error', onError);
|
||
|
|
stdout.off('close', onClose);
|
||
|
|
};
|
||
|
|
|
||
|
|
stdout.once('data', onData);
|
||
|
|
stdout.once('error', onError);
|
||
|
|
stdout.once('close', onClose);
|
||
|
|
|
||
|
|
stdout.resume();
|
||
|
|
});
|
||
|
3 years ago
|
|
||
|
|
function abort() {
|
||
|
3 years ago
|
abortController.abort();
|
||
|
3 years ago
|
}
|
||
|
|
|
||
|
3 years ago
|
let stderr = Buffer.alloc(0);
|
||
|
|
process.stderr?.on('data', (chunk) => {
|
||
|
|
stderr = Buffer.concat([stderr, chunk]);
|
||
|
|
});
|
||
|
3 years ago
|
|
||
|
3 years ago
|
(async () => {
|
||
|
|
try {
|
||
|
|
await process;
|
||
|
|
} catch (err) {
|
||
|
|
if (err instanceof Error && err.name === 'AbortError') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
3 years ago
|
|
||
|
2 years ago
|
// @ts-expect-error todo
|
||
|
|
if (!(err.killed)) {
|
||
|
|
// @ts-expect-error todo
|
||
|
3 years ago
|
console.warn(err.message);
|
||
|
2 years ago
|
console.warn(stderr.toString('utf8'));
|
||
|
3 years ago
|
}
|
||
|
|
}
|
||
|
3 years ago
|
})();
|
||
|
|
|
||
|
|
return { abort, readChunk };
|
||
|
3 years ago
|
}
|
||
|
|
|
||
|
2 years ago
|
export function readOneJpegFrame({ path, seekTo, videoStreamIndex }: { path: string, seekTo: number, videoStreamIndex: number }) {
|
||
|
3 years ago
|
const abortController = new AbortController();
|
||
|
2 years ago
|
const process = readOneJpegFrameRaw({ path, seekTo, videoStreamIndex });
|
||
|
3 years ago
|
|
||
|
2 years ago
|
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
||
|
3 years ago
|
abortController.signal.onabort = () => process.kill('SIGKILL');
|
||
|
|
|
||
|
|
function abort() {
|
||
|
|
abortController.abort();
|
||
|
|
}
|
||
|
|
|
||
|
|
const promise = (async () => {
|
||
|
|
try {
|
||
|
|
const { stdout } = await process;
|
||
|
|
return stdout;
|
||
|
|
} catch (err) {
|
||
|
2 years ago
|
// @ts-expect-error todo
|
||
|
3 years ago
|
logger.error('renderOneJpegFrame', err.shortMessage);
|
||
|
|
throw new Error('Failed to render JPEG frame');
|
||
|
|
}
|
||
|
|
})();
|
||
|
|
|
||
|
|
return { promise, abort };
|
||
|
3 years ago
|
}
|