From f93d84c457ad6936d417fc93790c1aa29894df2c Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Tue, 13 Aug 2024 15:33:30 +0000 Subject: [PATCH] web/libav: add ffprobe wrapper --- pnpm-lock.yaml | 10 ++++++++++ web/package.json | 1 + web/src/lib/libav.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a61bd324..84a135e4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -131,6 +131,9 @@ importers: '@types/eslint__js': specifier: ^8.42.3 version: 8.42.3 + '@types/fluent-ffmpeg': + specifier: ^2.1.25 + version: 2.1.25 '@types/node': specifier: ^20.14.10 version: 20.14.14 @@ -695,6 +698,9 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/fluent-ffmpeg@2.1.25': + resolution: {integrity: sha512-a9/Jtv/RVaCG4lUwWIcuClWE5eXJFoFS/oHOecOv/RS8n+lQdJzcJVmDlxA8Xbk4B82YpO88Dijcoljb6sYTcA==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -2634,6 +2640,10 @@ snapshots: '@types/estree@1.0.5': {} + '@types/fluent-ffmpeg@2.1.25': + dependencies: + '@types/node': 20.14.14 + '@types/json-schema@7.0.15': {} '@types/node@10.17.60': {} diff --git a/web/package.json b/web/package.json index 19fa7c17..c9454818 100644 --- a/web/package.json +++ b/web/package.json @@ -30,6 +30,7 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "@types/eslint__js": "^8.42.3", + "@types/fluent-ffmpeg": "^2.1.25", "@types/node": "^20.14.10", "compare-versions": "^6.1.0", "eslint": "^8.57.0", diff --git a/web/src/lib/libav.ts b/web/src/lib/libav.ts index d24e1847..ff68c267 100644 --- a/web/src/lib/libav.ts +++ b/web/src/lib/libav.ts @@ -1,6 +1,7 @@ import mime from "mime"; import LibAV, { type LibAV as LibAVInstance } from "@imput/libav.js-remux-cli"; import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, FileInfo, RenderParams } from "./types/libav"; +import type { FfprobeData } from "fluent-ffmpeg"; export default class LibAVWrapper { libav: Promise | null; @@ -22,6 +23,45 @@ export default class LibAVWrapper { } } + async probe(blob: Blob) { + if (!this.libav) throw new Error("LibAV wasn't initialized"); + const libav = await this.libav; + + const OUT_FILE = 'output.json'; + await libav.mkreadaheadfile('input', blob); + await libav.mkwriterdev(OUT_FILE); + + let writtenData = new Uint8Array(0); + + libav.onwrite = (name, pos, data) => { + if (name !== OUT_FILE) return; + + const newLen = Math.max(pos + data.length, writtenData.length); + if (newLen > writtenData.length) { + const newData = new Uint8Array(newLen); + newData.set(writtenData); + writtenData = newData; + } + writtenData.set(data, pos); + }; + + await libav.ffprobe([ + '-v', 'quiet', + '-print_format', 'json', + '-show_format', + '-show_streams', + 'input', + '-o', OUT_FILE + ]); + + await libav.unlink(OUT_FILE); + await libav.unlinkreadaheadfile('input'); + + const copy = new Uint8Array(writtenData); + const text = new TextDecoder().decode(copy); + return JSON.parse(text) as FfprobeData; + } + async render({ blob, output, args }: RenderParams) { if (!this.libav) throw new Error("LibAV wasn't initialized"); const libav = await this.libav;