1

The problem

I'm trying to loop some audio in a React app created with create-react-app using useEffect. I've got it working but there's a short delay between the audio ending and re-starting. I want to use the audio as backing tracks to play guitar to so I need it to loop perfectly smoothly. I'm confident that the track length is correct, I recorded it myself and exported exactly 8 bars, and it loops fine in iTunes.

Current code

Thanks to the accepted answer in this question, my audio player function works fine, and currently looks like this:

import React, { useState, useEffect } from 'react'

const useAudio = audioPath => {
  const [audio] = useState(new Audio(audioPath))
  const [playing, setPlaying] = useState(false)

  const toggle = () => setPlaying(!playing)

  useEffect(() => {
      playing ? audio.play() : audio.pause()
    },
    [playing, audio]
  )

  useEffect(() => {
    audio.addEventListener('ended', () => {
      audio.currentTime = 0
      audio.play()
      setPlaying(true)
    })
  }, [audio])

  return [playing, toggle]
}

const Player = ({ audioPath }) => {
  const [playing, toggle] = useAudio(audioPath)

  return (
    <div>
      <button onClick={toggle}>{playing ? 'Pause' : 'Play'}</button>
    </div>
  )
}

export default Player

The audioPath is passed in and is just a relative path, that loads fine. It plays fine, it pauses fine, it does loop, just with a tiny delay between loops.

What I've tried

As you can see from the code, I've been trying to hijack the audio ended event and setting the audio back to the start of the track but obviously this isn't instant - I'm not really sure how to handle this. I've tried in my first useEffect function checking the time of the audio and if it's within say 500ms of the end of the track setting the time back to 0 but I couldn't get that working, and it seems very hacky and unreliable anyway. Ideally I'm after a proper solution that will work with any tracks as I want to add more.

Demo

Go to the very bottom of the GitHub pages site where this is hosted, expand the very bottom panel and hit play.

NickH
  • 107
  • 1
  • 10
  • An – Kaiido Apr 14 '20 at 13:19
  • @Kaiido I've had a read of that question, makes sense though I'm also not sure how it would fit with React and browser support is a little sketchy. Ultimately I think you're right though, this isn't going to happen with – NickH Apr 14 '20 at 15:18

1 Answers1

0

Ive been playing around with audio a bit recently as well and found that the react-h5-audio-player npm package was the best option for me.

Its got good storyboard examples which include looping and custom controls etc which you might just be able to hide the display by using CSS if you want to keep the single play/pause button you currently have.

Thomas Allen
  • 725
  • 5
  • 17
  • 30
  • I was looking to ideally do it package free but that looks so perfect for my use case I'll give it a shot, thanks. I'll see if there are any pure JS answers but if this works for me I'll accept this answer! – NickH Apr 14 '20 at 13:39
  • Interestingly I still get a delay using this though I think it's possibly slightly shorter, I would be starting to think it was the start of the track itself if it didn't work perfectly in iTunes – NickH Apr 14 '20 at 14:27