import { Audio, AVPlaybackStatus } from "expo-av"; export interface RecordingResult { uri: string; durationMs: number; } let currentRecording: Audio.Recording | null = null; let currentSound: Audio.Sound | null = null; async function requestPermissions(): Promise { const { status } = await Audio.requestPermissionsAsync(); return status === "granted"; } export async function startRecording(): Promise { const granted = await requestPermissions(); if (!granted) return null; try { await Audio.setAudioModeAsync({ allowsRecordingIOS: true, playsInSilentModeIOS: true, }); const { recording } = await Audio.Recording.createAsync( Audio.RecordingOptionsPresets.HIGH_QUALITY ); currentRecording = recording; return recording; } catch (error) { console.error("Failed to start recording:", error); return null; } } export async function stopRecording(): Promise { if (!currentRecording) return null; try { await currentRecording.stopAndUnloadAsync(); const status = await currentRecording.getStatusAsync(); const uri = currentRecording.getURI(); currentRecording = null; await Audio.setAudioModeAsync({ allowsRecordingIOS: false, }); if (!uri) return null; const durationMs = (status as { durationMillis?: number }).durationMillis ?? 0; return { uri, durationMs }; } catch (error) { console.error("Failed to stop recording:", error); currentRecording = null; return null; } } export async function playAudio( uri: string, onFinish?: () => void ): Promise { try { await stopPlayback(); await Audio.setAudioModeAsync({ allowsRecordingIOS: false, playsInSilentModeIOS: true, }); const { sound } = await Audio.Sound.createAsync( { uri }, { shouldPlay: true } ); currentSound = sound; sound.setOnPlaybackStatusUpdate((status: AVPlaybackStatus) => { if (status.isLoaded && status.didJustFinish) { onFinish?.(); sound.unloadAsync().catch(() => {}); currentSound = null; } }); return sound; } catch (error) { console.error("Failed to play audio:", error); return null; } } export async function stopPlayback(): Promise { if (currentSound) { try { await currentSound.stopAsync(); await currentSound.unloadAsync(); } catch { // Ignore errors during cleanup } currentSound = null; } } export function encodeAudioToBase64(uri: string): Promise { // In React Native, we'd use FileSystem from expo-file-system // For now, return the URI as-is since we may not have expo-file-system return Promise.resolve(uri); }