mirror of
https://github.com/siddharthvaddem/openscreen.git
synced 2026-11-02 04:54:20 +08:00
refactor: extract loadFileAsArrayBuffer to eliminate duplicated file loading
Add a single exported loadFileAsArrayBuffer in streamingDecoder.ts that owns the IPC-vs-fetch branching for local and remote video URLs. StreamingVideoDecoder.loadSourceFile and useAudioPeaks both delegate to it, removing the duplicated readBinaryFile/fetch logic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
a72aa1a594
commit
514943c142
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { loadFileAsArrayBuffer } from "@/lib/exporter/streamingDecoder";
|
||||
|
||||
// Module-level cache keyed by URL — survives re-mounts within the same page session.
|
||||
const peaksCache = new Map<string, Float32Array>();
|
||||
@@ -67,9 +68,7 @@ export function useAudioPeaks(videoUrl?: string): Float32Array | null {
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const response = await fetch(videoUrl);
|
||||
if (cancelled) return;
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const arrayBuffer = await loadFileAsArrayBuffer(videoUrl);
|
||||
if (cancelled) return;
|
||||
const audioBuffer = await getAudioCtx().decodeAudioData(arrayBuffer);
|
||||
if (cancelled) return;
|
||||
|
||||
@@ -137,6 +137,29 @@ export function shouldFailDecodeEndedEarly({
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a video file as an ArrayBuffer, using the Electron IPC bridge for
|
||||
* local paths and falling back to `fetch` for remote / blob / data URLs.
|
||||
* This is the single canonical place for reading raw video bytes in the renderer.
|
||||
*/
|
||||
export async function loadFileAsArrayBuffer(videoUrl: string): Promise<ArrayBuffer> {
|
||||
const isRemoteUrl = /^(https?:|blob:|data:)/i.test(videoUrl);
|
||||
|
||||
if (!isRemoteUrl && window.electronAPI?.readBinaryFile) {
|
||||
const result = await window.electronAPI.readBinaryFile(videoUrl);
|
||||
if (!result.success || !result.data) {
|
||||
throw new Error(result.message ?? result.error ?? "Failed to read video file");
|
||||
}
|
||||
return result.data;
|
||||
}
|
||||
|
||||
const response = await fetch(videoUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch video file: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
return response.arrayBuffer();
|
||||
}
|
||||
|
||||
/** Caller must close the VideoFrame after use. */
|
||||
type OnFrameCallback = (
|
||||
frame: VideoFrame,
|
||||
@@ -158,43 +181,16 @@ export class StreamingVideoDecoder {
|
||||
private metadata: DecodedVideoInfo | null = null;
|
||||
|
||||
private async loadSourceFile(videoUrl: string): Promise<{ file: File; blob: Blob }> {
|
||||
const isRemoteUrl = /^(https?:|blob:|data:)/i.test(videoUrl);
|
||||
|
||||
if (!isRemoteUrl && window.electronAPI?.readBinaryFile) {
|
||||
const result = await this.withTimeout(
|
||||
window.electronAPI.readBinaryFile(videoUrl),
|
||||
SOURCE_LOAD_TIMEOUT_MS,
|
||||
"Timed out while loading the source video.",
|
||||
);
|
||||
if (!result.success || !result.data) {
|
||||
throw new Error(result.message || result.error || "Failed to read source video");
|
||||
}
|
||||
|
||||
const filename = (result.path || videoUrl).split(/[\\/]/).pop() || "video";
|
||||
const blob = new Blob([result.data]);
|
||||
return {
|
||||
blob,
|
||||
file: new File([blob], filename, { type: blob.type || "application/octet-stream" }),
|
||||
};
|
||||
}
|
||||
|
||||
const response = await this.withTimeout(
|
||||
fetch(videoUrl),
|
||||
const buffer = await this.withTimeout(
|
||||
loadFileAsArrayBuffer(videoUrl),
|
||||
SOURCE_LOAD_TIMEOUT_MS,
|
||||
"Timed out while loading the source video.",
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch source video: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const blob = await this.withTimeout(
|
||||
response.blob(),
|
||||
SOURCE_LOAD_TIMEOUT_MS,
|
||||
"Timed out while reading the source video.",
|
||||
);
|
||||
const filename = videoUrl.split("/").pop() || "video";
|
||||
const filename = videoUrl.split(/[\\/]/).pop() || "video";
|
||||
const blob = new Blob([buffer]);
|
||||
return {
|
||||
blob,
|
||||
file: new File([blob], filename, { type: blob.type }),
|
||||
file: new File([blob], filename, { type: blob.type || "application/octet-stream" }),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user