Search code examples
reactjstypescriptaudiomp3html5-audio

How to set the duration of the audio in React/Typescript?


I'm working on a web app using React and TypeScript. I made a component called SoundEffect, which takes the sound type as a prop, and plays the mp3 according to its type.

interface ISoundEffectProps {
    soundType: string,
    // duration?: number, <- want to add this
}

const SoundEffect: React.FunctionComponent<ISoundEffectProps> = (props) => {
  const sound = soundSelector(props.soundType)
  return (
    <div>
        <audio src={sound} autoPlay></audio>
    </div>
  );
};

export default SoundEffect;

soundSelector() takes the soundType as a string and returns an mp3 file. Now, I want to add duration to this, so when this component is rendered, like this:

<SoundEffect soundType="count-down" duration=3000/>

it only plays for 3 seconds and stops. Right now, I have to prepare separate mp3 files for different durations, which seems redundant. I can't add any buttons to this component, so I don't think I can have a component that can fire a function (correct me if I'm wrong). If anyone knows any solution or libraries/packages that would help me solve this issue, then please help me. Thanks

------I'll write a solution in below------

interface ISoundEffectProps {
  id: string,
  soundType: string,
  duration?: number,
}

const SoundEffect: React.FunctionComponent<ISoundEffectProps> = (props) => {
  const sound = soundSelector(props.soundType); // "../assets/sounds/example.mp3"
  const audio = document.getElementById(props.id) as HTMLAudioElement; 
// without "as HTMLAudioElement", audio becomes HTMLElement, which does not have pause() method. 

  function startTimer(duration: number) {
    if (audio != null) { // <- audio.pause() creates uncaught typeerror when audio is null
      const interval = setInterval(() => {
        audio.pause();
      }, duration 1000);
    }
  }
  return (
    <div>
        <audio autoPlay id={props.id} onPlay={()=> startTimer(props.duration || 10)}>
          <source src={sound} type="audio/mp3"/>
        </audio>
    </div>
  );
}

Now, I can call for this component like:

<SoundEffect id="beep_id", soundType="beep", duration={5}/>

This component stops its sound after 5 seconds. If I put duration={10}, it stops after 10 seconds.


Solution

  • You could use set interval to pause the playback after a duration.

    function startTimer(duration) {
     const interval = setInterval(() => {
         audioRef.pause()
        }, duration * 1000);
    }
    ...
    
    <audio src={sound} autoPlay onplay={()=> startTimer(duration)}></audio>