HTML5 音频元素 - 某些 Android 浏览器错误报告的曲目长度
HTML5 Audio element - Track length misreported by some Android browsers
我正在使用HTML5 <audio>
元素开发音频播放器,并试图跨浏览器解决一些问题。
此播放器配置为在单击其他轨道的链接时在音轨之间切换。在内部,它会暂停 <audio>
元素,将其currentTime
设置为 0
(如 HTML5 音频在 Android 4.0.4 设备本机浏览器中未多次播放中所述),并在使用指定的新源轨道创建新的<audio>
元素之前将其从 DOM 中删除。在元素上调用 play()
方法以加载曲目并开始播放。
在桌面浏览器,iPhone和iPad上,这工作正常。它也适用于同事的三星Galaxy S3 Mini。但是,在另一部测试手机(全尺寸三星Galaxy S3)上,后续曲目的播放失败 - 曲目甚至无法播放,并且在播放栏中显示为已完成。在我的摩托罗拉Xoom平板电脑上的库存Android 4.1.2浏览器上也是如此。
页面加载时指定的第一个轨道始终工作正常。
在 JavaScript 代码中添加了一些调试语句,特别是 timeupdate
回调函数后,我发现在播放失败的情况下,引发 timeupdate
时,<audio>
元素的duration
在两个实例中的值为 1。通常,对于 3-3 分钟的曲目,持续时间从 350 到刚刚超过 1000 不等。这就解释了为什么播放栏立即显示新加载的曲目已完成播放。
我认为后续曲目没有正确加载; 即使它之前已经加载并缓存在手机上,它肯定必须能够正确加载。所有曲目都是MP3,可以在相应的浏览器中播放。
我在这里错过了什么?知道问题是什么以及如何让它工作吗?
非常感谢。
更多信息:我已经将其他事件连接到 <audio>
元素以跟踪可能发生的事情:
-
progress
(带有缓冲范围的报告) -
loadedmetadata
-
canplay
-
error
在桌面上(正常工作),事件如下: timeupdate
(具有 NaN 持续时间)、progress
x3(0 个缓冲范围)、loadedmetadata
、canplay
、持续时间为 121.172368 的timeupdate
,progress
具有 1 个缓冲范围 [0, 11.507715],随着曲目继续播放,后跟一系列timeupdate
和progress
事件。iPhone也有类似的事件序列。
在三星 S3 上,我收到以下事件:持续时间为 1 的timeupdate
,后跟 progress
(0 个缓冲范围)、loadedmetadata
、canplay
,最后是持续时间仍为 1 的timeupdate
。
此页面在解释事件和数据结构方面非常有用:http://www.sitepoint.com/essential-audio-and-video-events-for-html5/
好吧,我终于解决了它:
- 首先,我更新了音频实现以在切换轨道时重复使用相同的
<audio>
元素,确保在更改src
之前暂停音频,等等。这可能会也可能不会产生任何积极影响,尽管这是一种保证我们没有太多<audio>
元素可能漂浮在内存中的方法,特别是如果某些未知手机一次只能处理一个实例。 -
在切换曲目之前,我添加了一个保护子句来停止任何当前播放的音频,并确保如果没有加载音频,
pause()
或设置currentTime
都不会导致错误:if (audioPlayerElement.readyState > 0) { audioPlayerElement.pause(); audioPlayerElement.currentTime = 0; }
-
由于后续曲目是自动播放的,因此需要修复语句的顺序。
对轨道持续时间的误报是<audio>
要素使用方式中一个更大问题的征兆。以前,我已经初始化了音频播放器,如下所示:
- 创建
<audio>
元素/将src
设置为MP3曲目的新URL - 对
<audio>
元素调用load()
- 绑定
timeupdate
和ended
事件 - 由于这是自动播放,因此将
autoplay
属性添加到<audio>
元素 - 由于这是一个自动播放,因此在
<audio>
元素上称为play()
(在上面的步骤 1 和 2 之间执行了用于调试跟踪的loadedmetadata
、canplay
、progress
事件的绑定。
我发现这个序列的问题是:
- 如果设置了
autoplay
属性,则调用play()
是多余的;并且 - 添加
autoplay
属性应在调用load()
之前进行,因为一旦缓冲了足够的数据load()
就会自动开始播放曲目。
因此,有效的最后步骤是:
- 将
<audio>
元素的src
属性设置为 MP3 曲目的新 URL - 绑定
timeupdate
和ended
事件 - 由于这是自动播放,因此将
autoplay
属性添加到<audio>
元素 - 在
<audio>
元素上调用load()
play()
功能仅在单击播放/暂停按钮或从轨道栏上的特定位置开始播放时适用。
最后,值得注意的是,在 iOS 设备和某些 Android 设备(取决于浏览器)上,如果播放器初始化为在页面加载时开始播放,则会自动播放。在此类设备上,仅当执行可以追溯到点击事件(或类似事件)时,自动播放才有效。在更新视觉对象以指示"正在播放"状态时,请记住这一点 - canplay
事件处理程序似乎是执行此操作的好地方。
完全回答您的问题,因为它对我也很有用 - 如果您有更好的解决方案,请告诉我:)
我将保留每个声音所需的所有元数据的哈希值。这个哈希可能只是来自服务器的 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;
- 如何通过自己获得Chrome扩展的用户反馈/错误报告
- angularjs$valid-on-dates在firefox中报告错误
- 可以't使用javascript通过soundcloud API向群组添加曲目
- Last.fm API发送2个曲目时,我要求一个,如果我正在听一首歌
- 使用c#中的邮件附件javascript在客户端机器上获取服务器端导出的crystal报告路径.下面的
- 如何将因果报应测试报告上传到声纳
- 在SoundCloud中,使用JavaScript SDK流式传输曲目是否会增加该曲目的playback_count
- "未捕获的语法错误:意外的标记<"当尝试使用谷歌'核心报告API
- 在Meteor js中生成PDF报告
- 使用javascript API响应内部服务器错误将曲目上传到SoundCloud
- 我可以把茉莉花规格报告器的输出写入文件吗
- 为什么jslint报告Unexpected'变量'
- 禁用报告的2个未来日期
- nodejs:child_process.spawn未报告退出代码
- 使用AddThis-config-data_ga_property向两个Google Analytics配置文件报告
- 如何修复JSlint报告的“foo未定义”错误
- 获取 Spotify 用户 [Web API] 当前播放的曲目名称
- Google Analytics(分析)多跟踪帐号维度数据部分未显示在报告中
- 生成图形图表报告
- HTML5 音频元素 - 某些 Android 浏览器错误报告的曲目长度