React Native Sound - after speed up audio and pausing, the time goes back

1.1k Views Asked by At

I have weird problem with react-native-sound library. I added possibility to speed up audio and it works while changing speed when audio is playing. When I press stop button and then start, time goes back on my slider which cause that audio is running, but I can't hear anything as long as time reaches proper time, for example: during playing I speed up audio x2. Audio goes to 20second, then I pause it. After play again, time on slider goes to 10 seconds and as long as don't reach 20seconds, I can't hear anything. Here is my code:


export interface audioStylesProps {
  ...
}

export interface AudioPlayerProps {
  track: {
    url: string,
  }
  audioStylesProps: audioStylesProps
}

const AudioPlayer = (props: AudioPlayerProps) => {

  const [music, setMusic] = useState(null)
  const [isPlaying, setPlaying] = useState(false)
  const [duration, setDuration] = useState(0)
  const [currentTime, setCurrentTime] = useState(0)
  const [speedTime, setSpeedTime] = useState(1)
  const [speedVisible, setSpeedVisible] = useState(false)

  const speedTimeValues = [1.00, 1.25, 1.50, 1.75, 2.00]

  useEffect(() => {
    const audio = new Sound(decodeURI(props.track.url), null, (err) => {
      if (err) {
        return
      }
    })
    Sound.setActive(true)
    Sound.setCategory('Playback', true)
    Sound.setMode('Default')
    setMusic(audio)
    return function cleanup() {
      Sound.setActive(false)
      audio.release()
    }
  }, [props.track])

  useEffect(() => {
    const interval = setInterval(() => {
      if (music && duration <= 0) {
        setDuration(music.getDuration())
      }
      if (music && isPlaying) {
        music.getCurrentTime((seconds: number) => {
          setCurrentTime(seconds)
        })
      }
    }, 100)

    return () => clearInterval(interval)
  })

  const onPlayPausePress = async () => {

    if (music.isPlaying()) {
      music.pause()
      music.setCurrentTime(currentTime)
      setCurrentTime(currentTime)
      setPlaying(false)
    } else {
      music.play(success => {
        setPlaying(false)
      })
      setPlaying(true)
    }
  }

  const manageSpeedTime = (speed) => {
    setSpeedTime(speed)
    music.setSpeed(speed)
  }

  const secondsToHHMMSS = (seconds: number | string) => {
    seconds = Number(seconds)
    const h = Math.floor(seconds / 3600)
    const m = Math.floor((seconds % 3600) / 60)
    const s = Math.floor((seconds % 3600) % 60)

    const hrs = h > 0 ? (h < 10 ? `0${h}:` : `${h}:`) : ''
    const mins = m > 0 ? (m < 10 ? `0${m}:` : `${m}:`) : '00:'
    const scnds = s > 0 ? (s < 10 ? `0${s}` : s) : '00'
    return `${hrs}${mins}${scnds}`
  }

  const onSliderChange = (value) => {
    setCurrentTime(value)
    music.setCurrentTime(value)
  }

  const playOrPauseIcon = isPlaying ? 'pause' : 'play'

  const renderSpeedButtons = () => {
    return speedTimeValues.map((item, index) => {
      return (
        <TouchableOpacity key={index} onPress={() => {manageSpeedTime(item)}} style={{
          justifyContent: "center",
          alignItems: "center",
        }}>
          <Text style={{
            color: speedTime === item ? props.audioStylesProps.activeSpeed : props.audioStylesProps.inactiveSpeed,
            fontSize: 16
          }}>{item}</Text>
          <Margin mBottom={margins.margin4}/>
        </TouchableOpacity>

      )
    })
  }

  return (
    <View style={{ alignSelf: "center", marginTop: margins.margin8, marginBottom: margins.margin8}}>
      <View style={{
        ...
      }}>
        <TouchableOpacity onPress={onPlayPausePress} style={{ width: "10%" }}>
          <Ikcon medium name={playOrPauseIcon} color={props.audioStylesProps.iconColor}/>
        </TouchableOpacity>
          <View style={{flexDirection: "row", width: "30%"}}>
            <Iktext color={props.audioStylesProps.timeColor}>{secondsToHHMMSS(Math.floor(currentTime))} / </Iktext>
            <Iktext color={props.audioStylesProps.timeColor}>{secondsToHHMMSS(Math.floor(duration))}</Iktext>
          </View>
        <Slider
          style={{ width: '55%', height: 40}}
          minimumValue={0}
          maximumValue={duration}
          minimumTrackTintColor={props.audioStylesProps.sliderRunColor}
          maximumTrackTintColor={props.audioStylesProps.sliderStartColor}
          thumbTintColor={props.audioStylesProps.sliderCircleColor}
          value={currentTime}
          onValueChange={onSliderChange}
        />
        <TouchableOpacity onPress={() => {setSpeedVisible(!speedVisible)}} style={{width: "5%", marginLeft: 10}}>
          <Ikcon medium name={"ellipsis_vertical"} color={props.audioStylesProps.speedIconColor}/>
        </TouchableOpacity>
      </View>
      {speedVisible ? <View
        style={{
          ...
        }}
      ><View style={{flexDirection: "column"}}>
        <Margin mTop={margins.margin6}/>
        {renderSpeedButtons()}
      </View>
      </View> : null }
    </View>
  )
}

export default AudioPlayer

Could somebody try to help my find reason why it works like that?

0

There are 0 best solutions below