mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-22 17:16:19 -07:00
feat(dictionary): add Hachidori backend support
- Add backend selection, setup gating, Anki integration, and external host support - Add launcher flags, documentation, packaging, and focused tests - Open on-demand overlay modals on the first attempt
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
export function createCaptureFrameEncoder({ WorkerClass = globalThis.Worker,
|
||||
createBitmap = globalThis.createImageBitmap } = {}) {
|
||||
const worker = new WorkerClass(new URL("./capture-frame-worker.js", import.meta.url), {
|
||||
type: "module", name: "hachidori-capture-frames",
|
||||
});
|
||||
let pending = null;
|
||||
let closed = false;
|
||||
const close = (error = new Error("Frame capture stopped.")) => {
|
||||
closed = true;
|
||||
worker.terminate();
|
||||
pending?.reject(error);
|
||||
pending = null;
|
||||
};
|
||||
worker.addEventListener("error", event => {
|
||||
close(event.error ?? new Error(event.message || "The frame encoder stopped."));
|
||||
});
|
||||
worker.addEventListener("message", ({ data }) => {
|
||||
const request = pending;
|
||||
pending = null;
|
||||
if (!request) return;
|
||||
if (data.error) request.reject(new Error(data.error));
|
||||
else request.resolve(data.bytes ? new Uint8Array(data.bytes) : null);
|
||||
});
|
||||
return {
|
||||
async encode(source, dimensions) {
|
||||
if (closed) throw new Error("Frame capture stopped.");
|
||||
// Clone raw VideoFrames without copying pixels; the preview fallback
|
||||
// supplies an ImageBitmap. Only one frame is submitted at a time.
|
||||
const frame = typeof source.clone === "function" ? source.clone() : await createBitmap(source);
|
||||
if (closed || pending) {
|
||||
frame.close();
|
||||
throw new Error(closed ? "Frame capture stopped." : "A capture frame is already being encoded.");
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
pending = { resolve, reject };
|
||||
try { worker.postMessage({ frame, ...dimensions }, [frame]); }
|
||||
catch (error) {
|
||||
pending = null;
|
||||
frame.close();
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
close,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user