web/libav/wrapper: make sure libav is initialized only once
This commit is contained in:
parent
72545ffb5d
commit
4636f7b0d4
1 changed files with 18 additions and 12 deletions
|
@ -3,7 +3,7 @@ import LibAV, { type LibAV as LibAVInstance } from "@imput/libav.js-remux-cli";
|
||||||
import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, FileInfo, RenderParams } from "./types/libav";
|
import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, FileInfo, RenderParams } from "./types/libav";
|
||||||
|
|
||||||
export default class LibAVWrapper {
|
export default class LibAVWrapper {
|
||||||
libav: LibAVInstance | null;
|
libav: Promise<LibAVInstance> | null;
|
||||||
concurrency: number;
|
concurrency: number;
|
||||||
onProgress?: FFmpegProgressCallback;
|
onProgress?: FFmpegProgressCallback;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export default class LibAVWrapper {
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
if (!this.libav) {
|
if (!this.libav) {
|
||||||
this.libav = await LibAV.LibAV({
|
this.libav = LibAV.LibAV({
|
||||||
yesthreads: true,
|
yesthreads: true,
|
||||||
base: '/_libav'
|
base: '/_libav'
|
||||||
});
|
});
|
||||||
|
@ -24,7 +24,7 @@ export default class LibAVWrapper {
|
||||||
|
|
||||||
async render({ blob, output, args }: RenderParams) {
|
async render({ blob, output, args }: RenderParams) {
|
||||||
if (!this.libav) throw new Error("LibAV wasn't initialized");
|
if (!this.libav) throw new Error("LibAV wasn't initialized");
|
||||||
|
const libav = await this.libav;
|
||||||
const inputKind = blob.type.split("/")[0];
|
const inputKind = blob.type.split("/")[0];
|
||||||
const inputExtension = mime.getExtension(blob.type);
|
const inputExtension = mime.getExtension(blob.type);
|
||||||
|
|
||||||
|
@ -43,19 +43,23 @@ export default class LibAVWrapper {
|
||||||
|
|
||||||
const outputName = `output.${output.extension}`;
|
const outputName = `output.${output.extension}`;
|
||||||
|
|
||||||
await this.libav.mkreadaheadfile("input", blob);
|
await libav.mkreadaheadfile("input", blob);
|
||||||
|
|
||||||
// https://github.com/Yahweasel/libav.js/blob/7d359f69/docs/IO.md#block-writer-devices
|
// https://github.com/Yahweasel/libav.js/blob/7d359f69/docs/IO.md#block-writer-devices
|
||||||
await this.libav.mkwriterdev(outputName);
|
await libav.mkwriterdev(outputName);
|
||||||
await this.libav.mkwriterdev('progress.txt');
|
await libav.mkwriterdev('progress.txt');
|
||||||
|
|
||||||
// since we expect the output file to be roughly the same size
|
// since we expect the output file to be roughly the same size
|
||||||
// as the original, preallocate its size for the output
|
// as the original, preallocate its size for the output
|
||||||
let writtenData = new Uint8Array(blob.size), actualSize = 0;
|
let writtenData = new Uint8Array(blob.size), actualSize = 0;
|
||||||
|
|
||||||
this.libav.onwrite = (name, pos, data) => {
|
libav.onwrite = (name, pos, data) => {
|
||||||
if (name === 'progress.txt') {
|
if (name === 'progress.txt') {
|
||||||
|
try {
|
||||||
return this.#emitProgress(data);
|
return this.#emitProgress(data);
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
} else if (name !== outputName) return;
|
} else if (name !== outputName) return;
|
||||||
|
|
||||||
actualSize = Math.max(pos + data.length, actualSize);
|
actualSize = Math.max(pos + data.length, actualSize);
|
||||||
|
@ -68,7 +72,7 @@ export default class LibAVWrapper {
|
||||||
writtenData.set(data, pos);
|
writtenData.set(data, pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.libav.ffmpeg([
|
await libav.ffmpeg([
|
||||||
'-nostdin', '-y',
|
'-nostdin', '-y',
|
||||||
'-loglevel', 'error',
|
'-loglevel', 'error',
|
||||||
'-progress', 'progress.txt',
|
'-progress', 'progress.txt',
|
||||||
|
@ -78,9 +82,9 @@ export default class LibAVWrapper {
|
||||||
outputName
|
outputName
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await this.libav.unlink(outputName);
|
await libav.unlink(outputName);
|
||||||
await this.libav.unlink('progress.txt');
|
await libav.unlink('progress.txt');
|
||||||
await this.libav.unlinkreadaheadfile("input");
|
await libav.unlinkreadaheadfile("input");
|
||||||
|
|
||||||
// if we didn't need as much space as we allocated for some reason,
|
// if we didn't need as much space as we allocated for some reason,
|
||||||
// shrink the buffer so that we don't inflate the file with zeros
|
// shrink the buffer so that we don't inflate the file with zeros
|
||||||
|
@ -98,6 +102,8 @@ export default class LibAVWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#emitProgress(data: Uint8Array | Int8Array) {
|
#emitProgress(data: Uint8Array | Int8Array) {
|
||||||
|
if (!this.onProgress) return;
|
||||||
|
|
||||||
const copy = new Uint8Array(data);
|
const copy = new Uint8Array(data);
|
||||||
const text = new TextDecoder().decode(copy);
|
const text = new TextDecoder().decode(copy);
|
||||||
const entries = Object.fromEntries(
|
const entries = Object.fromEntries(
|
||||||
|
|
Loading…
Reference in a new issue