Search code examples
htmlreactjstypescriptnext.jsaudio

React TSX component in NextJs 14.0.4 unable to play local mp3 file but can play external online mp3 file


I'm making a component that wraps html audio and source tags. Currently, it works when playing mp3 files from an external source, like this sound clip https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3. At the same time, it is returns GET 404 error when trying to locate local mp3 files. Why is this?

Component:

type Props = {
    captionText: string,
    src: string,
    type?: string,
    allowDownload: boolean,
}

export default function AudioPlayButton({
    captionText,
    src,
    type = "mp3",
    allowDownload = true,
}: Props) {
    return <div>
        <figure style={{...Style.column, ...Style.spaceAround}}>
            <figcaption style={Style.caption}>{captionText}:</figcaption>
            <audio controls>
                {
                    type == "mp3" ?
                    <source src={src} type="audio/mp3"></source>
                    :
                    <></>
                }
            </audio>
            <p>
                {
                    allowDownload && type == "mp3" ? 
                    <span>Download <a href={src}>MP3</a></span>
                    :
                    <></>
                }   
            </p>
        </figure>
    </div>;
}

In the top-most page.tsx:

'use client'
import AudioPlayButton from '@/components/showcase/ui/AudioPlayButton';
export default function Home() {
  return (
    <main>
This correctly shows sound player UI but with length 0:00 and can't load sound file. Console Returns ERROR 404 GET localhost:3000/name.mp3
<AudioPlayButton captionText={'Play Pronunciation'} src={"./name.mp3"} allowDownload={true}></AudioPlayButton>

This correctly loads mp3 and can play the sound by clicking the ui
<AudioPlayButton captionText={'Play Pronunciation'} src={"https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"} allowDownload={true}></AudioPlayButton>

</main>
    )
}

If I try adding

import namePronunciation from "./name.mp3";

and changing the src to

<AudioPlayButton captionText={'Play Pronunciation'} src={namePronunciation } allowDownload={true}></AudioPlayButton>

NextJs VSCode terminal prints "Module not found: Can't resolve './name.mp3'" which I don't understand?


Solution

  • As far as I know, the mp3 needs to be available for a GET request for the audio tag to fetch it. Which means that it must be available through a web call (to download/stream it to the client browser).

    In your application, that means you need to have the mp3 in your public folder (or a remote as you pointed out) so it can be available through http://<your host>:<your port>/<path-to-mp3>.mp3

    From the path you use in your code, it seems to be located with your source code.

    So, with a bit of folder structure the mp3 file would reside in public/music/name.mp3 then you can send it with URL like:

    <AudioPlayButton captionText={'Play Pronunciation'} src={"/music/name.mp3"} allowDownload={true}></AudioPlayButton>
    

    Note that it starts with /without .in front.

    On default setup when running locally, it would mean that the mp3 is available at http://localhost:3000/music/name.mp3