从 Javascript 播放 <audio> + <video> 的正确方法
Posted
技术标签:
【中文标题】从 Javascript 播放 <audio> + <video> 的正确方法【英文标题】:Correct way to play <audio> + <video> from Javascript 【发布时间】:2013-04-28 11:13:18 【问题描述】:我在使用 和
假设我使用的是 preload="auto" 或 preload="metadata" :
audio.src = "filename";
audio.play();
这似乎在 Firefox 和 Chrome 中都可以正常工作,但我想使用 preload="none" 然后 Chrome dossent 播放。
所以我正在尝试使用 preload="none" 的代码:
audio.src = url;
audio.load();
audio.addEventListener('canplay', function(e)
audio.play(); // For some reason this dossent work in Firefox
, false);
audio.play(); // Added this so Firefox would play
我不知道这样做是否正确。
我正在使用: 火狐 20.0.1 铬 25.0.1364.172 米
我做了一个演示:http://netkoder.dk/test/test0217.html
编辑:
在第二个音频播放器(在演示页面上)似乎使用 preload="none" 时必须使用 load()。 但是在 load() 之后立即使用 play() 是正确的,还是在播放之前使用事件等待文件加载的正确方法?
在第三个音频播放器中,似乎 Firefox 20.0.1 dossent 在与 addEventListener() 一起使用时正确支持 canplay 事件,因为它在 load() 之后触发,它在 play() 之后触发,并且在擦洗声音时也会触发dossent 似乎是 canplay 应该工作的方式。 使用 .oncanplay 确实有效。
所以下面的代码似乎可以工作:
function afspil2(url)
afspiller2.src = url;
afspiller2.load(); // use load() when <audio> has preload="none"
afspiller2.play();
function afspil3(url)
afspiller3.src = url;
afspiller3.load(); // use load() when <audio> has preload="none"
//afspiller3.addEventListener('canplay', function() // For some reason this dossent work correctly in Firefox 20.0.1, its triggers after load() and when scrubbing
// afspiller3.play();
//, false);
afspiller3.oncanplay = afspiller3.play(); // Works in Firefox 20.0.1
我更新了演示以包含更改:http://netkoder.dk/test/test0217.html
我在 afspil3() 函数中添加 addEventListener 的方法看起来不错,因为第一次调用该函数时,addEventListener 中的代码被调用了 1 次。第二次调用函数,addEventListener里面的代码被调用了2次,然后是3次,以此类推。
【问题讨论】:
你能提供一个完整的例子来说明你在哪里设置preload="none"
并且它不起作用吗?
演示:netkoder.dk/test/test0217.html
【参考方案1】:
这是因为您的audio
标记缺少必需的src
属性或<source>
标记。当我将它们添加到您的演示中时,所有 3 名玩家都立即开始在 Chrome 和 FF 中工作。
另外,我最近发现src
不能是空字符串,后来用JS改了。如果有一个原因你不能在 HTML 中设置 src
,你最好的选择,IMO,是用 Javascript 创建 audio
元素:
var audio = new Audio();
audio.src = url;
audio.controls = true;
audio.preload = false;
// and so on
编辑:好的。似乎在Chrome中,当HTML为preload="none"
时,当src
改变时,需要在播放前调用load()
。你的第二个audio
没有预加载,所以你的函数需要是这样的:
function afspil2(url)
afspiller2.src = url;
afspiller2.load(); // add load call
afspiller2.play();
那么,在 Firefox 中,似乎需要在将事件附加到 canplay
事件时设置 preload="auto";
,就像在第 3 个函数中一样。
function afspil3(url)
afspiller3.src = url;
afspiller3.preload = "auto";
afspiller3.load();
afspiller3.addEventListener('canplay', function(e)
this.play(); // For some reason this dossent work in Firefox
, false);
这看起来很奇怪,但是我测试了很多次,每次调用preload="auto"
时它都会播放,但如果不调用它就不会播放。请注意,第二个播放器不是必需的,它也是 HTML 标记中的 preload="none"
。
最后,如果页面上有多个<audio>
元素,Chrome 会出现一些奇怪的行为。对于所有三个玩家,重新加载页面并单击“大电子”链接将正常播放。
重新加载然后在第 2 位或第 3 位玩家上单击“Yoda”不会做任何事情,但它会为第一个玩家播放。但是,如果以任何方式首先播放***玩家 - 播放按钮或任一链接 - 然后其他两个“尤达”链接将突然起作用。
另外,如果您在重新加载后先点击第 2 或第 3 个“Yoda”链接,然后点击顶部玩家,则之前点击的“Yoda”(之前未播放)将在***玩家停止。
只要说他们有一些错误需要解决就足够了。
【讨论】:
如果启动音频播放器,添加 src 会播放该文件,但如果您尝试通过播放器上方的链接更改音频源,我的 Javascript 代码仍然无法正常工作。 @scootergrisen 刚刚添加了一个编辑。伙计,HTML5<audio>
还没有达到它需要的位置。我实际上通过 W3C 验证器运行了您的 HTML,因为我认为也许多个 ID 或其他东西可以解释疯狂的行为。不,没有错误。它只是还没有很好地开发。
没关系,它还没有开发出来,并且不能在所有浏览器中运行,我喜欢生活在边缘:D 但我想知道正确的方法是什么。
load() 修复了第二个音频播放器。是的,Chrome 有一些奇怪的问题,但这不是问题,我只想知道编写代码的正确方法是什么。意味着标准的 W3C 方式,即使它现在不能在浏览器中正常工作。无论如何,我刚刚发现 Firefox dossent 在与 addEventlistener() 一起使用时似乎支持 canplay 事件,但它确实支持 oncanplay 事件。【参考方案2】:
我认为正确的方法是使用现有的解决方案,例如http://mediaelementjs.com/
如果您真的对使用 js 播放音频和视频的最佳方式的详细信息感兴趣,请查看源代码: https://github.com/johndyer/mediaelement/tree/master/src/js
https://github.com/johndyer/mediaelement/blob/master/src/js/me-mediaelements.js
【讨论】:
github.com/johndyer/mediaelement/blob/master/build/… 有一个以“Chrome 现在支持 preload="none"” 开头的注释掉的部分,所以这可能暗示仍然可能存在一些问题。我写的代码是让其他人在我的网站上看到的,所以我不想使用 mediaelementjs 之类的代码。 借助 mediaelementjs,您甚至可以完全支持旧浏览器,并且大多数人会使用它而不是尝试重新发明***。您应该至少添加指向 mediaelementjs 页面的链接作为(imo:更好的)替代方案。 那很好,你认为它更好,但这不是我想要的。我想知道如何自己从底层编写代码,我不介意它在旧浏览器甚至所有新浏览器中都不起作用。以上是关于从 Javascript 播放 <audio> + <video> 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 javascript 从 Audio Element 录制音频