fix: prefer preview-compatible audio recording formats
All checks were successful
Build & Deploy to K3s / build-and-deploy (push) Successful in 35s

This commit is contained in:
ordinarthur 2026-04-11 16:49:39 +02:00
parent 800214976f
commit 21cd789a62
2 changed files with 36 additions and 9 deletions

View File

@ -18,14 +18,31 @@ export function useAudioRecorder() {
/** Choisit le meilleur mimeType supporté par le navigateur. */
const getMimeType = useCallback(() => {
const types = [
const audio = document.createElement("audio");
const isAppleDevice = /iPhone|iPad|iPod|Mac/.test(navigator.userAgent);
const types = isAppleDevice
? [
"audio/mp4",
"audio/webm;codecs=opus",
"audio/webm",
"audio/mp4",
"audio/ogg;codecs=opus",
]
: [
"audio/webm;codecs=opus",
"audio/webm",
"audio/ogg;codecs=opus",
"audio/mp4",
];
for (const type of types) {
if (MediaRecorder.isTypeSupported(type)) return type;
const baseType = type.split(";")[0];
if (
MediaRecorder.isTypeSupported(type) &&
audio.canPlayType(baseType) !== ""
) {
return type;
}
}
return ""; // fallback : le navigateur choisira
}, []);
@ -45,7 +62,8 @@ export function useAudioRecorder() {
audio: {
echoCancellation: true,
noiseSuppression: true,
sampleRate: 44100,
autoGainControl: true,
channelCount: 1,
},
});
streamRef.current = stream;

View File

@ -83,6 +83,7 @@ export default function RecipeForm() {
const [audioFile, setAudioFile] = useState<File | null>(null)
const [pageState, setPageState] = useState<PageState>("idle")
const [error, setError] = useState("")
const [previewError, setPreviewError] = useState("")
const [recordingTime, setRecordingTime] = useState(0)
const [user, setUser] = useState<User | null>(null)
const [tipIndex, setTipIndex] = useState(0)
@ -119,6 +120,7 @@ export default function RecipeForm() {
setAudioFile(file)
setPageState("review")
setError("")
setPreviewError("")
}, [currentRecording])
// Timer
@ -572,7 +574,9 @@ export default function RecipeForm() {
if (isPlaying) {
audio.pause()
} else {
audio.play()
audio.play().catch(() => {
setPreviewError("Impossible de lire cet aperçu audio sur ce navigateur.")
})
}
}}
className="h-12 w-12 shrink-0 rounded-full bg-gradient-to-br from-orange-500 to-amber-500 text-white shadow-md flex items-center justify-center hover:shadow-lg hover:scale-105 transition-all"
@ -612,15 +616,20 @@ export default function RecipeForm() {
<audio
id="review-audio"
src={audioUrl}
preload="metadata"
onPlay={() => setIsPlaying(true)}
onPause={() => setIsPlaying(false)}
onEnded={() => setIsPlaying(false)}
onError={() => setPreviewError("La lecture de l'aperçu audio a échoué.")}
className="hidden"
/>
<div className="mt-3 text-[11px] text-muted-foreground text-right">
{(audioFile.size / 1024).toFixed(0)} KB
</div>
{previewError && (
<p className="mt-2 text-xs text-red-500 text-right">{previewError}</p>
)}
</div>
{/* Actions */}