diff --git a/lib/media/wasm/wasmLoader.ts b/lib/media/wasm/wasmLoader.ts index 4a9a176..9577396 100644 --- a/lib/media/wasm/wasmLoader.ts +++ b/lib/media/wasm/wasmLoader.ts @@ -15,33 +15,6 @@ const moduleState: WASMModuleState = { let ffmpegInstance: FFmpeg | null = null; let imagemagickInstance: any = null; -/** - * Helper to fetch a file with local priority and CDN fallback - */ -async function fetchWithFallback(localPath: string, cdnUrl: string): Promise { - try { - const response = await fetch(localPath); - if (!response.ok) throw new Error(`Local fetch failed: ${response.status}`); - console.log(`[WASM] Loaded from local: ${localPath}`); - return await response.arrayBuffer(); - } catch (e) { - console.warn(`[WASM] Local load failed for ${localPath}, falling back to CDN:`, e); - const response = await fetch(cdnUrl); - if (!response.ok) throw new Error(`CDN fetch failed: ${response.status}`); - console.log(`[WASM] Loaded from CDN: ${cdnUrl}`); - return await response.arrayBuffer(); - } -} - -/** - * Helper to create a blob URL from a fallback fetch - */ -async function getBlobUrl(localPath: string, cdnUrl: string, mimeType: string): Promise { - const buffer = await fetchWithFallback(localPath, cdnUrl); - const blob = new Blob([buffer], { type: mimeType }); - return URL.createObjectURL(blob); -} - /** * Load FFmpeg WASM module */ @@ -58,20 +31,18 @@ export async function loadFFmpeg(): Promise { console.log('[FFmpeg]', message); }); - const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd'; - - // Load core and dependencies with local priority - const coreURL = await getBlobUrl('/wasm/ffmpeg-core.js', `${baseURL}/ffmpeg-core.js`, 'text/javascript'); - const wasmURL = await getBlobUrl('/wasm/ffmpeg-core.wasm', `${baseURL}/ffmpeg-core.wasm`, 'application/wasm'); + // Files are guaranteed to exist in /wasm/ by the postinstall script + const coreURL = '/wasm/ffmpeg-core.js'; + const wasmURL = '/wasm/ffmpeg-core.wasm'; await ffmpegInstance.load({ coreURL, wasmURL }); moduleState.ffmpeg = true; - console.log('FFmpeg loaded successfully'); + console.log('[FFmpeg] Loaded successfully from local assets'); return ffmpegInstance; } catch (error) { - console.error('Failed to load FFmpeg:', error); + console.error('[FFmpeg] Failed to load:', error); throw new Error('Failed to load FFmpeg WASM module'); } } @@ -87,10 +58,17 @@ export async function loadImageMagick(): Promise { try { const { initializeImageMagick } = await import('@imagemagick/magick-wasm'); - const localWasmUrl = '/wasm/magick.wasm'; - const cdnUrl = 'https://unpkg.com/@imagemagick/magick-wasm@0.0.38/dist/magick.wasm'; + // File is guaranteed to exist in /wasm/ by the postinstall script + const wasmUrl = '/wasm/magick.wasm'; - const arrayBuffer = await fetchWithFallback(localWasmUrl, cdnUrl); + console.log('[ImageMagick] Loading local WASM:', wasmUrl); + + const response = await fetch(wasmUrl); + if (!response.ok) { + throw new Error(`Failed to fetch WASM file: ${response.status} ${response.statusText}`); + } + + const arrayBuffer = await response.arrayBuffer(); console.log('[ImageMagick] WASM file size:', arrayBuffer.byteLength, 'bytes'); await initializeImageMagick(arrayBuffer); @@ -98,7 +76,7 @@ export async function loadImageMagick(): Promise { const ImageMagick = await import('@imagemagick/magick-wasm'); imagemagickInstance = ImageMagick; moduleState.imagemagick = true; - console.log('[ImageMagick] Loaded and initialized successfully'); + console.log('[ImageMagick] Loaded and initialized successfully from local asset'); return imagemagickInstance; } catch (error) { diff --git a/package.json b/package.json index be5d50d..3ba8c26 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,11 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start", - "lint": "eslint ." + "lint": "eslint .", + "postinstall": "mkdir -p public/wasm && cp node_modules/.pnpm/@ffmpeg+core@0.12.6/node_modules/@ffmpeg/core/dist/umd/ffmpeg-core.* public/wasm/ && cp node_modules/.pnpm/@imagemagick+magick-wasm@0.0.38/node_modules/@imagemagick/magick-wasm/dist/magick.wasm public/wasm/" }, "dependencies": { + "@ffmpeg/core": "0.12.6", "@ffmpeg/ffmpeg": "^0.12.15", "@ffmpeg/util": "^0.12.2", "@imagemagick/magick-wasm": "^0.0.38", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 352bbd0..72f71cb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@ffmpeg/core': + specifier: 0.12.6 + version: 0.12.6 '@ffmpeg/ffmpeg': specifier: ^0.12.15 version: 0.12.15 @@ -314,6 +317,10 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ffmpeg/core@0.12.6': + resolution: {integrity: sha512-PrjWBTfGn2WVn9T7wGnzfFwChbqWeZc7tM9vvJZVRadYFUDakfzy7W0LpYC0cvvK0xT82qlBsk38lQhJ/Hps5A==} + engines: {node: '>=16.x'} + '@ffmpeg/ffmpeg@0.12.15': resolution: {integrity: sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==} engines: {node: '>=18.x'} @@ -4223,6 +4230,8 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@ffmpeg/core@0.12.6': {} + '@ffmpeg/ffmpeg@0.12.15': dependencies: '@ffmpeg/types': 0.12.4