簡體   English   中英

Expo AV 播放回調奇怪行為與 state 屬性

[英]Expo AV playback callback strange behaviour with state properties

我開始用這個 go 堅果。 我正在錄制音頻,一旦我停止錄制作為此過程的一部分,我還會加載音頻,以便在必要時可以播放它,在這里我執行setOnPlaybackStatusUpdate 我使用播放回調,以便可以根據positionMillis更新我的currentSeconds state 。

問題是我得到的currentSecondsrecordedDuration state 值。 它們的值如何在觸發音頻播放的playAudio方法和作為回調方法的onPlaybackStatusUpdate之間發生變化?

當我在控制台中使用 output 時,它們在兩種方法中的值都是我期望它們相同時得到的:

In playAudio - currentSeconds: 0
In playAudio - recordedDuration: 4.5
In onPlaybackStatusUpdate - currentSeconds: 115.5
In onPlaybackStatusUpdate - recordedDuration: 0

這是代碼:

const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());
const timerMaxDuration = 120
const [currentSeconds, setCurrentSeconds] = useState<number>(timerMaxDuration);
const [recordedDuration, setRecordedDuration] = useState<number>(0);

const stopRecording = async () => {
        try {
            await AudioRecorder.current.stopAndUnloadAsync();

            // To hear sound through speaker and not earpiece on iOS
            await Audio.setAudioModeAsync({ allowsRecordingIOS: false });

            const recordedURI = AudioRecorder.current.getURI();
            SetRecordingURI(recordedURI)

            AudioRecorder.current = new Audio.Recording();
            send('STOP')

            setRecordedDuration(+(timerMaxDuration - currentSeconds).toFixed(1)) // there is subtraction because during the recording there is a countdown from timerMaxDuration
            setCurrentSeconds(0)
            // Load audio after recording so that it is ready to be played
            loadAudio(recordedURI)
        } catch (error) {
            console.log(error);
        }
    };

    const loadAudio = async (recordedUri) => {
        try {
            const playerStatus = await AudioPlayer.current.getStatusAsync();
            if (playerStatus.isLoaded === false) {
                AudioPlayer.current.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate)
                await AudioPlayer.current.loadAsync({ uri: recordedUri }, { progressUpdateIntervalMillis: 20 }, true)
            }
        } catch (error) {
            console.log(error)
        }
    }

    const playAudio = async () => {
        console.log(`In playAudio - currentSeconds: ${currentSeconds}`)
        console.log(`In playAudio - recordedDuration: ${recordedDuration}`)
        try {
            const playerStatus = await AudioPlayer.current.getStatusAsync();

            if (playerStatus.isLoaded) {
                if (playerStatus.isPlaying === false) {
                    AudioPlayer.current.playAsync();
                    send('PLAY')
                }
            }
        } catch (error) {
            console.log(error);
        }
    };

const onPlaybackStatusUpdate = playbackStatus => {
        if (playbackStatus.isPlaying) {
            console.log(`In onPlaybackStatusUpdate - currentSeconds: ${currentSeconds}`)
            console.log(`In onPlaybackStatusUpdate - recordedDuration: ${recordedDuration}`)
            if(currentSeconds >= recordedDuration){
                stopAudio()
            }
            else{
                setCurrentSeconds(+(playbackStatus.positionMillis / 1000).toFixed(1))
            }
        }
    }

好的,所以播放回調沒有任何問題。 問題是兩個播放回調都是一個箭頭函數,這意味着在回調中唯一會改變的屬性值是參數playbackStatus之一,其他屬性的值將保持與創建function時相同。

React 中的一個解決方法是通過以下方式使用 useEffect,它允許訪問 state 值currentSecondsrecordedDuration

useEffect(() => {
        if(currentSeconds >= recordedDuration)
            stopAudio()
    }, [currentSeconds]);

    const onPlaybackStatusUpdate = playbackStatus => {
        if (playbackStatus.isPlaying)
            setCurrentSeconds(+(playbackStatus.positionMillis / 1000).toFixed(1))
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM