Improve Transcribe error diagnostics, add minimum audio check
- Log $response status/headers/body on deserialization errors - Add 10ms delay between audio chunks to prevent stream overload - Skip transcription if audio < 0.5s (too short for recognition) - Cleaner error logging with dedicated logTranscribeError helper
This commit is contained in:
parent
42b002eea8
commit
a36cd9a299
1 changed files with 47 additions and 27 deletions
|
|
@ -61,7 +61,23 @@ function convertToPCM(inputBuffer) {
|
||||||
async function* makeAudioStream(buffer) {
|
async function* makeAudioStream(buffer) {
|
||||||
for (var i = 0; i < buffer.length; i += CHUNK_SIZE) {
|
for (var i = 0; i < buffer.length; i += CHUNK_SIZE) {
|
||||||
yield { AudioEvent: { AudioChunk: buffer.slice(i, i + CHUNK_SIZE) } };
|
yield { AudioEvent: { AudioChunk: buffer.slice(i, i + CHUNK_SIZE) } };
|
||||||
await new Promise(function(r) { setTimeout(r, 0); });
|
// Small delay between chunks to prevent overwhelming the stream
|
||||||
|
await new Promise(function(r) { setTimeout(r, 10); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function logTranscribeError(label, err) {
|
||||||
|
console.error('[Transcribe] ' + label + ':', err.message);
|
||||||
|
if (err.name) console.error('[Transcribe] name:', err.name);
|
||||||
|
if (err.$metadata) console.error('[Transcribe] metadata:', JSON.stringify(err.$metadata));
|
||||||
|
if (err.cause) console.error('[Transcribe] cause:', err.cause.message || JSON.stringify(err.cause));
|
||||||
|
if (err.$response) {
|
||||||
|
try {
|
||||||
|
var resp = err.$response;
|
||||||
|
console.error('[Transcribe] status:', resp.statusCode);
|
||||||
|
if (resp.headers) console.error('[Transcribe] headers:', JSON.stringify(resp.headers));
|
||||||
|
if (resp.body) console.error('[Transcribe] body:', typeof resp.body === 'string' ? resp.body.slice(0, 500) : '(stream)');
|
||||||
|
} catch (e) { /* ignore logging errors */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,8 +91,6 @@ async function transcribeWithAWS(audioBuffer, mimeType) {
|
||||||
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
||||||
} : undefined;
|
} : undefined;
|
||||||
|
|
||||||
var client = new TranscribeStreamingClient({ region: region, credentials: credentials });
|
|
||||||
|
|
||||||
// Try ffmpeg conversion to PCM (most reliable with AWS Transcribe).
|
// Try ffmpeg conversion to PCM (most reliable with AWS Transcribe).
|
||||||
// Falls back to ogg-opus passthrough if ffmpeg is not installed.
|
// Falls back to ogg-opus passthrough if ffmpeg is not installed.
|
||||||
var audioToSend = audioBuffer;
|
var audioToSend = audioBuffer;
|
||||||
|
|
@ -90,13 +104,18 @@ async function transcribeWithAWS(audioBuffer, mimeType) {
|
||||||
console.log('[Transcribe] ffmpeg conversion OK — PCM 16kHz, ' + audioToSend.length + ' bytes');
|
console.log('[Transcribe] ffmpeg conversion OK — PCM 16kHz, ' + audioToSend.length + ' bytes');
|
||||||
} catch (ffErr) {
|
} catch (ffErr) {
|
||||||
console.warn('[Transcribe] ffmpeg unavailable, sending ogg-opus directly:', ffErr.message);
|
console.warn('[Transcribe] ffmpeg unavailable, sending ogg-opus directly:', ffErr.message);
|
||||||
// For WAV input, try pcm anyway without ffmpeg
|
|
||||||
if (mimeType && mimeType.indexOf('wav') !== -1) {
|
if (mimeType && mimeType.indexOf('wav') !== -1) {
|
||||||
mediaEncoding = 'pcm';
|
mediaEncoding = 'pcm';
|
||||||
sampleRate = 16000;
|
sampleRate = 16000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Minimum ~0.5s of PCM audio at 16kHz mono 16-bit = 16000 bytes
|
||||||
|
if (mediaEncoding === 'pcm' && audioToSend.length < 16000) {
|
||||||
|
console.warn('[Transcribe] Audio too short (' + audioToSend.length + ' bytes), skipping');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
var useMedical = process.env.AWS_TRANSCRIBE_MEDICAL === 'true';
|
var useMedical = process.env.AWS_TRANSCRIBE_MEDICAL === 'true';
|
||||||
var specialty = process.env.AWS_TRANSCRIBE_SPECIALTY || 'PRIMARYCARE';
|
var specialty = process.env.AWS_TRANSCRIBE_SPECIALTY || 'PRIMARYCARE';
|
||||||
var transcript = '';
|
var transcript = '';
|
||||||
|
|
@ -118,10 +137,11 @@ async function transcribeWithAWS(audioBuffer, mimeType) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try Medical first if enabled, with fallback to Standard
|
||||||
if (useMedical) {
|
if (useMedical) {
|
||||||
try {
|
try {
|
||||||
var StartMedicalStreamTranscriptionCommand = TranscribeModule.StartMedicalStreamTranscriptionCommand;
|
var client = new TranscribeStreamingClient({ region: region, credentials: credentials });
|
||||||
var medCmd = new StartMedicalStreamTranscriptionCommand({
|
var medCmd = new TranscribeModule.StartMedicalStreamTranscriptionCommand({
|
||||||
LanguageCode: 'en-US',
|
LanguageCode: 'en-US',
|
||||||
MediaSampleRateHertz: sampleRate,
|
MediaSampleRateHertz: sampleRate,
|
||||||
MediaEncoding: mediaEncoding,
|
MediaEncoding: mediaEncoding,
|
||||||
|
|
@ -131,29 +151,29 @@ async function transcribeWithAWS(audioBuffer, mimeType) {
|
||||||
});
|
});
|
||||||
var medResp = await client.send(medCmd);
|
var medResp = await client.send(medCmd);
|
||||||
transcript = await collectTranscript(medResp.TranscriptResultStream);
|
transcript = await collectTranscript(medResp.TranscriptResultStream);
|
||||||
console.log('[Transcribe] Medical transcription OK (' + transcript.length + ' chars)');
|
console.log('[Transcribe] Medical OK (' + transcript.length + ' chars)');
|
||||||
} catch (medErr) {
|
} catch (medErr) {
|
||||||
console.warn('[Transcribe] Medical failed:', medErr.message);
|
logTranscribeError('Medical failed', medErr);
|
||||||
if (medErr.name) console.warn('[Transcribe] Error name:', medErr.name);
|
console.warn('[Transcribe] Falling back to standard...');
|
||||||
if (medErr.$metadata) console.warn('[Transcribe] Metadata:', JSON.stringify(medErr.$metadata));
|
try {
|
||||||
if (medErr.cause) console.warn('[Transcribe] Cause:', medErr.cause.message || medErr.cause);
|
var client2 = new TranscribeStreamingClient({ region: region, credentials: credentials });
|
||||||
console.warn('[Transcribe] Falling back to standard Transcribe...');
|
var stdCmd = new TranscribeModule.StartStreamTranscriptionCommand({
|
||||||
// Fallback to standard Transcribe
|
LanguageCode: 'en-US',
|
||||||
var client2 = new TranscribeStreamingClient({ region: region, credentials: credentials });
|
MediaSampleRateHertz: sampleRate,
|
||||||
var StartStreamTranscriptionCommand = TranscribeModule.StartStreamTranscriptionCommand;
|
MediaEncoding: mediaEncoding,
|
||||||
var cmd = new StartStreamTranscriptionCommand({
|
AudioStream: makeAudioStream(audioToSend)
|
||||||
LanguageCode: 'en-US',
|
});
|
||||||
MediaSampleRateHertz: sampleRate,
|
var stdResp = await client2.send(stdCmd);
|
||||||
MediaEncoding: mediaEncoding,
|
transcript = await collectTranscript(stdResp.TranscriptResultStream);
|
||||||
AudioStream: makeAudioStream(audioToSend)
|
console.log('[Transcribe] Standard fallback OK (' + transcript.length + ' chars)');
|
||||||
});
|
} catch (stdErr) {
|
||||||
var resp = await client2.send(cmd);
|
logTranscribeError('Standard also failed', stdErr);
|
||||||
transcript = await collectTranscript(resp.TranscriptResultStream);
|
throw stdErr;
|
||||||
console.log('[Transcribe] Standard fallback OK (' + transcript.length + ' chars)');
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var StartStreamTranscriptionCommand = TranscribeModule.StartStreamTranscriptionCommand;
|
var client = new TranscribeStreamingClient({ region: region, credentials: credentials });
|
||||||
var cmd = new StartStreamTranscriptionCommand({
|
var cmd = new TranscribeModule.StartStreamTranscriptionCommand({
|
||||||
LanguageCode: 'en-US',
|
LanguageCode: 'en-US',
|
||||||
MediaSampleRateHertz: sampleRate,
|
MediaSampleRateHertz: sampleRate,
|
||||||
MediaEncoding: mediaEncoding,
|
MediaEncoding: mediaEncoding,
|
||||||
|
|
@ -161,7 +181,7 @@ async function transcribeWithAWS(audioBuffer, mimeType) {
|
||||||
});
|
});
|
||||||
var resp = await client.send(cmd);
|
var resp = await client.send(cmd);
|
||||||
transcript = await collectTranscript(resp.TranscriptResultStream);
|
transcript = await collectTranscript(resp.TranscriptResultStream);
|
||||||
console.log('[Transcribe] Standard transcription OK (' + transcript.length + ' chars)');
|
console.log('[Transcribe] Standard OK (' + transcript.length + ' chars)');
|
||||||
}
|
}
|
||||||
|
|
||||||
return transcript.trim();
|
return transcript.trim();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue