我正在制作一个钢琴应用程序。我在 React 组件中有一个 js 函数,可以根据提供的注释播放相应的文件,但控制台总是抛出此错误:
未捕获(承诺中)DOMException:src 属性指示的媒体资源或分配的媒体提供程序对象不合适。
并且没有声音播放。这是函数:
var handleClick = (note) => {
var path = "../../public/notes/" + note + ".mp3";
var audio = new Audio(path);
audio.play();
console.log(audio);
return audio.play();
};
我的文件结构是:
App
public
node_modules
src
Components
Piano.js
确保您的 mp3 文件按照 这些规范 进行编码。您可以使用任何离线或在线工具来检查您的文件信息。也许您刚刚将其他音频文件的扩展名重命名为 mp3。您可以在某处共享您的文件吗?
另外,当用户单击钢琴键时不要加载文件。尝试像这样预加载所有声音文件:
// 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>
我遇到了同样的问题,但不明白为什么它不从文件夹路径接受它。
http://streaming.tdiradio.com:8000/house.mp3
我最终将我的声音文件上传到公共亚马逊 s3 存储桶并使用该 url,而 React 应用程序通过使用该 url 来处理我想要的声音。
第一:确保您的路径正确!有很多次我只是拼错了一些东西,这导致了一个奇怪/令人困惑的错误。您只需 console.log(path)
第二:在
audio.type("audio/mp3")
之前添加audio.play
可以帮助你的代码快速知道它要查找的文件类型以及如何读取它。但据我所知,这是可选的。
第三:尝试等待音频文件这是全部代码:
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);
}
};
你的路径似乎有问题
process.env.PUBLIC_URL + "/notes/" + note + ".mp3"
或
window.location.origin + "/notes/" + note + ".mp3"
或直接使用访问它
notes/ + note + ".mp3"
让我们看看您的公用文件夹的结构
实现此方案的 2 种方法:
UIFX
包: 我认为答案非常简单,以至于重复它让我感觉很奇怪。 Chrome 不允许媒体播放,除非有控件。您的代码只是调用媒体,而客户端无权暂停或停止它。
我今天遇到了同样的问题并解决了。