如果 src 静态设置,则 html5 音频播放,但如果动态设置则不播放

Posted

技术标签:

【中文标题】如果 src 静态设置,则 html5 音频播放,但如果动态设置则不播放【英文标题】:html5 audio plays if src set statically but not if set dynamically 【发布时间】:2012-08-29 14:49:16 【问题描述】:

我有一个问题,如果将音频文件作为 src 属性直接添加到 html5 源代码中,我可以播放它,但如果我尝试在运行时设置 src,它不会播放。

最初我有以下包含一些音频标签的 HTML:

<audio id="audio1" controls preload="none" src="http:/theurl/clip1.mp3"></audio>
<audio id="audio2" controls preload="none" src="http:/theurl/clip2.mp3"></audio>

使用以下函数播放剪辑,该函数使用 id 和剪辑 url 调用:

function audioClick(id, clip) 
    var audio = document.getElementById(id);
    if (audio.paused) 
        audio.play();
    
    else 
        audio.pause();
        audio.currentTime = 0;
    

这很有效,当用户点击页面的相关部分时,相应的音频文件就会播放,但问题是浏览器需要大约 3-4 秒来加载页面,这太长了。我已经找到了延迟的原因是由于 src 属性是远程文件。并且将 preload 设置为“none”或“metadata”并不能加快速度。

为了解决这个问题,我想在运行时设置 src,所以将函数更改为:

function audioClick(id, clip) 
    var audio = document.getElementById(id);
    if (audio.paused) 
        audio.setSrc(clip);
        audio.load();
        audio.play();
    
    else 
        audio.pause();
        audio.currentTime = 0;
    

我尝试将 html 设置为此

<audio id="audio1" controls></audio>
<audio id="audio2" controls></audio>

但是有两个问题: 1)音频不播放 2) 控件显示一条初始消息,说明文件无法播放

我没有在控件中显示无法播放文件的消息,因此我将 html 更改为:

<audio id="audio1"></audio>
<audio id="audio2"></audio>

但是文件不播放的问题仍然存在。

为什么这样做后音频文件不播放?

【问题讨论】:

根据 W3C 规范,setSrc 似乎不是 HTMLAudioElement 的方法。您只是想设置src 属性吗? 【参考方案1】:

当您的目标是 ios 时,会有一些陷阱。第一个是设置音频标签的属性 preload 什么都不做。 iOS 只会做它想做的事,对此我们无能为力。

我认为 Yoshi 的代码在 chrome 中运行良好但在 iOS 中运行良好的原因是因为 iOS 要求对 audio.play() 的所有调用都与单击事件在同一个调用堆栈中。由于 canplay 事件的调用结果我认为它被 iOS 忽略了。此外,当您设置 src 时,iOS 不会预加载任何音频。您需要调用 audio.load() 来执行此操作,但就像以前一样,您需要用户单击某些内容才能让 iOS 实际执行该功能。

要使其在 iOS 中运行,您需要避免 canplay 回调并简单地使用:

audio.src = src;
audio.play();

这不太理想。 Safari 加载文件时可能需要一两秒钟,但它应该可以工作。与 android 浏览器或更好的新移动 chrome 相比,iOS 对 HTML5 音频的处理相当有限。移动 Safari 有点把规范抛到了窗外,只是做它想做的事。

【讨论】:

谢谢,但这与我在上面发布的 javascript 代码的第二部分有何不同。您在帖子中提到 load() 但在代码 sn-p 中没有它,在哪里/何时调用 load() 是否重要? 抱歉,对于 iOS,调用 load() 并不重要,因为在 iOS 的移动版 Safari 下,加载和播放都需要用户触发点击操作。因此,如果 iOS 是主要目标,您不妨调用 play()。与您上面的代码没有什么不同,只是您确实需要 audio.src = src 就像 Yoshi 所说的不是您所拥有的 setSrc。【参考方案2】:

尝试类似:

function audioClick(id, src) 
  var audio = document.getElementById(id);
  if (audio.paused) 
    audio.addEventListener('canplay', function canplay() 
      this.removeEventListener('canplay', canplay, false);
      this.play();
    , false);

    audio.src = src;
  
  else 
    audio.pause();
    audio.currentTime = 0;
  

看看其他可用的media events。

【讨论】:

谢谢。但是我无法让它工作,canplay() 函数永远不会被调用。我应该为 html 设置什么? @Mungbeans 你在用什么浏览器测试。我只用 Chrome 来写上面的代码。 Yoshi 我使用的是 KomodoEdit 的默认浏览器和 iOS(这是我的目标浏览器,应该完全支持 html5 音频)。但是我改用了 KomodoEdit 的 Chrome 并且它起作用了。我会将您的答案标记为已接受,但我现在必须看看是否有任何解决方法可以使其在 iOS 上运行。 (不知道为什么 KomodoEdit 中的默认浏览器也不起作用)

以上是关于如果 src 静态设置,则 html5 音频播放,但如果动态设置则不播放的主要内容,如果未能解决你的问题,请参考以下文章

HTML5音频和视频

如果 DOM 中不存在视频/音频元素,如何设置 html5 视频/音频的播放速度

HTML5 音频播放器。无法更改 src 元素

HTML5中audio标签的使用

注入 src URL 后 HTML5 音频不播放

Html5之高级-5 HTML5音频处理(在H5中播放音频编程实现音频播放器)