【问题标题】:Play audio with React使用 React 播放音频
【发布时间】:2019-10-29 07:37:13
【问题描述】:

无论我做什么,在尝试播放声音时都会收到一条错误消息:

未捕获(承诺)DOMException。

在 Google 上搜索后,我发现如果我在用户对页面进行任何操作之前自动播放音频,它应该会出现,但对我来说并非如此。我什至这样做了:

componentDidMount() {
  let audio = new Audio('sounds/beep.wav');
  audio.load();
  audio.muted = true;
  document.addEventListener('click', () => {
    audio.muted = false;
    audio.play();
  });
}

但是消息仍然出现并且声音没有播放。我该怎么办?

【问题讨论】:

  • 服务器上是否存在“sounds/beep.wav”文件?你确定相对路径正确吗?
  • 如果将前三行的语句放在事件处理程序的开头,错误消息是否仍然存在?如果您删除将 audio.play() 放在 componentDidMount 末尾的事件处理程序,它是否仍然存在?
  • 文件存在于“服务器”上。那是我自己的电脑,我有它在 /src/sounds 文件夹和 /src 中的 App.js。我不知道它是否是重复的。我不是要自动播放,它应该在用户点击后播放。虽然我也试过了,但我可以捕捉到错误,但我该怎么办?
  • 错误仍然存​​在于componentDidMount() { document.addEventListener("click", () => { let audio = new Audio("sounds/beep.wav"); audio.load(); audio.play(); }) }

标签: javascript reactjs


【解决方案1】:

我认为最好使用这个组件 (https://github.com/justinmc/react-audio-player) 而不是直接的 dom 操作

【讨论】:

  • 还是一样。我的代码与该组件看起来像这样:function() { this.refs.audioEl.pause(); this.refs.audioEl.currentTime = 0; this.refs.audioEl.play(); } render(){ return( <ReactAudioPlayer src="sounds/beep.wav" ref={(element) => { this.refs = element; }} autoPlay /> ) }
  • 可能你应该使用controls 属性来控制音乐?而不是使用参考?
  • 添加了控件,但还是一样。音频播放器显示为灰色。我不想显示控件,音频应该在点击网站的其他组件时播放。
  • 如果我必须分配新的网址怎么办?
【解决方案2】:

音频是HTMLMediaElement, and calling play() returns a Promise,所以需要处理。根据文件的大小,它通常已经准备好了,但如果它没有加载(例如挂起的 promise),它会抛出“AbortError”DOMException。

您可以先检查它是否已加载,然后捕获错误以关闭消息。例如:

componentDidMount() {
      this.audio = new Audio('sounds/beep.wav')
      this.audio.load()
      this.playAudio()
}

playAudio() {
    const audioPromise = this.audio.play()
    if (audioPromise !== undefined) {
      audioPromise
        .then(_ => {
          // autoplay started
        })
        .catch(err => {
          // catch dom exception
          console.info(err)
        })
    }
}

另一种运行良好但没有显示错误的模式是将组件创建为具有autoPlay 属性的HTML audio element,然后在需要时将其呈现为组件。例如:


const Sound = ( { soundFileName, ...rest } ) => (
  <audio autoPlay src={`sounds/${soundFileName}`} {...rest} />
)

const ComponentToAutoPlaySoundIn = () => (
   <>
     ...
     <Sound soundFileName="beep.wav" />
     ...
   </>
)

【讨论】:

  • 是的,我已经尝试过了,我可以捕捉到错误并且 console.log 说“DOMException”。有时我必须单击两次才能使 console.log 出现。如果我 console.logged in 然后分支什么都没有出现。音频从未开始。我也尝试在另一个组件中渲染它。
  • @HenrikHollósi 好的,所以你有一个元素(我们称之为按钮),当你点击它时,它应该播放本地/静态声音而不会显示任何错误。那是对的吗?还是有什么其他功能?打算更新一下。
  • 是的,基本上就是这样。它还有一个逻辑,这样按钮应该启动一个计时器计数为零,当计时器达到零时播放音频。
  • @HenrikHollósi Codesandbox Sample。您可能已经知道如何做到这一点,但只是想看看我是否可以复制您的错误。起初我遇到了相同的 console.log 错误,但查看它们显示它们要么是“NotAllowed”(意味着浏览器设置阻止了音频),要么是“NotSupported”(意味着不兼容的文件类型或 CORS 试图获取文件的问题) .尝试应用到您的代码并注销音频承诺,看看抛出了什么样的错误,这应该有助于您找到更准确的解决方案。
  • 所以,我应用了您的解决方案,它必须对链接做一些事情。如果我提供自己的文件,我会收到“DOMException”、“消息:该元素没有支持的来源”。记录承诺。如果我使用来自外部来源的声音,例如您的链接,它就可以正常工作。我绝对确定我为自己的文件使用了有效的 url,我仔细检查了两次。也许我无法使用从 soundbible 下载的声音。
【解决方案3】:

简单的错误提示音

如果您想要像播放简单的错误提示音这样简单的事情(例如,在条形码扫描仪环境中用于非视觉反馈),并且不想安装依赖项等 - 它可以非常简单。只需链接到您的音频文件:

import ErrorAudio from './error.mp3'

并在代码中,引用它并播放它:

var AudioPlay = new Audio (ErrorAudio);
AudioPlay.play();

在弄乱了更复杂的选项后才发现这一点。

【讨论】:

    猜你喜欢
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 2017-10-15
    • 2021-10-17
    • 2012-09-14
    相关资源
    最近更新 更多