- Gemini batch transcription (no Deepgram live)
- blobToBase64 helper (shared/lib/audio.ts)
- AudioRecorder: remove onChunk, add maxSeconds/onMaxReached auto-submit
- Timer stops at maxSeconds and triggers auto-submission
- EnregistrementEOPage: audioBase64 to backend, fix race condition step=done
- SimulationFlowProvider: submitEoAudio(audioBase64, mimeType, nclcCible)
- MIME normalization (strip codec params)
- Split CORRECTION_EE_TIMEOUT_MS (60s) / CORRECTION_EO_TIMEOUT_MS (120s)
- PresentationGenereeT1Page: localStorage persistence
Typecheck: OK · Tests: 159/159 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
/**
|
|
* Helpers audio partagés — Sprint 4c-3.
|
|
*/
|
|
|
|
/**
|
|
* Convertit un Blob en chaîne base64 (sans le préfixe `data:<mime>;base64,`).
|
|
*
|
|
* Utilise FileReader.readAsDataURL puis strip le préfixe avant retour. Le
|
|
* payload audio EO est ensuite envoyé tel quel dans le body JSON de
|
|
* `POST /corrections/eo` (cf. SimulationFlowProvider.submitEoAudio).
|
|
*
|
|
* Reject si le reader émet une erreur ou si le résultat n'est pas une chaîne
|
|
* data URI bien formée.
|
|
*/
|
|
export function blobToBase64(blob: Blob): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader()
|
|
reader.onerror = () => {
|
|
reject(new Error('FileReader: lecture du Blob audio impossible.'))
|
|
}
|
|
reader.onload = () => {
|
|
const result = reader.result
|
|
if (typeof result !== 'string') {
|
|
reject(new Error('FileReader: résultat inattendu (non-string).'))
|
|
return
|
|
}
|
|
const commaIdx = result.indexOf(',')
|
|
if (commaIdx < 0 || !result.startsWith('data:')) {
|
|
reject(new Error('FileReader: résultat non conforme au format data URI.'))
|
|
return
|
|
}
|
|
resolve(result.slice(commaIdx + 1))
|
|
}
|
|
reader.readAsDataURL(blob)
|
|
})
|
|
}
|