fix: prefer preview-compatible audio recording formats
All checks were successful
Build & Deploy to K3s / build-and-deploy (push) Successful in 35s
All checks were successful
Build & Deploy to K3s / build-and-deploy (push) Successful in 35s
This commit is contained in:
parent
800214976f
commit
21cd789a62
@ -18,14 +18,31 @@ export function useAudioRecorder() {
|
||||
|
||||
/** Choisit le meilleur mimeType supporté par le navigateur. */
|
||||
const getMimeType = useCallback(() => {
|
||||
const types = [
|
||||
"audio/webm;codecs=opus",
|
||||
"audio/webm",
|
||||
"audio/mp4",
|
||||
"audio/ogg;codecs=opus",
|
||||
];
|
||||
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/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;
|
||||
|
||||
@ -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 */}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user