{"version":3,"sources":["../src/hooks/useSTT.ts","../src/audio/recorder.ts","../src/adapters/baseAdapter.ts","../src/utils/audioConverter.ts","../src/adapters/whisperAdapter.ts","../src/hooks/useFFmpeg.ts"],"sourcesContent":["import { useState, useCallback, useRef, useEffect } from 'react';\nimport { STTOptions, STTResult } from '../types';\nimport { BaseError } from '../adapters/baseAdapter';\nimport { WhisperAdapter } from '../adapters/whisperAdapter';\nimport { useFFmpeg } from './useFFmpeg';\n\ninterface UseSTTResult {\n  transcript: string;\n  isRecording: boolean;\n  isProcessing: boolean;\n  error: Error | null;\n  isInitialized: boolean;\n  isStopping: boolean;\n  startRecording: () => Promise<void>;\n  stopRecording: () => Promise<void>;\n  pauseRecording: () => void;\n  resumeRecording: () => void;\n}\n\nconst isDev = process.env.NODE_ENV === 'development';\n\nexport function useSTT(options: STTOptions): UseSTTResult {\n  const { disabled = false } = options;\n  const [isRecording, setIsRecording] = useState(false);\n  const [isProcessing, setIsProcessing] = useState(false);\n  const [transcript, setTranscript] = useState('');\n  const [error, setError] = useState<Error | null>(null);\n  const [isInitialized, setIsInitialized] = useState(false);\n  const [isStopping, setIsStopping] = useState(false);\n  const adapterRef = useRef<WhisperAdapter | null>(null);\n  const optionsRef = useRef(options);\n\n  useEffect(() => {\n    optionsRef.current = options;\n  }, [options]);\n\n  const { ffmpeg, loaded, loading, error: ffmpegError, load: loadFFmpeg } = useFFmpeg();\n\n  useEffect(() => {\n    if (disabled) {\n      if (isDev) console.log('useSTT is disabled. Cleaning up adapter.');\n      if (adapterRef.current) {\n        adapterRef.current.abort();\n        adapterRef.current = null;\n      }\n      setIsRecording(false);\n      setIsStopping(false);\n      setIsInitialized(false);\n    } else if (loaded && ffmpeg && !adapterRef.current && !isInitialized) {\n      if (isDev) console.log('useSTT is re-enabled. Will attempt to initialize adapter if not already initializing.');\n    }\n  }, [disabled, loaded, ffmpeg, isInitialized]);\n\n  useEffect(() => {\n    let isMounted = true;\n\n    const initializeAdapter = async () => {\n      if (disabled || !loaded || !ffmpeg) {\n        if (ffmpegError && isMounted && !disabled) {\n          setError(ffmpegError);\n        }\n        return;\n      }\n\n      if (adapterRef.current && isInitialized) return;\n      \n      if (isDev) console.log('useSTT: Initializing adapter.');\n      try {\n        console.log('Creating new WhisperAdapter instance');\n        const adapter = new WhisperAdapter({\n          ...optionsRef.current,\n          ffmpeg,\n          onResult: (result: STTResult) => {\n            if (!isMounted || optionsRef.current.disabled) return;\n            setTranscript(result.transcript);\n            if (result.isFinal) {\n              setIsProcessing(false);\n            }\n          },\n          onError: (err: Error) => {\n            if (!isMounted || optionsRef.current.disabled) return;\n            setError(err);\n            setIsProcessing(false);\n            setIsRecording(false);\n          },\n          onStart: () => {\n            if (!isMounted || optionsRef.current.disabled) return;\n            setError(null);\n            setIsRecording(true);\n            setIsProcessing(true);\n          },\n          onEnd: () => {\n            if (!isMounted || optionsRef.current.disabled) return;\n            setIsRecording(false);\n            setIsStopping(false);\n          }\n        });\n\n        adapterRef.current = adapter;\n        if (isMounted) {\n          setIsInitialized(true);\n          setError(null);\n        }\n      } catch (err) {\n        console.error('Error initializing adapter:', err);\n        if (isMounted && !optionsRef.current.disabled) {\n          setError(err instanceof Error ? err : new BaseError('Failed to initialize adapter'));\n          setIsInitialized(false);\n        }\n      }\n    };\n\n    initializeAdapter();\n\n    return () => {\n      isMounted = false;\n      if (adapterRef.current && !optionsRef.current.disabled) {\n         if (isDev) console.log('useSTT: Unmounting, aborting adapter.');\n        adapterRef.current.abort();\n        adapterRef.current = null;\n      } else if (adapterRef.current && optionsRef.current.disabled) {\n        adapterRef.current = null;\n      }\n    };\n  }, [loaded, ffmpeg, ffmpegError, disabled, isInitialized]);\n\n  useEffect(() => {\n    if (disabled) {\n        if (isDev) console.log('useSTT is disabled. FFmpeg load call skipped.');\n      return;\n    }\n    if (!loaded && !loading && !ffmpegError) {\n        if (isDev) console.log('useSTT: loadFFmpeg called.');\n        loadFFmpeg();\n    }\n  }, [loadFFmpeg, disabled, loaded, loading, ffmpegError]);\n\n  const startRecording = useCallback(async () => {\n    // Priority 1: Check if disabled\n    if (optionsRef.current.disabled) {\n      if (isDev) console.log('useSTT: startRecording aborted (STT is disabled).');\n      throw new Error('STT is disabled.');\n    }\n\n    // Priority 2: Check for FFmpeg loading errors directly\n    // This error should be surfaced regardless of initialization state if an attempt to record is made.\n    if (ffmpegError) {\n        if (isDev) console.log('useSTT: startRecording aborted (FFmpeg error).');\n        throw ffmpegError; \n    }\n    \n    // Priority 3: Check if FFmpeg is actually loaded (should be redundant if ffmpegError is null, but good safeguard)\n    if (!loaded || !ffmpeg) {\n        if (isDev) console.log('useSTT: startRecording aborted (FFmpeg not loaded).');\n        throw new Error('FFmpeg not loaded');\n    }\n\n    // Priority 4: Check if adapter is initialized\n    if (!isInitialized || !adapterRef.current) {\n      if (isDev) console.log('useSTT: startRecording aborted (adapter not initialized or no adapter).');\n      throw new Error('STT adapter not initialized.');\n    }\n\n    // If all checks pass, proceed with starting the adapter\n    try {\n      await adapterRef.current.start();\n    } catch (err) {\n      // Error during adapter.start() call\n      if (!optionsRef.current.disabled) { // Only set component error state if not disabled\n        setIsRecording(false);\n        setIsProcessing(false);\n        setError(err instanceof Error ? err : new BaseError('Failed to start recording'));\n      }\n      throw err; // Re-throw to allow parent to catch\n    }\n  }, [loaded, ffmpeg, ffmpegError, isInitialized]); // optionsRef.current.disabled is checked inside\n\n  const stopRecording = useCallback(async () => {\n    if (!adapterRef.current) {\n      if (isDev) console.log('useSTT: stopRecording aborted (no adapter).');\n      return;\n    }\n    if (isDev) console.log('useSTT: stopRecording called.');\n    try {\n      setIsStopping(true);\n      await adapterRef.current.stop();\n      if (optionsRef.current.disabled) {\n        setIsStopping(false);\n        setIsRecording(false);\n        setIsProcessing(false);\n      }\n    } catch (err) {\n      if (!optionsRef.current.disabled) {\n        setError(err instanceof Error ? err : new BaseError('Failed to stop recording'));\n      }\n       setIsStopping(false);\n       setIsProcessing(false);\n      throw err;\n    }\n  }, []);\n\n  const pauseRecording = useCallback(() => {\n    if (optionsRef.current.disabled || !adapterRef.current) {\n      if (isDev) console.log('useSTT: pauseRecording aborted (disabled or no adapter).');\n      return;\n    }\n    if (isDev) console.log('useSTT: pauseRecording called.');\n    adapterRef.current.pause();\n  }, []);\n\n  const resumeRecording = useCallback(() => {\n    if (optionsRef.current.disabled || !adapterRef.current) {\n      if (isDev) console.log('useSTT: resumeRecording aborted (disabled or no adapter).');\n      return;\n    }\n    if (isDev) console.log('useSTT: resumeRecording called.');\n    adapterRef.current.resume();\n  }, []);\n\n  return {\n    transcript,\n    isRecording,\n    isProcessing: isProcessing || loading,\n    error: error || ffmpegError,\n    isInitialized,\n    isStopping,\n    startRecording,\n    stopRecording,\n    pauseRecording,\n    resumeRecording,\n  };\n}\n","export interface AudioRecorderOptions {\n  onDataAvailable?: (data: Blob) => void;\n  onError?: (error: Error) => void;\n  mimeType?: string;\n}\n\nexport class AudioRecorder {\n  private mediaRecorder: MediaRecorder | null = null;\n  private stream: MediaStream | null = null;\n  private options: AudioRecorderOptions;\n\n  constructor(options: AudioRecorderOptions) {\n    this.options = options;\n  }\n\n  private getSupportedMimeType(): string {\n    const mimeTypes = [\n      'audio/webm',\n      'audio/mp4',\n      'audio/ogg',\n      'audio/wav'\n    ];\n\n    if (this.options.mimeType && MediaRecorder.isTypeSupported(this.options.mimeType)) {\n      return this.options.mimeType;\n    }\n\n    const supportedType = mimeTypes.find(type => MediaRecorder.isTypeSupported(type));\n    if (!supportedType) {\n      throw new Error('No supported audio MIME types found');\n    }\n\n    return supportedType;\n  }\n\n  async start(): Promise<void> {\n    try {\n      if (this.mediaRecorder?.state === 'recording') {\n        throw new Error('Recording already in progress');\n      }\n\n      const stream = await navigator.mediaDevices.getUserMedia({ \n        audio: {\n          channelCount: 1,\n          sampleRate: 16000,\n          echoCancellation: true,\n          noiseSuppression: true,\n          autoGainControl: true\n        } \n      });\n\n      const mimeType = this.getSupportedMimeType();\n      console.log('Creating MediaRecorder with options:', {\n        mimeType,\n        platform: typeof window !== 'undefined' ? window.navigator.platform : 'unknown',\n        userAgent: typeof window !== 'undefined' ? window.navigator.userAgent : 'unknown'\n      });\n\n      this.stream = stream;\n      this.mediaRecorder = new MediaRecorder(stream, { mimeType });\n      \n      this.mediaRecorder.ondataavailable = (event) => {\n        if (event.data.size > 0 && this.options.onDataAvailable) {\n          console.log('MediaRecorder data available:', {\n            size: event.data.size,\n            type: event.data.type\n          });\n          this.options.onDataAvailable(event.data);\n        }\n      };\n\n      this.mediaRecorder.onerror = (event) => {\n        const error = event.error || new Error('MediaRecorder error');\n        if (this.options.onError) {\n          this.options.onError(error);\n        }\n      };\n\n      this.mediaRecorder.start();\n      console.log('MediaRecorder started');\n    } catch (error) {\n      console.error('Error starting MediaRecorder:', error);\n      if (this.options.onError) {\n        this.options.onError(error as Error);\n      }\n      throw error;\n    }\n  }\n\n  async stop(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      if (!this.mediaRecorder) {\n        reject(new Error('MediaRecorder not initialized'));\n        return;\n      }\n\n      console.log('Stopping MediaRecorder');\n      \n      const handleStop = () => {\n        this.cleanup();\n        resolve();\n      };\n\n      const handleError = (event: Event) => {\n        this.cleanup();\n        reject(new Error('MediaRecorder error'));\n      };\n\n      this.mediaRecorder.onstop = handleStop;\n      this.mediaRecorder.onerror = handleError;\n      \n      this.mediaRecorder.stop();\n    });\n  }\n\n  pause(): void {\n    if (this.mediaRecorder?.state === 'recording') {\n      this.mediaRecorder.pause();\n    }\n  }\n\n  resume(): void {\n    if (this.mediaRecorder?.state === 'paused') {\n      this.mediaRecorder.resume();\n    }\n  }\n\n  private cleanup(): void {\n    if (this.stream) {\n      this.stream.getTracks().forEach(track => track.stop());\n      this.stream = null;\n    }\n    this.mediaRecorder = null;\n  }\n} ","import { STTOptions, STTResult } from '../types';\nimport { AudioRecorder } from '../audio/recorder';\n\nexport class BaseError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'BaseError';\n  }\n}\n\nexport abstract class BaseAdapter {\n  protected options: STTOptions;\n  protected recorder: AudioRecorder | null = null;\n  \n  // Callbacks\n  protected resultCallback?: (result: STTResult) => void;\n  protected errorCallback?: (error: Error) => void;\n  protected startCallback?: () => void;\n  protected endCallback?: () => void;\n  \n  constructor(options: STTOptions) {\n    console.log('Initializing BaseAdapter');\n    this.options = options;\n    // Initialize callbacks from options\n    if (options.onResult) this.resultCallback = options.onResult;\n    if (options.onError) this.errorCallback = options.onError;\n    if (options.onStart) this.startCallback = options.onStart;\n    if (options.onEnd) this.endCallback = options.onEnd;\n  }\n\n  protected handleError(error: unknown) {\n    const err = error instanceof Error ? error : new BaseError('Unknown error');\n    // Call error callback first to set error state\n    this.errorCallback?.(err);\n    // Then call end callback to reset processing/recording states\n    this.endCallback?.();\n    // Clean up recorder if it exists\n    if (this.recorder) {\n      this.recorder.stop().catch(console.error);\n      this.recorder = null;\n    }\n    throw err; // Re-throw to propagate to caller\n  }\n\n  // Core method that derived classes must implement - this is where provider-specific logic goes\n  protected abstract processAudio(audioBlob: Blob): Promise<STTResult>;\n  \n  async start(): Promise<void> {\n    try {      \n      console.log('Starting adapter...');\n      \n      // Initialize recorder first\n      this.recorder = new AudioRecorder({\n        mimeType: 'audio/webm',\n        onDataAvailable: async (data) => {\n          try {\n            console.log('Processing complete recording:', {\n              size: data.size,\n              type: data.type\n            });\n            const result = await this.processAudio(data);\n            this.resultCallback?.(result);\n            this.endCallback?.(); // Call end callback after successful processing\n          } catch (error) {\n            console.error('Error processing audio:', error);\n            this.handleError(error);\n          }\n        },\n        onError: (error) => this.handleError(error)\n      });\n\n      // Call startCallback before starting recording to ensure state is set\n      this.startCallback?.();\n\n      // Wait for the recorder to start before proceeding\n      await this.recorder.start();\n    } catch (error) {\n      console.error('Error in start():', error);\n      this.handleError(error);\n    }\n  }\n\n  async stop(): Promise<void> {\n    try {\n      if (!this.recorder) return;\n      console.log('Stopping recording...');\n      const currentRecorder = this.recorder;\n      await currentRecorder.stop();\n      this.recorder = null;\n    } catch (error) {\n      console.error('Error in stop():', error);\n      this.handleError(error);\n    }\n  }\n\n  pause(): void {\n    if (this.recorder) {\n      this.recorder.pause();\n    }\n  }\n\n  resume(): void {\n    if (this.recorder) {\n      this.recorder.resume();\n    }\n  }\n\n  async abort(): Promise<void> {\n    console.log('Cleaning up adapter...');\n    if (this.recorder) {\n      try {\n        await this.recorder.stop();\n        this.recorder = null;\n      } catch (error) {\n        console.error('Error in abort():', error);\n      }\n    }\n  }\n\n  // Callback setters\n  onResult(callback: (result: STTResult) => void): void {\n    this.resultCallback = callback;\n  }\n\n  onError(callback: (error: Error) => void): void {\n    this.errorCallback = callback;\n  }\n\n  onStart(callback: () => void): void {\n    this.startCallback = callback;\n  }\n\n  onEnd(callback: () => void): void {\n    this.endCallback = callback;\n  }\n}\n","import { FFmpeg } from '@ffmpeg/ffmpeg';\nimport { fetchFile } from '@ffmpeg/util';\nimport type { FFmpegConfig, AudioMetadata } from '../types';\n\nconst SUPPORTED_INPUT_FORMATS = [\n  'audio/webm',\n  'audio/mp4',\n  'audio/wav',\n  'audio/ogg',\n  'audio/mpeg'\n];\n\nfunction validateAudioFormat(blob: Blob) {\n  // Extract main MIME type without codecs\n  const mainType = blob.type.split(';')[0];\n  if (!SUPPORTED_INPUT_FORMATS.includes(mainType)) {\n    throw new Error(`Unsupported audio format: ${blob.type}. Supported formats are: ${SUPPORTED_INPUT_FORMATS.join(', ')}`);\n  }\n}\n\nexport async function convertAudioToWebM(ffmpeg: FFmpeg, file: File | Blob, config: FFmpegConfig = {}): Promise<Blob> {\n  console.log('Starting audio conversion to WebM...', {\n    fileType: file.type,\n    fileSize: file.size,\n    config\n  });\n  validateAudioFormat(file);\n  \n  try {\n    console.log('Writing input file...');\n    const fileData = await fetchFile(file);\n    await ffmpeg.writeFile('input', fileData);\n    console.log('Input file written successfully');\n\n    console.log('Converting to WebM...');\n    const args = [\n      '-i', 'input',\n      '-ar', `${config.outputSampleRate || 16000}`,  // Sample rate\n      '-ac', `${config.outputChannels || 1}`,        // Channels\n    ];\n\n    // Add filters\n    const filters: string[] = [];\n    \n    // Noise reduction if requested\n    if (config.denoise) {\n      filters.push('anlmdn'); // Noise reduction filter\n    }\n\n    // Normalization if requested\n    if (config.normalize) {\n      filters.push(`loudnorm=I=${config.normalizationLevel || -16}`);\n    }\n\n    // Voice Activity Detection if requested\n    if (config.vad) {\n      filters.push(`silenceremove=start_periods=1:start_duration=1:start_threshold=${config.vadLevel || 1}:detection=peak`);\n    }\n\n    // Add any custom filters\n    if (config.filters && config.filters.length > 0) {\n      filters.push(...config.filters);\n    }\n\n    // Apply all filters if any\n    if (filters.length > 0) {\n      args.push('-af', filters.join(','));\n    }\n\n    // Add codec and compression settings\n    args.push(\n      '-c:a', 'libopus',\n      '-b:a', config.bitrate || '24k',\n      '-compression_level', `${config.compressionLevel || 10}`\n    );\n\n    args.push('output.webm');\n    \n    console.log('FFmpeg conversion args:', args);\n    await ffmpeg.exec(args);\n    console.log('FFmpeg conversion completed');\n\n    const data = await ffmpeg.readFile('output.webm');\n    \n    // Clean up\n    await ffmpeg.deleteFile('input');\n    await ffmpeg.deleteFile('output.webm');\n\n    const blob = new Blob([data], { type: 'audio/webm;codecs=opus' });\n    console.log('Conversion complete:', {\n      inputSize: file.size,\n      outputSize: blob.size,\n      outputType: blob.type,\n      appliedFilters: filters\n    });\n    return blob;\n  } catch (error) {\n    console.error('Audio conversion failed:', {\n      error,\n      message: error instanceof Error ? error.message : 'Unknown error',\n      stack: error instanceof Error ? error.stack : undefined\n    });\n    throw error;\n  }\n}\n\n// Keep the original convertAudioToMono as a fallback\nexport async function convertAudioToMono(ffmpeg: FFmpeg, file: File | Blob): Promise<Blob> {\n  return convertAudioToWebM(ffmpeg, file);\n}\n\nexport async function convertWithFFmpeg(\n  ffmpeg: FFmpeg,\n  file: File | Blob, \n  config: FFmpegConfig = {}\n): Promise<Blob> {\n  console.log('Starting FFmpeg conversion with config:', config);\n  \n  try {\n    // Write input file\n    console.log('Writing input file...');\n    await ffmpeg.writeFile('input', await fetchFile(file));\n\n    // Build FFmpeg arguments\n    const args = [\n      '-i', 'input',\n      '-ar', `${config.outputSampleRate || 16000}`,\n      '-ac', `${config.outputChannels || 1}`,\n    ];\n\n    // Add normalization if requested\n    if (config.normalize) {\n      args.push('-filter:a', 'loudnorm');\n    }\n\n    // Add codec\n    args.push('-c:a', config.codec || 'pcm_s16le');\n\n    // Add output file\n    const outputFile = `output.${config.outputFormat || 'wav'}`;\n    args.push(outputFile);\n\n    // Execute FFmpeg command\n    console.log('Executing FFmpeg command with args:', args);\n    await ffmpeg.exec(args);\n\n    // Read the output file\n    console.log('Reading converted file...');\n    const data = await ffmpeg.readFile(outputFile);\n    \n    // Clean up\n    console.log('Cleaning up...');\n    await ffmpeg.deleteFile('input');\n    await ffmpeg.deleteFile(outputFile);\n\n    // Convert to Blob\n    const blob = new Blob([data], { \n      type: `audio/${config.outputFormat || 'wav'}`\n    });\n    console.log('Conversion complete. Output size:', blob.size);\n    return blob;\n  } catch (error) {\n    console.error('FFmpeg conversion error:', error);\n    throw new Error('Audio conversion failed: ' + (error instanceof Error ? error.message : 'Unknown error'));\n  }\n}\n\nexport async function getAudioMetadata(ffmpeg: FFmpeg, file: File | Blob): Promise<AudioMetadata> {\n  console.log('Getting audio metadata...');\n  \n  try {\n    // Write input file\n    console.log('Writing input file...');\n    await ffmpeg.writeFile('input', await fetchFile(file));\n\n    // Get file information using FFprobe\n    console.log('Getting file information...');\n    await ffmpeg.exec([\n      '-i', 'input',\n      '-f', 'null', '-'\n    ]);\n\n    // Clean up\n    console.log('Cleaning up...');\n    await ffmpeg.deleteFile('input');\n\n    // Parse FFprobe output (this is a simplified example)\n    // In reality, you'd want to parse the FFprobe output more carefully\n    const metadata = {\n      duration: 0, // You'd get this from FFprobe output\n      sampleRate: 16000,\n      channels: 1,\n      format: file.type as any,\n      size: file.size\n    };\n    console.log('Metadata extracted:', metadata);\n    return metadata;\n  } catch (error) {\n    console.error('FFmpeg metadata error:', error);\n    throw new Error('Failed to get audio metadata: ' + (error instanceof Error ? error.message : 'Unknown error'));\n  }\n} ","import { BaseAdapter, BaseError } from './baseAdapter';\nimport { STTOptions, STTResult } from '../types';\nimport { convertAudioToMono } from '../utils/audioConverter';\nimport { FFmpeg } from '@ffmpeg/ffmpeg';\n\ninterface WhisperAdapterOptions extends STTOptions {\n  ffmpeg: FFmpeg;\n  onResult?: (result: STTResult) => void;\n  onError?: (error: Error) => void;\n  onStart?: () => void;\n  onEnd?: () => void;\n}\n\nexport class WhisperAdapter extends BaseAdapter {\n  private ffmpeg: FFmpeg;\n\n  constructor(options: WhisperAdapterOptions) {\n    super(options);\n    console.log('Initializing WhisperAdapter');\n    this.ffmpeg = options.ffmpeg;\n  }\n\n  protected async processAudio(audioBlob: Blob): Promise<STTResult> {\n    try {\n      if (audioBlob.size === 0) {\n        return {\n          transcript: '',\n          isFinal: true,\n          confidence: 1\n        };\n      }\n\n      // Check if we already have WebM format\n      const isWebM = audioBlob.type.includes('webm');\n      \n      let processedBlob = audioBlob;\n      if (!isWebM) {\n        // Convert non-WebM formats to WebM with Opus codec\n        console.log('Converting audio to WebM format...', {\n          originalFormat: audioBlob.type,\n          originalSize: audioBlob.size\n        });\n        processedBlob = await convertAudioToMono(this.ffmpeg, audioBlob);\n        console.log('Conversion complete:', {\n          newFormat: processedBlob.type,\n          newSize: processedBlob.size\n        });\n      } else {\n        console.log('Audio already in WebM format, skipping conversion:', {\n          format: audioBlob.type,\n          size: audioBlob.size\n        });\n      }\n\n      console.log('Processing audio with transcribe function...');\n      const result = await this.options.transcribe(processedBlob);\n      \n      return {\n        transcript: result.transcript,\n        isFinal: true,\n        confidence: result.confidence ?? 0.95\n      };\n    } catch (error) {\n      console.error('Error in processAudio:', error);\n      const baseError = new BaseError(error instanceof Error ? error.message : 'Transcription failed');\n      baseError.cause = error; // Preserve original error as cause\n      throw baseError;\n    }\n  }\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { FFmpeg } from '@ffmpeg/ffmpeg';\nimport { toBlobURL } from '@ffmpeg/util';\n\ninterface UseFFmpegResult {\n  ffmpeg: FFmpeg | null;\n  loaded: boolean;\n  loading: boolean;\n  error: Error | null;\n  load: () => Promise<void>;\n}\n\nexport function useFFmpeg(): UseFFmpegResult {\n  const [loaded, setLoaded] = useState(false);\n  const [loading, setLoading] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n  const ffmpegRef = useRef<FFmpeg | null>(null);\n\n  const load = useCallback(async () => {\n    try {\n      setLoading(true);\n      setError(null);\n\n      // Create new FFmpeg instance if not exists\n      if (!ffmpegRef.current) {\n        ffmpegRef.current = new FFmpeg();\n      }\n\n      const ffmpeg = ffmpegRef.current;\n\n      // Add logging handler\n      ffmpeg.on('log', ({ message }) => {\n        console.log('FFmpeg:', message);\n      });\n\n      // Load FFmpeg core files\n      const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.10/dist/umd';\n      await ffmpeg.load({\n        coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),\n        wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),\n      });\n\n      setLoaded(true);\n    } catch (err) {\n      console.error('Failed to load FFmpeg:', err);\n      setError(err instanceof Error ? err : new Error('Failed to load FFmpeg'));\n    } finally {\n      setLoading(false);\n    }\n  }, []);\n\n  return {\n    ffmpeg: ffmpegRef.current,\n    loaded,\n    loading,\n    error,\n    load\n  };\n} "],"mappings":"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","names":["useState","useCallback","useRef","useState","useRef","useCallback"]}