Files
convert-ui/lib/wasm/wasmLoader.ts
Sebastian Krüger 1771ca42eb feat: initialize Convert UI - browser-based file conversion app
- Add Next.js 16 with Turbopack and React 19
- Add Tailwind CSS 4 with OKLCH color system
- Implement FFmpeg.wasm for video/audio conversion
- Implement ImageMagick WASM for image conversion
- Add file upload with drag-and-drop
- Add format selector with fuzzy search
- Add conversion preview and download
- Add conversion history with localStorage
- Add dark/light theme support
- Support 22+ file formats across video, audio, and images

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 10:44:49 +01:00

144 lines
3.4 KiB
TypeScript

import type { FFmpeg } from '@ffmpeg/ffmpeg';
import type { ConverterEngine, WASMModuleState } from '@/types/conversion';
/**
* WASM module loading state
*/
const moduleState: WASMModuleState = {
ffmpeg: false,
imagemagick: false,
pandoc: false,
};
/**
* Cached WASM instances
*/
let ffmpegInstance: FFmpeg | null = null;
let imagemagickInstance: any = null;
let pandocInstance: any = null;
/**
* Load FFmpeg WASM module
*/
export async function loadFFmpeg(): Promise<FFmpeg> {
if (ffmpegInstance && moduleState.ffmpeg) {
return ffmpegInstance;
}
try {
const { FFmpeg } = await import('@ffmpeg/ffmpeg');
const { toBlobURL } = await import('@ffmpeg/util');
ffmpegInstance = new FFmpeg();
// Load core and dependencies
const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd';
ffmpegInstance.on('log', ({ message }) => {
console.log('[FFmpeg]', message);
});
await ffmpegInstance.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
moduleState.ffmpeg = true;
console.log('FFmpeg loaded successfully');
return ffmpegInstance;
} catch (error) {
console.error('Failed to load FFmpeg:', error);
throw new Error('Failed to load FFmpeg WASM module');
}
}
/**
* Load ImageMagick WASM module
*/
export async function loadImageMagick(): Promise<any> {
if (imagemagickInstance && moduleState.imagemagick) {
return imagemagickInstance;
}
try {
const ImageMagick = await import('@imagemagick/magick-wasm');
imagemagickInstance = ImageMagick;
moduleState.imagemagick = true;
console.log('ImageMagick loaded successfully');
return imagemagickInstance;
} catch (error) {
console.error('Failed to load ImageMagick:', error);
throw new Error('Failed to load ImageMagick WASM module');
}
}
/**
* Load Pandoc WASM module (placeholder for future implementation)
*/
export async function loadPandoc(): Promise<any> {
if (pandocInstance && moduleState.pandoc) {
return pandocInstance;
}
// TODO: Implement Pandoc WASM loading when available
// For now, throw an error
throw new Error('Pandoc WASM module is not yet implemented');
}
/**
* Get loaded module state
*/
export function getModuleState(): WASMModuleState {
return { ...moduleState };
}
/**
* Check if a specific module is loaded
*/
export function isModuleLoaded(engine: ConverterEngine): boolean {
return moduleState[engine];
}
/**
* Load appropriate WASM module for converter engine
*/
export async function loadModule(engine: ConverterEngine): Promise<any> {
switch (engine) {
case 'ffmpeg':
return loadFFmpeg();
case 'imagemagick':
return loadImageMagick();
case 'pandoc':
return loadPandoc();
default:
throw new Error(`Unknown converter engine: ${engine}`);
}
}
/**
* Unload all WASM modules and free memory
*/
export function unloadAll(): void {
if (ffmpegInstance) {
// FFmpeg doesn't have an explicit unload method
// Just null the instance
ffmpegInstance = null;
moduleState.ffmpeg = false;
}
if (imagemagickInstance) {
imagemagickInstance = null;
moduleState.imagemagick = false;
}
if (pandocInstance) {
pandocInstance = null;
moduleState.pandoc = false;
}
console.log('All WASM modules unloaded');
}