Reputation: 91
I am making a piano app. I have a js function in a react component that plays the corresponding file to the note provided but the console always throws this error:
Uncaught (in promise) DOMException: The media resource indicated by the src attribute or assigned media provider object was not suitable.
And no sound is played. Here is the function:
var handleClick = (note) => {
var path = "../../public/notes/" + note + ".mp3";
var audio = new Audio(path);
audio.play();
console.log(audio);
return audio.play();
};
Also my file structure is:
App
public
node_modules
src
Components
Piano.js
Upvotes: 4
Views: 12475
Reputation: 24
You need to use a source tag inside the audio element like this:
<audio
ref={audioRef}
onDurationChange={(e) => handleDuration(e.currentTarget.duration)}
onEnded={handleOnEnd}
onTimeUpdate={(e) => updateCurrentTime(e.currentTarget.currentTime)}
>
<source src={trackSrc} type="audio/mpeg" />
Your browser does not support the audio element.
</audio>
Upvotes: 0
Reputation: 321
I faced same problem today and resolved it.
I'm using [https://vitejs.dev/|vite] and found out that for assets like sound of different types (For me its *.m4a) need to add that within configuration file of vite i.e vite.config.mjs like mentioned here https://vitejs.dev/config/shared-options#assetsinclude
Upvotes: 0
Reputation: 11
I ran into the same problem and couldn't figure out why it wouldn't accept it from folder path.
I found another thread where someone used a url as the source and it worked for me. Example url: http://streaming.tdiradio.com:8000/house.mp3
I ended up uploading my sound file to a public amazon s3 bucket and using the url and the react app worked with my desired sound like that, by using the url.
Upvotes: 1
Reputation: 31
I think the answer is very simple, so much that makes me feel weird repeating it. Chrome does not allow media playing unless it has controls. Your code is just calling the media while the client does not have access to pausing or stopping it.
Simply add any audio player controller to your file and it should work just fine as it does in FireFox.
Upvotes: 0
Reputation: 1214
2 ways for implementing this senario:
1- using UIFX package:
// Note: Player.js and music file located in src
import music from './music.mp3'
import UIFx from "uifx";
export default function Player(){
const sound = new UIFx(music , {
volume: 0.8,
});
sound.play();
// 2-way => custom function
const playTheSound = () =>{
var audio = new Audio(music);
audio.play();
// it works in FireFox but chrome raise error that you can not play manualy.
}
return <p>Player</p>
}
Upvotes: 0
Reputation: 1089
Seems there's a problem with your path
Since you are trying to access the file path and its in your public folder, try using this
process.env.PUBLIC_URL + "/notes/" + note + ".mp3"
or
window.location.origin + "/notes/" + note + ".mp3"
or access it directly using
notes/ + note + ".mp3"
Let's see how your public folder is structured
Upvotes: 0
Reputation: 18408
Make sure your mp3 files are encoded as per these specifications. You can use any offline or online tool to check your file info.
Maybe you've just renamed the extension to mp3 of some other audio file. Can you share your file somewhere?
Also, don't load files when user clicks on piano keys. Try to preload all sound files like this:
// handle all promise rejections
window.onunhandledrejection = function(event) {
console.log(`Reason: ${event.reason}`,
` Return value: ${event.returnValue}`
);
};
let mouseDown = false;
let sounds = {
a: "https://freesound.org/data/previews/448/448573_9311684-lq.mp3",
b: "https://freesound.org/data/previews/448/448565_9311684-lq.mp3",
c: "https://freesound.org/data/previews/448/448540_9311684-lq.mp3",
d: "https://freesound.org/data/previews/448/448600_9311684-lq.mp3",
}
// preload audio files
let promises = [];
Object.keys(sounds).forEach(s => {
promises.push(new Promise((resolve, reject) => {
let url = sounds[s];
sounds[s] = new Audio();
sounds[s].addEventListener('canplaythrough', resolve, false);
sounds[s].src = url;
}));
});
Promise.all(promises).then(() => {
stats.innerText = `All audio files loaded! Drag mouse over the keys 😋`;
stats.style.color = 'green';
init();
}).catch(e => {
console.log('error loading audio files: ', e);
stats.innerText = 'Error loading audio files, see console logs.'
});
function init() {
Object.keys(sounds).forEach(s => {
document.querySelectorAll(`.${s}`).forEach(k => {
k.addEventListener('mousedown', () => {
sounds[s].play();
});
k.addEventListener('mouseenter', () => {
if (mouseDown)
sounds[s].play();
});
k.addEventListener('mouseup', () => {
sounds[s].currentTime = 0;
sounds[s].pause();
});
k.addEventListener('mouseleave', () => {
sounds[s].currentTime = 0;
sounds[s].pause();
});
})
});
piano.addEventListener('mousedown', () => mouseDown = true);
piano.addEventListener('mouseup', () => mouseDown = false);
piano.addEventListener('mouseleave', () => mouseDown = false);
}
* {
box-sizing: border-box;
margin: 0;
}
.piano {
height: 100px;
width: 100vw;
padding: 0 1rem 0 1rem;
}
.key {
float: left;
max-width: 50px;
width: 10%;
height: 100%;
padding-bottom: .5rem;
margin-right: 0px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
border: 1px solid gray;
border-radius: 0 0 .6rem .6rem;
cursor: pointer;
user-select: none;
color: gray;
}
.key:hover {
box-shadow: inset -2px 0px 1px 3px wheat;
}
.key:active {
box-shadow: inset -3px 0px 1px 2px rgb(212, 180, 120);
}
#stats {
position: absolute;
left: 1rem;
bottom: 1rem;
color: darkred;
}
<div id="piano" class="piano">
<div class="key a">A</div>
<div class="key b">B</div>
<div class="key c">C</div>
<div class="key d">D</div>
<div class="key a">A</div>
<div class="key b">B</div>
<div class="key c">C</div>
<div class="key d">D</div>
</div>
<div id="stats">Loading audio...</div>
Upvotes: 2
Reputation: 1
It might be your path, but try await
1st: Make sure your paths are correct! There have been so many times where I just misspelled something and it caused a weird/ confusing error. You can simply console.log(path)
and see if it matches.
2nd: Adding audio.type("audio/mp3")
before audio.play
can help your code quickly know what type of file it's looking for and how to read it. But from what I've seen this is optional.
3rd: try awaiting the audio file
Here is the code all together:
var handleClick = async (note) => {
var path = "../../public/notes/" + note + ".mp3";
var importRes = await import(path);
var audio = new Audio(importRes.default);
audio.type = "audio/mp3";
try {
await audio.play();
console.log("Playing audio" + audio);
} catch (err) {
console.log("Failed to play, error: " + err);
}
};
Upvotes: 0