diff --git a/chat_window.php b/chat_window.php index cb55e23..cd4bcff 100644 --- a/chat_window.php +++ b/chat_window.php @@ -547,18 +547,61 @@ if (empty($user_id)) { // ===== FFmpeg in-browser conversion helpers ===== let ffmpegInstance = null; let ffmpegLoaded = false; + + // Cargar script dinámicamente + function loadScript(url) { + return new Promise((resolve, reject) => { + const s = document.createElement('script'); + s.src = url; + s.onload = () => resolve(); + s.onerror = () => reject(new Error('Failed to load ' + url)); + document.head.appendChild(s); + }); + } + async function ensureFFmpeg() { if (ffmpegLoaded) return; + + if (typeof WebAssembly === 'undefined') { + throw new Error('WebAssembly no está disponible en este navegador; no se puede convertir en cliente'); + } + + // Si FFmpeg no está presente, intentar cargar desde varios CDNs if (!window.FFmpeg || !window.FFmpeg.createFFmpeg) { - throw new Error('FFmpeg WASM no está disponible en este navegador'); + const cdns = [ + 'https://cdn.jsdelivr.net/npm/@ffmpeg/ffmpeg@0.11.8/dist/ffmpeg.min.js', + 'https://unpkg.com/@ffmpeg/ffmpeg@0.11.8/dist/ffmpeg.min.js' + ]; + let loaded = false; + for (const url of cdns) { + try { + await loadScript(url); + if (window.FFmpeg && window.FFmpeg.createFFmpeg) { + loaded = true; + break; + } + } catch (e) { + console.warn('No se pudo cargar ffmpeg desde', url, e); + } + } + if (!loaded) { + throw new Error('No se pudo cargar ffmpeg.wasm desde los CDNs'); + } + } + + const { createFFmpeg, fetchFile } = window.FFmpeg; + ffmpegInstance = createFFmpeg({ log: true }); + + showAlert('Cargando conversor de audio en navegador... (esto puede tardar varios segundos)', 'info'); + try { + await ffmpegInstance.load(); + // attach helper + ffmpegInstance._fetchFile = fetchFile; + ffmpegLoaded = true; + } catch (e) { + console.error('FFmpeg load failed:', e); + throw new Error('No se pudo inicializar ffmpeg en el navegador: ' + (e.message || e)); } - const { createFFmpeg, fetchFile } = FFmpeg; - ffmpegInstance = createFFmpeg({ log: false }); - // Inform user loading may take some seconds - showAlert('Cargando conversor de audio en navegador...', 'info'); - await ffmpegInstance.load(); - ffmpegInstance._fetchFile = fetchFile; // store helper - ffmpegLoaded = true; } async function convertWebmToOgg(file) { @@ -567,7 +610,17 @@ if (empty($user_id)) { const outName = 'output.ogg'; try { showAlert('Convirtiendo audio a OGG... puede tardar unos segundos', 'info'); - const data = await ffmpegInstance._fetchFile(file); + // fetchFile helper puede fallar en algunas builds; intentar con fetch si es necesario + let data; + if (ffmpegInstance._fetchFile) { + data = await ffmpegInstance._fetchFile(file); + } else if (window.FFmpeg && window.FFmpeg.fetchFile) { + data = await window.FFmpeg.fetchFile(file); + } else { + // fallback: leer como ArrayBuffer + data = new Uint8Array(await file.arrayBuffer()); + } + ffmpegInstance.FS('writeFile', inName, data); await ffmpegInstance.run('-i', inName, '-c:a', 'libopus', '-b:a', '64k', outName); const outData = ffmpegInstance.FS('readFile', outName); @@ -576,7 +629,7 @@ if (empty($user_id)) { const outFile = new File([blob], newName, { type: 'audio/ogg' }); return outFile; } catch (err) { - console.error('Error converting to OGG:', err); + console.error('Error converting to OGG (client):', err); throw err; } }