【问题标题】:HTML5 Audio element - Track length misreported by some Android browsersHTML5 音频元素 - 某些 Android 浏览器误报音轨长度
【发布时间】:2013-10-29 09:30:40
【问题描述】:

我正在使用 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>元素的duration的值为1 在引发timeupdate 的两种情况下。通常,持续时间报告为从 350 到刚刚超过 1000 的 3-4 分钟曲目。这就解释了为什么播放栏会立即将新加载的曲目显示为已完成播放。

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

我在这里缺少什么?知道问题出在哪里以及如何让它发挥作用吗?

非常感谢。

更多信息: 我已将其他事件连接到 <audio> 元素以跟踪可能发生的情况:

  • progress(带有缓冲范围的报告)
  • loadedmetadata
  • canplay
  • error

在桌面(正常工作的地方)上,事件如下: timeupdate(具有 NaN 持续时间),progress x3(0 个缓冲范围),loadedmetadatacanplaytimeupdate,持续时间为 121.172368,progress,具有 1 个缓冲范围 [0, 11.507715],然后是随着曲目继续播放,一系列timeupdateprogress 事件。 iPhone 也有类似的事件序列。

在三星 S3 上,我收到以下事件:timeupdate,持续时间为 1,然后是 progress(0 个缓冲范围),loadedmetadatacanplay,最后是持续时间为 timeupdate仍然是 1。

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

【问题讨论】:

  • 为什么要使用播放时间等待删除元素,而不是使用声音播放完毕后触发的ended 事件?
  • 我不会在timeupdate 上切换曲目;我已经更新了问题以尝试澄清这一点。由于曲目长达几分钟,因此网站访问者很可能会通过单击适当的曲目链接在播放过程中在曲目之间切换。我已经连接了ended 事件来处理这种情况,尽管在我所指的场景中不会出现这个事件。
  • 我正在研究他们如何在 soundmanager2 中获得持续时间,但看起来他们也没有真正解决问题的方法:github.com/scottschiller/SoundManager2/blob/master/script/…
  • 你能检查一下持续时间是否无效,然后通过ajax从服务器获取持续时间吗?
  • 我的印象是 duration 是根据 MP3 本身的 loadedmetadata 事件计算的。这似乎也取决于浏览器 - 相同的 3:24 长轨道在 iPhone 上的持续时间为 205.4008,但在 Galaxy S3 上为 946.4950。

标签: javascript android html html5-audio


【解决方案1】:

好吧,我终于解决了:

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

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

曲目持续时间的误报是<audio> 元素的使用方式存在较大问题的征兆。之前,我已经将音频播放器初始化如下:

  1. 创建<audio> 元素/将src 设置为MP3 曲目的新URL
  2. <audio> 元素上调用load()
  3. 绑定timeupdateended事件
  4. 由于这是自动播放,因此将autoplay 属性添加到<audio> 元素
  5. 由于这是自动播放,因此在 <audio> 元素上称为 play()

loadedmetadatacanplayprogress 事件的绑定在上面的步骤 1 和 2 之间执行。)

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

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

因此,最后的工作步骤是:

  1. <audio>元素的src属性设置为MP3曲目的新URL
  2. 绑定timeupdateended 事件
  3. 由于这是自动播放,请将autoplay 属性添加到<audio> 元素
  4. <audio> 元素上调用load()

play() 函数仅在单击播放/暂停按钮或从轨迹栏上的特定位置开始播放时适用。

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

【讨论】:

    【解决方案2】:

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

    我将保留每个声音所需的所有元数据的哈希值。此哈希可能只是来自服务器的 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;
    

    【讨论】:

    • 感谢您的帮助。我发现误报的持续时间是更深层次问题的征兆 - 请参阅我的答案了解详情。
    猜你喜欢
    • 2015-03-25
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 2012-06-09
    • 2012-04-18
    • 1970-01-01
    相关资源
    最近更新 更多