Fix speech-to-text with Groq Whisper
This commit is contained in:
@@ -7,6 +7,7 @@ const googleTTS = require('google-tts-api');
|
||||
require('dotenv').config();
|
||||
|
||||
const HUGGINGFACE_API_TOKEN = process.env.HUGGINGFACEHUB_API_TOKEN || process.env.HF_API_TOKEN;
|
||||
const GROQ_API_KEY = process.env.GROQ_API_KEY;
|
||||
const nllbLangMap = {
|
||||
'en': 'eng_Latn',
|
||||
'es': 'spa_Latn',
|
||||
@@ -77,7 +78,7 @@ function loadSslOptions() {
|
||||
// Generate a temporary self-signed certificate for localhost
|
||||
console.warn('No SSL cert/key provided. Generating a temporary self-signed certificate for https://localhost:' + SSL_PORT);
|
||||
const attrs = [{ name: 'commonName', value: 'localhost' }];
|
||||
const pems = selfsigned.generate(attrs, { days: 365 });
|
||||
const pems = selfsigned.generate(attrs, { days: 365, keySize: 2048 });
|
||||
return { key: pems.private, cert: pems.cert };
|
||||
}
|
||||
|
||||
@@ -332,7 +333,25 @@ const translateViaLibreTranslate = async (text, sourceLang, targetLang) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Speech-to-text endpoint using Hugging Face Whisper
|
||||
function getTranscriptionFilename(contentType) {
|
||||
const mimeType = (contentType || 'audio/webm').split(';')[0].trim().toLowerCase();
|
||||
|
||||
if (mimeType.includes('mp4') || mimeType.includes('m4a') || mimeType.includes('aac')) {
|
||||
return 'audio.mp4';
|
||||
}
|
||||
|
||||
if (mimeType.includes('webm')) {
|
||||
return 'audio.webm';
|
||||
}
|
||||
|
||||
if (mimeType.includes('wav')) {
|
||||
return 'audio.wav';
|
||||
}
|
||||
|
||||
return 'audio.webm';
|
||||
}
|
||||
|
||||
// Speech-to-text endpoint using Groq Whisper
|
||||
app.post('/api/transcribe', async (req, res) => {
|
||||
try {
|
||||
const audioBuffer = req.body;
|
||||
@@ -340,29 +359,40 @@ app.post('/api/transcribe', async (req, res) => {
|
||||
return res.status(400).json({ error: 'No audio provided' });
|
||||
}
|
||||
|
||||
if (!HUGGINGFACE_API_TOKEN) {
|
||||
return res.status(500).json({ error: 'Hugging Face token not configured' });
|
||||
if (!GROQ_API_KEY) {
|
||||
return res.status(503).json({ error: 'Speech-to-text is temporarily unavailable: GROQ API key is not configured.' });
|
||||
}
|
||||
|
||||
const contentType = req.headers['content-type'] || 'application/octet-stream';
|
||||
const response = await axios.post(
|
||||
'https://api-inference.huggingface.co/models/openai/whisper-large-v3',
|
||||
audioBuffer,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${HUGGINGFACE_API_TOKEN}`,
|
||||
'Content-Type': contentType
|
||||
},
|
||||
timeout: 60000
|
||||
}
|
||||
);
|
||||
const contentType = req.headers['content-type'] || 'audio/webm';
|
||||
const mimeType = contentType.split(';')[0].trim().toLowerCase();
|
||||
const filename = getTranscriptionFilename(contentType);
|
||||
const formData = new FormData();
|
||||
|
||||
const data = response.data;
|
||||
const transcript = Array.isArray(data) ? data[0]?.text : data?.text || '';
|
||||
res.json({ transcript });
|
||||
formData.append('file', new Blob([audioBuffer], { type: mimeType }), filename);
|
||||
formData.append('model', 'whisper-large-v3-turbo');
|
||||
formData.append('response_format', 'json');
|
||||
|
||||
const response = await fetch('https://api.groq.com/openai/v1/audio/transcriptions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${GROQ_API_KEY}`
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json().catch(() => null);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorMessage = data?.error?.message || data?.error || 'Speech-to-text failed';
|
||||
console.error('Groq speech-to-text error:', errorMessage);
|
||||
return res.status(response.status).json({ error: errorMessage });
|
||||
}
|
||||
|
||||
const transcript = data?.text || '';
|
||||
return res.json({ transcript });
|
||||
} catch (error) {
|
||||
console.error('Speech-to-text error:', error.message || error);
|
||||
res.status(500).json({ error: 'Speech-to-text failed' });
|
||||
return res.status(500).json({ error: 'Speech-to-text failed' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user