HTML5音频元素 - 某些Android浏览器误报的音轨长度

时间:2013-10-21 02:09:13

标签: javascript android html5 html5-audio

我正在使用HTML5 <audio>元素处理音频播放器,并尝试跨浏览器解决一些问题。

此播放器配置为在单击不同曲目的链接时在音轨之间切换。在内部,它会暂停<audio>元素,将其currentTime设置为0(如HTML5 audio not playing multiple times in Android 4.0.4 device Native Browser中所述)并在新的<audio>元素之前将其从DOM中删除是使用指定的新源轨道创建的。在元素上调用play()方法来加载轨道并开始播放。

在桌面浏览器,iPhone和iPad上,这很好用。它也适用于同事的三星Galaxy S3 Mini。然而,在不同的测试手机上,全尺寸的三星Galaxy S3,后续曲目的播放失败 - 曲目甚至无法播放,并且在播放栏中显示已完成。我的摩托罗拉Xoom平板电脑上的Android 4.1.2浏览器也是如此。

页面加载时指定的第一首曲目始终正常。

在JavaScript代码中添加了一些调试语句,特别是timeupdate回调函数后,我发现在回放失败的情况下,<audio>元素{{1}在duration引发时,两个实例中的值 1 。通常情况下,持续时间报告为从 350 1000 的任何内容,持续3-4分钟的音轨。这解释了为什么播放栏会立即显示新加载的曲目已完成播放。

我认为后续曲目没有正确加载;即使它先前已经加载并缓存在手机上,它肯定必须能够正确加载。所有曲目都是MP3,可以在各自的浏览器中播放。

我在这里缺少什么?知道问题是什么以及如何使其发挥作用?

非常感谢。

更多信息: 我已将其他事件与timeupdate元素联系起来,以追踪可能发生的事情:

  • <audio>(有关缓冲范围的报告)
  • progress
  • loadedmetadata
  • canplay

在桌面上(这可以正常工作),事件如下: error(持续时间为NaN),timeupdate x3(0个缓冲范围),progressloadedmetadatacanplay,持续时间为121.172368,timeupdate具有1个缓冲范围[0,11.507715],随后是跟踪继续播放的progresstimeupdate事件序列。 iPhone有类似的事件序列。

在Samsung S3上,我收到以下事件:progress持续时间为1,后跟timeupdate(0缓冲范围),progressloadedmetadata,最后一个持续时间为1的canplay

此页面在解释事件和数据结构时非常有用:http://www.sitepoint.com/essential-audio-and-video-events-for-html5/

2 个答案:

答案 0 :(得分:2)

好吧,我终于解决了它:

  • 首先,我更新了音频实现,以便在切换曲目时重复使用相同的<audio>元素,确保在更改src之前暂停音频等。这可能有也可能没有积极的影响,虽然这是一种保证我们没有太多<audio>元素可能在内存中浮动的方法,特别是如果一部未知的手机一次只能处理一个实例。
  • 在切换曲目之前,我添加了一个保护子句来停止当前正在播放的音频,并确保如果没有加载音频,pause()和设置currentTime都不会导致错误:

    if (audioPlayerElement.readyState > 0)
    {
        audioPlayerElement.pause();
        audioPlayerElement.currentTime = 0;
    }
    
  • 由于后续曲目是自动播放的,因此需要修改语句的顺序。

错误报告跟踪持续时间是<audio>元素使用方式问题较大的一个症状。以前,我按如下方式初始化了音频播放器:

  1. 创建<audio>元素/将src设置为MP3曲目的新网址
  2. 致电load()元素
  3. 上的<audio>
  4. 绑定timeupdateended个事件
  5. 由于这是自动播放,因此将autoplay属性添加到<audio>元素
  6. 由于这是一个自动播放,play()元素
  7. 上名为<audio>

    (调试跟踪的loadedmetadatacanplayprogress事件的绑定是在上面的步骤1和2之间执行的。)

    我在这个序列中发现的问题是:

    • 如果设置了play()属性,则调用autoplay是多余的;和
    • 添加autoplay属性应该在load()被调用之前发生,因为一旦有足够的数据被缓冲,load()会自动开始播放曲目。

    因此,最后的步骤是:

    1. src元素的<audio>属性设置为MP3曲目的新网址
    2. 绑定timeupdateended个事件
    3. 由于这是自动播放,因此将autoplay属性添加到<audio>元素
    4. 致电load()元素
    5. 上的<audio>

      play()功能仅在单击播放/暂停按钮或从曲目栏上的特定位置开始播放时适用。

      最后,值得注意的是,在iOS设备和某些Android设备上(取决于浏览器),如果播放器初始化为开始播放页面加载,则会忽略自动播放。在此类设备上,只有执行可以追溯到点击事件(或类似事件)时,自动播放才有效。在更新视觉效果以指示“播放”状态时请记住这一点 - canplay事件处理程序似乎是一个很好的地方。

答案 1 :(得分:0)

我将完全回答你的问题,因为它对我也有用 - 如果你有更好的解决方案,请告诉我:)

我将保留每个声音所需的所有元数据的哈希值。这个哈希可能只是来自服务器的json响应 - 例如:

app.sounds.metadata = {
    "enter the sandman": {
        "artist": "Metaliica",
        "album": "Metallica.",
        "description": "Lorem ipsum dolor sit amet."
        "genre": "metal",
        "duration": 19920,
        "playcount": 312
    },
    "piano man": {
        "artist": "Billy Joel",
        "album": "You're my home",
        "description": "Lorem ipsum dolor sit amet."
        "genre": "Soft rock",
        "duration": 16200,
        "playcount": 135,

    }
}

我的音频元素将被声明为:

<audio data-sound="piano man">
    <source src="piano_man.ogg" type="audio/ogg">
    <source src="piano_man.mp3" type="audio/mpeg">
</audio>

现在,当我使用我的声音时,我可以使用:
var html5offset = 1000

var meta = app.sounds.metadata[sound.getAttribute("data-sound")];
var soundduration = meta.duration || sound.duration*html5offset;