[{"data":1,"prerenderedAt":309},["ShallowReactive",2],{"\u002Fprojects\u002Ftranscribe-local":3,"posts":222},{"id":4,"title":5,"body":6,"description":148,"extension":149,"featured":150,"images":151,"links":174,"meta":181,"navigation":150,"order":182,"path":183,"seo":184,"stack":185,"stats":205,"stem":218,"tag":219,"url":220,"__hash__":221},"projects\u002Fprojects\u002Ftranscribe-local.md","TranscribeLocal",{"type":7,"value":8,"toc":136},"minimark",[9,14,73,77,82,86,90,93,97,100,104],[10,11,13],"h2",{"id":12},"qué-hace","Qué hace",[15,16,17,25,31,37,43,49,55,61,67],"ul",{},[18,19,20,24],"li",{},[21,22,23],"strong",{},"Transcribir audio y vídeo."," Arrastras un archivo y Whisper lo convierte en texto con marcas de tiempo, con el modelo que elijas: de tiny (~75 MB) a large-v3-turbo (~1,5 GB).",[18,26,27,30],{},[21,28,29],{},"Cien idiomas."," Detecta el idioma solo o se lo indicas tú.",[18,32,33,36],{},[21,34,35],{},"Subtítulos listos."," Exporta a SRT y VTT, con cada frase en su tiempo, y también a TXT, JSON y Markdown.",[18,38,39,42],{},[21,40,41],{},"Reproductor sincronizado."," Mientras suena el audio se resalta la frase que se está diciendo, y al pulsar una frase salta a ese momento.",[18,44,45,48],{},[21,46,47],{},"Quién habla."," Separa la transcripción por hablantes (Hablante 1, Hablante 2…).",[18,50,51,54],{},[21,52,53],{},"Resumen."," Un modelo de lenguaje pequeño, Qwen2.5, lo resume sin salir del equipo.",[18,56,57,60],{},[21,58,59],{},"Grabar."," Desde el micrófono o desde el audio de otra pestaña del navegador.",[18,62,63,66],{},[21,64,65],{},"Modelos bajo control."," Se descargan una vez, se quedan en el navegador y un gestor enseña cuánto ocupan y deja borrarlos.",[18,68,69,72],{},[21,70,71],{},"Instalable y sin conexión."," Es una PWA: una vez descargados los modelos, funciona sin internet.",[10,74,76],{"id":75},"cómo-está-hecho","Cómo está hecho",[78,79,81],"h3",{"id":80},"whisper-en-el-navegador","Whisper en el navegador",[83,84,85],"p",{},"Transformers.js ejecuta los modelos en formato ONNX con WebGPU si hay GPU, y con WebAssembly si no. Cada tarea (transcribir, separar hablantes, resumir) va en su propio Web Worker, así que la interfaz no se congela aunque el modelo tarde.",[78,87,89],{"id":88},"del-archivo-al-modelo","Del archivo al modelo",[83,91,92],{},"El audio se decodifica con la Web Audio API, se mezcla a mono y se remuestrea a 16 kHz, que es lo que espera Whisper. Los audios de más de 30 segundos se transcriben en trozos de 30 segundos que se solapan 5.",[78,94,96],{"id":95},"quién-habla-en-tres-pasos","Quién habla, en tres pasos",[83,98,99],{},"pyannote-segmentation-3.0 recorre el audio en ventanas de 10 segundos y marca dónde habla cada voz. WeSpeaker convierte cada intervención en un vector. Un agrupamiento propio por similitud del coseno decide qué vectores son la misma persona en todo el audio.",[10,101,103],{"id":102},"problemas-que-resolví","Problemas que resolví",[15,105,106,112,118,124,130],{},[18,107,108,111],{},[21,109,110],{},"Whisper se inventaba frases en los silencios."," El audio prácticamente mudo o de menos de un cuarto de segundo ya no llega al modelo, y en los audios cortos no se trocea, porque el relleno de silencio provocaba bucles de texto repetido.",[18,113,114,117],{},[21,115,116],{},"Los audios largos se cortaban a los 30 segundos."," Sin trocear, el extractor de características de Whisper descarta todo lo que pasa de ahí sin avisar.",[18,119,120,123],{},[21,121,122],{},"Alucinaciones en WebGPU."," El codificador de Whisper necesita fp32 para no inventar texto en otros idiomas, mientras que el decodificador va en q4 para no agotar la memoria.",[18,125,126,129],{},[21,127,128],{},"Resúmenes sin sentido."," Con el modelo cuantizado en q8, WebGPU devolvía una mezcla de idiomas y fragmentos de código. Ahora va en q4 en WebGPU y en q8 en WebAssembly.",[18,131,132,135],{},[21,133,134],{},"Descargas que se cortaban a los 5 minutos."," El service worker de la PWA interceptaba las descargas de los modelos, y Chrome corta un service worker que tarda más de 5 minutos en responder. Ahora los modelos van directos a la caché de Transformers.js y no se guardan dos veces.",{"title":137,"searchDepth":138,"depth":138,"links":139},"",2,[140,141,147],{"id":12,"depth":138,"text":13},{"id":75,"depth":138,"text":76,"children":142},[143,145,146],{"id":80,"depth":144,"text":81},3,{"id":88,"depth":144,"text":89},{"id":95,"depth":144,"text":96},{"id":102,"depth":138,"text":103},"Transcribe audio y vídeo y saca subtítulos con Whisper dentro del navegador, sin subir nada a ningún servidor. Distingue quién habla, resume con un modelo de lenguaje local, exporta a SRT, VTT, TXT, JSON y Markdown y funciona como app instalable (PWA), con WebGPU o WebAssembly.","md",true,[152,157,162,166,171],{"src":153,"alt":154,"width":155,"height":156},"\u002Fimages\u002Fposts\u002Ftranscribe-local\u002Fportada.webp","Un diálogo transcrito, con el reproductor resaltando la frase que suena",1440,900,{"src":158,"alt":159,"width":160,"height":161},"\u002Fimages\u002Fposts\u002Ftranscribe-local\u002Fhablantes.webp","La transcripción separada por hablantes, con un número de color para cada voz",780,485,{"src":163,"alt":164,"width":160,"height":165},"\u002Fimages\u002Fposts\u002Ftranscribe-local\u002Fexportar.webp","La transcripción con los botones para exportarla a TXT, SRT, VTT, JSON y Markdown",365,{"src":167,"alt":168,"width":169,"height":170},"\u002Fimages\u002Fposts\u002Ftranscribe-local\u002Fmodelos.webp","El gestor de modelos, con los que están guardados en el navegador y un botón para borrar cada uno",540,765,{"src":172,"alt":173,"width":155,"height":156},"\u002Fimages\u002Fposts\u002Ftranscribe-local\u002Foscuro.webp","TranscribeLocal en modo oscuro",[175,178],{"label":176,"url":177},"Cómo se usa","\u002Fposts\u002Ftranscribe-local-subtitulos-en-tu-navegador",{"label":179,"url":180},"Por dentro","\u002Fposts\u002Ftranscribe-local-por-dentro",{},6,"\u002Fprojects\u002Ftranscribe-local",{"title":5,"description":148},[186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204],"Nuxt 4","Vue 3","TypeScript","Transformers.js","ONNX Runtime Web","WebGPU","WebAssembly","Web Workers","Web Audio API","MediaRecorder","Whisper","pyannote","WeSpeaker","Qwen2.5","PWA","Tailwind CSS","Vitest","Playwright","GitHub Actions",[206,209,212,215],{"value":207,"label":208},"4","modelos de IA en local",{"value":210,"label":211},"0","archivos subidos",{"value":213,"label":214},"237","tests (Vitest)",{"value":216,"label":217},"100","idiomas","projects\u002Ftranscribe-local","transcribe-local","https:\u002F\u002Fabdell1999.github.io\u002Ftranscribe-local-public\u002F","3YjUvDDEcoV48BAC0kaWJI99j82RkZ51iBIwtZj-JPQ",[223,233,240,249,258,263,270,276,284,290,296,302],{"title":224,"description":225,"date":226,"path":180,"tags":227,"type":232},"TranscribeLocal por dentro: Whisper en el navegador y cómo dejó de inventarse frases","Cómo ejecuta TranscribeLocal Whisper, la separación de hablantes y un modelo de lenguaje dentro del navegador con Transformers.js, por qué Whisper se inventaba frases en los silencios, qué hace falta para transcribir audios largos y por qué un service worker cortaba las descargas a los cinco minutos.","2026-10-22",[219,228,229,230,231],"ia","arquitectura","typescript","nuxt","tecnico",{"title":234,"description":235,"date":226,"path":177,"tags":236,"type":239},"TranscribeLocal: transcribe y saca subtítulos de cualquier vídeo, sin salir de tu navegador","Una app web que convierte audio y vídeo en texto y subtítulos con Whisper, distingue quién habla y hace resúmenes, todo en tu ordenador. Sin subir nada a ningún servidor, sin límites de duración y gratis. Qué hace y cómo se usa.",[219,228,237,238],"privacidad","proyectos","guia",{"title":241,"description":242,"date":243,"path":244,"tags":245,"type":239},"PokeStore: un tema de WordPress a medida para tiendas de cartas coleccionables","Un tema de WordPress y WooCommerce hecho desde cero para tiendas de Pokémon y One Piece TCG. Un recorrido por la tienda como la ve quien compra, de la portada a la lista de deseos, y por lo que puede ajustar quien la lleva.","2026-10-21","\u002Fposts\u002Fpokestore-tema-wordpress-para-tiendas-tcg",[246,247,248,238],"pokestore","wordpress","woocommerce",{"title":250,"description":251,"date":252,"path":253,"tags":254,"type":239},"YouTube Like Shortcut: da like con una tecla, como en TikTok","Una extensión de Chrome que da like al vídeo o Short de YouTube que estás viendo al pulsar la L. Cómo se instala, qué opciones tiene y por qué no se dispara mientras escribes.","2026-10-20","\u002Fposts\u002Fyoutube-like-shortcut-like-con-una-tecla",[255,256,257,238],"youtube-like-shortcut","youtube","productividad",{"title":259,"description":260,"date":252,"path":261,"tags":262,"type":232},"YouTube Like Shortcut por dentro: pulsar un botón en una web que cambia sin avisar","Cómo una extensión de una sola función llega antes que el reproductor de YouTube, encuentra el botón de like entre variantes ocultas y layouts que cambian con el ancho de la ventana, y se asegura de que el like ha entrado aunque YouTube esté reconstruyendo la página.","\u002Fposts\u002Fyoutube-like-shortcut-por-dentro",[255,256,229,230],{"title":264,"description":265,"date":266,"path":267,"tags":268,"type":239},"AI Upscaler: amplía imágenes y quita fondos con IA, sin salir de tu navegador","Una extensión de Chrome que amplía imágenes ×2 o ×4 y elimina fondos con inteligencia artificial, todo en tu equipo. Sin subir nada a ningún servidor, sin cuentas y gratis. Qué hace y cómo se usa.","2026-10-19","\u002Fposts\u002Fai-upscaler-imagenes-con-ia-en-tu-navegador",[269,228,237,238],"ai-upscaler",{"title":271,"description":272,"date":266,"path":273,"tags":274,"type":232},"AI Upscaler por dentro: dos redes neuronales en una extensión de Chrome","Cómo ejecuta AI Upscaler Real-ESRGAN y U²-Net dentro del navegador con ONNX Runtime Web, por qué la imagen se procesa en mosaicos con margen, qué hubo que parchear en el modelo de quitar fondos y qué obstáculos pone una extensión Manifest V3 a los workers y al WebAssembly.","\u002Fposts\u002Fai-upscaler-por-dentro",[269,228,229,230,275],"vue",{"title":277,"description":278,"date":279,"path":280,"tags":281,"type":239},"ABR Cipher: cifrado seguro, completamente en tu navegador","Una suite de cifrado que no envía nada a ningún servidor. Cifrar textos y archivos, compartir secretos con un enlace que caduca, guardar contraseñas y destruir archivos. Qué hace y cómo se usa.","2026-10-18","\u002Fposts\u002Fabr-cipher-cifrado-en-tu-navegador",[282,283,237,238],"cipher","seguridad",{"title":285,"description":286,"date":279,"path":287,"tags":288,"type":232},"ABR Cipher por dentro: criptografía sin servidor, de la URL al disco","Por qué ABR Cipher solo usa la Web Crypto API, cómo viaja un secreto en el fragmento de una URL, cómo se cifra un archivo de varios GB en el navegador y qué hace falta para destruir un archivo de verdad, con un compañero en Rust que lee NTFS.","\u002Fposts\u002Fabr-cipher-por-dentro",[282,283,229,230,289],"rust",{"title":291,"description":292,"date":279,"path":293,"tags":294,"type":232},"ABReader por dentro: el lector que no encontré, construido a mi medida","Voces neuronales que se ejecutan en el navegador, sincronización entre dispositivos sin servidor y once formatos detrás de un mismo contrato. Las decisiones técnicas de ABReader y por qué las tomé.","\u002Fposts\u002Fabreader-por-dentro",[295,229,230,231],"abreader",{"title":297,"description":298,"date":279,"path":299,"tags":300,"type":239},"ABReader: tu biblioteca de libros electrónicos en el navegador","Un lector de libros electrónicos que funciona en el navegador, sin cuentas ni servidores. Qué hace, cómo se usa y cómo probarlo en un minuto.","\u002Fposts\u002Fabreader-tu-biblioteca-en-el-navegador",[295,301,238],"lectura",{"title":303,"description":304,"date":279,"path":305,"tags":306,"type":232},"Cómo construí este blog: estático, sin servidor y sin coste de hosting","Por qué elegí Nuxt y Markdown en lugar de WordPress, cómo separo el código privado del sitio publicado y qué se rompió en el primer despliegue.","\u002Fposts\u002Farquitectura-de-este-blog",[231,275,307,308],"devops","meta",1792636040214]