Implementa una transcripción de audio confiable con Whisper en Node.js y evita fallos comunes desde el primer intento. Aquí verás cómo preparar variables, llamar a la función de transcript audio, manejar errores con try/catch y validar resultados en la terminal de Visual Studio Code.
¿Cómo implementar transcript audio con OpenAI en Node.js?
Para iniciar, se definen las variables esenciales: la ruta del archivo MP3 y la API key. Luego, se hace la llamada a la función de transcript audio pasando ambos valores y se imprime el resultado en consola.
Define la ruta del audio con una constante: audioPath apunta al MP3 en la carpeta local.
Crea la API key de OpenAI y asígnala a una variable de tipo string.
Invoca la función transcript audio con: audioPath y openAIAPIKey.
Usa una arrow function para confirmar: “transcripción completada con éxito.”
Muestra en consola la transcripción con console.log.
Añade un catch para capturar y mostrar errores con console.error.
Ejemplo de implementación en JavaScript:
// fs.openaiconst audioPath ='./audio/mi-archivo.mp3';const openAIAPIKey ='tu_api_key_aqui';transcriptAudio(audioPath, openAIAPIKey).then((transcription)=>{console.log('Transcripción completada con éxito.');console.log(transcription);}).catch((error)=>{console.error('Falló la transcripción.');console.error(error);});
¿Qué errores comunes y cómo manejarlos con try/catch?
Los errores son aliados: muestran dónde ajustar la lógica. Aquí, el log reveló que el path estaba recibiendo un buffer en lugar de la ruta del archivo. El mensaje indicó revisar [37:12], lo que llevó a cambiar de audioFile (buffer) a audioFilePath (ruta válida).
Identifica el tipo incorrecto: buffer vs ruta de archivo.
Corrige el argumento esperado: usa audioFilePath en la llamada.
Asegura manejo completo con try/catch, catch y posible throw para propagar contexto.
Muestra mensajes claros con console.error para depurar más rápido.
Patrón de manejo de errores:
try{const transcription =awaittranscriptAudio(audioPath, openAIAPIKey);console.log('Transcripción completada con éxito.');console.log(transcription);}catch(error){console.error('Falló la transcripción.');console.error(error);// referencia útil: [37:12]}
¿Cómo ejecutar en Visual Studio Code y validar la transcripción con Whisper?
La prueba se realiza desde la terminal integrada de Visual Studio Code. Tras corregir el error, la ejecución confirma que el archivo se guarda y que la transcripción se imprime correctamente.
Ejecuta en la terminal: node fs openai.
Espera la respuesta y verifica: “transcripción guardada en audio transcription.”
Confirma el mensaje: “Transcripción completada con éxito.”
Revisa el texto devuelto por Whisper desde el blob de audio.
Comprueba que el guardado funciona con el módulo de file system y el manejo de path para operar en cualquier sistema.
Ejemplo de salida de la transcripción:
“Bajo el brillo tenue del amanecer, sueñan las hojas con el canto del viento...”.
“En su dorada caricia, florece la esperanza y el día se viste de luz nueva.”
Conceptos y habilidades clave aplicadas:
Uso de variables y constantes para configurar audioPath y API key.
Invocación de transcript audio con dos parámetros requeridos.
Patrón con arrow function para procesar respuestas y errores.
Manejo de errores con try/catch, catch, throw y mensajes con console.log y console.error [37:12].
Diferencia entre buffer y ruta de archivo (path), y su impacto en la función [37:12].
Integración del módulo de file system y manejo de path para guardar el resultado.
Ejecución en Visual Studio Code con la terminal y comando node fs openai.
¿Te surgió otra duda o te topaste con un error distinto?: cuéntalo en los comentarios para que lo resolvamos juntos.
Aqui te dejo una manera de hacerlo con la Api Gratuita y es el mismo modelo que usa OpenIA que es Whisper.
Tienes que crearte una cuenta en Huggin Face,
Tienes que Agregar un token que va ser la apiKey, Ingresar a la cuenta y en en el menu izquierdo acceder a Acces Tokens y crear el token y copiar este mismo.
Darle los permisos de Make calls to Inference Providers al token
Agregar el token al codigo nodejs
En los headers agregar 'Content-Type': 'audio/mpeg' para especificar el tipo de archivo.
Lo demas es lo mismo que estaba haciendo para la de openIA
const fs =require('fs');const path =require('path');asyncfunctiontranscribeWithHuggingFace(audioFilePath, hfApiKey){try{// 1. Lee el archivo de audio como un Bufferif(!fs.existsSync(audioFilePath)){thrownewError('Audio file does not exist');}const audioData = fs.readFileSync(audioFilePath);// 2. Elige un modelo Whisper en Hugging Face const modelUrl ='https://api-inference.huggingface.co/models/openai/whisper-large-v3';// 3. Llama a la API de Hugging Faceconsole.log(`Sending audio to Hugging Face model: ${modelUrl}...`);const response =awaitfetch(modelUrl,{method:'POST',headers:{Authorization:`Bearer ${hfApiKey}`,'Content-Type':'audio/mpeg'},body: audioData // Envía el buffer de audio directamente});// 4. Valida y procesa la respuestaif(!response.ok){const errorText =await response.text();thrownewError(`Error from Hugging Face API: ${response.status}${response.statusText} - ${errorText}`);}const data =await response.json();// Valida la estructura de la respuestaif(!data ||typeof data.text==='undefined'){console.warn('Unexpected response structure:', data);thrownewError('Transcription not found in Hugging Face response.');}const transcription = data.text;// 5. Guarda la transcripciónconst outputFilePath = path.join(path.dirname(audioFilePath),`${path.basename(audioFilePath, path.extname(audioFilePath))}_transcription_hf.txt`); fs.writeFileSync(outputFilePath, transcription,'utf8');console.log('Transcription saved to:', outputFilePath);return transcription;// Devuelve error si hay problemas durante la transcripción}catch(error){console.error('Error during Hugging Face transcription:', error.message);if(error.cause){console.error('Cause:', error.cause);}throw error;}}// USAR LA API DE HUGGING FACEconst audioPath ='./audio.mp3';// Asegúrate que esta ruta sea correctaconstHUGGING_FACE_API_KEY='XXXXXXXXXXXXXXXXXXXXXX';// Reemplaza con tu token real de Hugging Faceif(!HUGGING_FACE_API_KEY||HUGGING_FACE_API_KEY==='XXXXXXXXXXXXX'){console.error("Error: Debes reemplazar 'hf_TU_TOKEN_DE_HUGGING_FACE' con tu token real de Hugging Face.");}else{transcribeWithHuggingFace(audioPath,HUGGING_FACE_API_KEY).then(transcription=>{console.log('\n--- Hugging Face Transcription ---');console.log('Transcription successful:\n', transcription);console.log('----------------------------------');}).catch(error=>{console.error('\n--- Hugging Face Transcription Failed ---');console.error('--------------------------------------');});}
Grande ! excelente tutorial ! logre hacerlo solo leyendo tu comentario !
¡Buenísimo tu aporte! estaba probando deepgram pero en verdad que con Hugging Face es practicamente lo mismo que openAI.
Aquí la versión equivalente con la apiKey gratuita de Deepgram:
const fs =require('fs');const path =require('path');const apiUrl ="https://api.deepgram.com/v1/listen?model=nova-3&detect_language=true";asyncfunctiontranscribeAudio(audioFilePath, apiKey){try{if(!fs.existsSync(audioFilePath)){thrownewError('El archivo de audio no existe');}const audioFile = fs.readFileSync(audioFilePath);const response =awaitfetch(apiUrl,{method:"POST",headers:{Accept:"application/json",Authorization:`Token ${apiKey}`,"Content-Type":"audio/mp3",},body: audioFile
})if(!response.ok){const errorData =await response.json();thrownewError(`Error en la API: ${JSON.stringify(errorData)}`);}const data =await response.json();const transcription = data.results.channels[0].alternatives[0].transcript;const outputFilePath = path.join(path.dirname(audioFilePath),`${path.basename(audioFilePath, path.extname(audioFilePath))}_transcription.txt`); fs.writeFileSync(outputFilePath, transcription);return transcription
}catch(error){console.error(`Error en la transcripción: ${error.message}`);throw error;}}const audioPath ='./audio.mp3';const deepgramApiKey ='a27a612658ed5c34c1dd0499d81a19337acda96a'//Free Apikey from DeepgramtranscribeAudio(audioPath, deepgramApiKey).then(transcription=>{console.log('Transcripción completada con éxito');console.log(transcription);}).catch(error=>{console.error('Falló la transcripción ', error);})
Hola amigo, hardcodeaste el ApiKey. Deepgram te da $200 de créditos free si alguien copia tu apikey estaría usando tus créditos gratuitos.
En el caso de que algún día metas tu tarjeta capaz te puede afectar dejar expuesta esta ApiKey.
Te paso una screen del dashboard donde te dice el costo. Para traducir este texto es ínfimo, pero imagínate si alguien la usa para algo mas extenso.
Ojo OpenAi pide configurar un metodo de pago y consumir al menos 5 dolares, por lo que este ejemplo requiere una versión paga, una alternativa es levantar un modelo local como deepseek pero se complica un poco el ejercicio.
correcto, pide poner un metodo pago y pagar. Casualmente pague fue por Gemini Advanced
El ejercicio es interesante, pero deberian hacer el ejercicio con una Api gratuita. Queda aclarar que si las hay, pero es mas complejo consumirlas.
Es recomendable guardar la configuración sensible fuera del código. Sobre todo antes de publicarlo.
Se debe crear un fichero .env donde guardar tu API Key.
OPENAI_API_KEY=tu_clave
También verificar que .gitignore contiene .env
# dotenv environment variable files
.env
Y después importarla al código mediante require()
(Añadir esta la línea de código al principio)
require('dotenv').config();console.log("API KEY CARGADA:", process.env.OPENAI_API_KEY);// Comprobar que se carga la API KEYconst fs =require('fs');const{ open }=require('inspector/promises');const path =require('path');
Y donde está const openaiApiKey sustituir tu API Key por:
const openaiApiKey = process.env.OPENAI_API_KEY;
Así evitarás comprometer tu API Key ;)
Aquí les dejo una forma de hacerlo con Gemini. De esta forma lo puedes hacer de forma gratuita.
OJO: La API key hay que agregarla en el .env de la forma GEMINI_API_KEY=api_key
import{GoogleGenAI, createUserContent, createPartFromUri,}from"@google/genai";importpathfrom'path';import{ fileURLToPath }from'url';importdotenvfrom"dotenv";dotenv.config();// Recrear __dirname para módulos ESconst __filename =fileURLToPath(import.meta.url);const __dirname = path.dirname(__filename);const ai =newGoogleGenAI({});const audioPath = path.join(__dirname,'files','testAudio.mp3');asyncfunctionmain(){try{const myfile =await ai.files.upload({file: audioPath,config:{mimeType:"audio/mp3"},});const response =await ai.models.generateContent({model:"gemini-2.5-flash",contents:createUserContent([createPartFromUri(myfile.uri, myfile.mimeType),"Generate a transcript from the speech",]),});console.log(response.text);}catch(error){console.error("❌ Error al llamar a la API:", error.message);}}awaitmain();
Para los que no saben como obtener su API Key, les dejo donde deben registrarse e iniciar sesion.
url:
Deben tener en cuenta que es posible que les falle y les lance un error al ejecutar el codigo, si el tipo de error es insufficient\_quota deben verificar en el area de billing, a mi me funciono al registrar un medio de pago.
Nunca habia usado la api de OpenAI, esta super el ejercicio!
importfsfrom'fs';importpathfrom'path';importdotenvfrom'dotenv';dotenv.config();asyncfunctiontranscriptAudio(audioFilePath, openaiApiKey){try{if(!openaiApiKey){thrownewError('OpenAI API key is missing!');}if(!fs.existsSync(audioFilePath)){thrownewError('Audio file not found');}const audio = fs.readFileSync(audioFilePath);const formData =newFormData();const blob =newBlob([audio]); formData.append('file', blob, path.basename(audioFilePath)); formData.append('model','whisper-1');const wisperAPI ='https://api.openai.com/v1/audio/transcriptions';const response =awaitfetch(wisperAPI,{method:'POST',headers:{Authorization:`Bearer ${openaiApiKey}`,},body: formData
});if(!response.ok){const errorData =await response.json();// error.type === 'insufficient_quota' Revisar el apartado de billingif(errorData && errorData.error){thrownewError(`Error in transcript audio: ${errorData.error.message}`);}thrownewError(`Error in transcript audio!`);}const data =await response.json();const transcription = data.text;const outputFilePath = path.join( path.dirname(audioFilePath),`${path.basename(audioFilePath, path.extname(audioFilePath))}_transcription.txt`); fs.writeFileSync(outputFilePath, transcription);console.log(`Transcription saved to: ${outputFilePath}`);return transcription;}catch(error){console.error('Error during transcription!');throw error;}}const __dirname = path.resolve();const audioFilePath = path.join(__dirname,'src','static','audio.mp3');const openaiApiKey = process.env.OPENAI_APIKEY;// console.log({ dirname: __dirname, audioFilePath, openaiApiKey });transcriptAudio(audioFilePath, openaiApiKey).then((transcription)=>{console.log({ transcription });}).catch((error)=>{console.error('Error during transcription:', error);});