Incrementar la accesibilidad y la interactividad de tu sitio web es esencial en el desarrollo web moderno. La conversión de texto a voz no solo mejora la accesibilidad, especialmente para usuarios con discapacidades visuales, sino que también enriquece la experiencia del usuario al ofrecer contenido multimedia interactivo. Este tutorial detallado te guiará a través de la integración de la API de OpenAI Text-to-Speech en un proyecto Astro existente, utilizando React para el frontend y Next.js para el backend.
Configuración Inicial
Antes de comenzar, asegúrate de que tu proyecto Astro esté configurado para usar React. Astro permite una fácil integración con marcos de JavaScript como React, lo que hace posible usar componentes de React dentro de tus páginas Astro.
Si estás planeando usar Next.js para manejar las funciones del backend, como la API, asegúrate de tener Next.js instalado y configurado en tu proyecto. Esto puede implicar configurar un subdirectorio específico para Next.js si estás integrando Next.js en un proyecto Astro ya existente.
Backend: Creando el Endpoint de API con Next.js
Paso 1: Configuración de la API de Next.js
Crea una carpeta /pages/api
en tu proyecto Next.js. Dentro de esta carpeta, crea un archivo text-to-speech.js
. Este archivo será tu endpoint de API que interactúa con la API de OpenAI.
Paso 2: Implementación del Endpoint
En text-to-speech.js
, implementa la función que manejará las solicitudes POST. Esta función deberá aceptar texto del cuerpo de la solicitud, enviarlo a la API de OpenAI y devolver la respuesta (generalmente una URL de audio) al cliente.
Aquí tienes un ejemplo de cómo se podría ver el código:
// pages/api/text-to-speech.js
import axios from 'axios';
import dotenv from 'dotenv';
import { enableCors } from '@/src/middleware/enableCors';
import { methodValidator } from '@/src/utils/methodValidator';
dotenv.config();
async function handleAudioRequest(req, res) {
console.log('Inicio de la solicitud de audio');
await methodValidator(req, res, 'POST');
if (res.headersSent) {
console.log('Respuesta ya enviada después de la validación del método HTTP');
return;
}
const { text } = req.body;
if (!text) {
console.log('Falta el texto en el cuerpo de la solicitud');
return res.status(400).json({ error: 'Falta el texto' });
}
try {
console.log('Llamando a la API de OpenAI para generar audio');
const openaiResponse = await axios.post(
'https://api.openai.com/v1/audio/speech',
{
model: 'tts-1',
input: text,
voice: 'echo',
format: 'mp3',
},
{
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
responseType: 'arraybuffer',
}
);
console.log('Audio generado con éxito.');
res.writeHead(200, {
'Content-Type': 'audio/mpeg',
'Content-Length': openaiResponse.data.length,
});
res.end(openaiResponse.data);
} catch (error) {
console.error('Error en handleAudioRequest:', error);
res.status(500).json({ error: `Error al procesar la solicitud: ${error.message}` });
}
}
export default enableCors(handleAudioRequest);
Recuerda que necesitarás manejar la autenticación con OpenAI de manera segura, generalmente usando variables de entorno para tus claves API.
Frontend: Implementando el Componente TextToSpeechController en React
Paso 1: Creación del Componente React
Crea un nuevo componente React, TextToSpeechController.jsx
, en tu directorio de componentes. Este componente incluirá un botón para activar la conversión de texto a voz y lógica para manejar la reproducción de audio.
Paso 2: Lógica del Componente
En tu componente, usa useState
y useRef
de React para manejar el estado de reproducción y una referencia al elemento de audio, respectivamente. Agrega una función, togglePlayback
, que manejará la solicitud al endpoint de Next.js y la reproducción del audio resultante.
Aquí tienes un esquema de cómo podría implementarse:
import { useState, useRef } from 'react';
const TextToSpeechController = ({ title, content }) => {
const [isPlaying, setIsPlaying] = useState(false);
const audioRef = useRef(null);
const togglePlayback = async () => {
if (audioRef.current && isPlaying) {
audioRef.current.pause();
setIsPlaying(false);
return;
}
if (!content) return;
setIsPlaying(true);
try {
const response = await fetch('http://localhost:3000/api/speech', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: `${title}.\n${content}`, title }),
});
if (response.ok) {
const { url } = await response.json();
if (!audioRef.current) {
audioRef.current = new Audio(url);
} else {
audioRef.current.src = url;
}
audioRef.current.play();
audioRef.current.onended = () => {
setIsPlaying(false);
};
} else {
console.error('Error en la solicitud:', response.statusText);
setIsPlaying(false);
}
} catch (error) {
console.error('Error al hacer la solicitud:', error);
setIsPlaying(false);
}
};
return (
<button
onClick={togglePlayback}
className="flex items-center font-medium transition duration-300 hover:text-primary"
disabled={!content}
>
{isPlaying ? 'Detener' : 'Reproducir'}
</button>
);
};
export default TextToSpeechController;
Paso 3: Integración del Componente en Astro
Asegúrate de integrar correctamente tu componente TextToSpeechController
en las páginas de Astro donde deseas ofrecer la funcionalidad de texto a voz. Esto puede implicar importar y renderizar el componente de React dentro de tus archivos .astro
.
---
// Importa el componente React
import TextToSpeechController from '../components/TextToSpeechController';
---
// Usar el componente en tu página
<TextToSpeechController client:load content={markdownify(audio)} title={markdownify(title)} />
Pruebas y Despliegue
Antes de desplegar tu sitio, realiza pruebas exhaustivas para asegurarte de que la comunicación entre el frontend y el backend funciona como se espera. Prueba la funcionalidad en diferentes navegadores y dispositivos para garantizar que todos los usuarios puedan acceder a la función de texto a voz.
Conclusión
Al completar este tutorial, habrás mejorado significativamente la accesibilidad y la interactividad de tu sitio web, permitiendo a los usuarios convertir texto en voz de manera eficiente. Esta integración no solo mejora la experiencia del usuario, sino que también demuestra la poderosa combinación de Astro con React y Next.js para desarrollar funciones web avanzadas.