Drum Machine won't work with local sound files

For my drum machine I want to use files on my computer instead of linking to a sound online, like in the FCC drum machine example, but when I attempt to play these local files I get these errors:

Chrome:

DOMException: The element has no supported sources.

Firefox:

DOMException: The media resource indicated by the src attribute or assigned media provider object was not suitable

I have gone down the stackoverflow rabbit hole but nothing there has helped. I have tried setting the crossOrigin to anonymous (admittedly maybe not correctly), catching the promise of .play() and making sure the file path is correct. My drum machine works fine when I link directly to a sound online but just not with the local files.

If anyone has any insights into what is happening please let me know.

The specific code I am having trouble with is Here on GitHub (it’s a bit messy with commented out code and other stuff from testing different solutions)

just incase it’s important, I am working in vs code and used create-react-app.

If you want to use a resource in React (audio, video…), you have to import it first, and useRef as a reference to the resource. What worked for me was something like this:

import React, {useRef} from 'react'
import audioSrc from `./soundfile.mp3`

const drumPad = () => {
  const sound = useRef(null)
  
  const play = () => {
   sound.current.currentTime=0;
   sound.current.play()
 }

 return (
    <>
       <audio src={audioSrc} ref={sound}></audio>
       <button onClick={play}>play</button>
    </>
 )
}

Edit2: It does seem to work when I remove the homepage property in the package.json, I think I just messed up the path when I was doing it the second time.

To get it working all I did was remove the property, move the sounds folder to the public folder, and then just add back the old click handler code.

Edit: Well apparently there is more to it then that. I just tried to reproduce it and it didn’t work. Now I have to backtrack again to see what else I did to make it work. All I know is removing that property in the package.json file was the last thing I did before it worked.


Man, this really had me stumped.

As far as I can tell it is caused by the homepage property in the package.json file. I don’t know why it is causing this issue but I tried a bunch of stuff and it wasn’t until I removed that from the package.json file that it worked.

I used the same local files setup I use in my own project and it should have 100% been working but it didn’t. I tried a bunch of different things but nothing changed anything (different audio sources and a bunch of random little things).

The only difference so far I can find is with that property in the package.json file when I look at the source file in the console as an object I see this property on it.

error: MediaError {code: 4, message: "DEMUXER_ERROR_COULD_NOT_OPEN: FFmpegDemuxer: open context failed"}

I have no idea what is causing it.

BTW. You can’t use the Audio constructor for this project. The tests require you to use audio elements. Also, using refs may pose an issue with the keyboard requirements.

As for the local setup. You can use the public folder for the audio files and link to them in the drumBank objects.

{
  keyCode: 81,
  keyTrigger: 'Q',
  id: 'closed-hat',
  url: './sounds/closed-hat.wav'
}

Folder: public/sounds

Using import has worked and I noticed that it works without useRef. Is there a way to import all the sounds from the folder at once instead of each sound having an individual import statement? Also moving the sounds to the public folder seems to break the import, giving this error:

Module not found: You attempted to import ../../public/sounds/A.mp3 which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.

I am also confused as to how the drumbank objects url property would work with the import statements?

Thanks for your help so far.

You have two possibilities:

  • put the files somewhere inside the src folder (that’s the only place where you can import a resource like an image or a soundfile from, with an import statement at the top of your file)
  • add an element in your return statement/render method with the src attribute pointing at that imported resource

The other way is what @lasjorg did:

  • put the files into the public folder
  • add an element in your return statement/render method with the src attribute pointing to a URI relative to the public folder

I use these things so rarely, so I’m a bit on thin ice. I can’t even tell what’s the better choice. If you go for the first method, you’ll need as many import statements as you have sound files. With the second, you only need an array of URIs (or an array of drumBank objects) that you map over, and return the audio elements with their respective src attribute set.

I ended up getting it to work with the first solution since the second kept giving me the same errors that I started with lol. Also I somehow didn’t realize two separate people responded, I thought it was just @jsdisco, my b lol. But thank you both for the help :slight_smile:

Apparently, it is the subfolder path for the homepage property that is doing it.

Not sure if this is a bug or what but when using the homepage property with a subfolder path the audio file shows up as 206 Partial Content in the network tab and the Content-Type of the audio files are Content-Type: text/html; charset=UTF-8 which is not correct.

With subfolder path for the homepage property:

Without subfolder path for the homepage property:

The MIME type of the actual source file in the DOM is correct.

I’m guessing this issue is specific to create-react-app but I didn’t really look into it much.