改变html5video标签的来源

我试图build立一个video播放器,无处不在。 到目前为止,我会与:

<video> <source src="video.mp4"></source> <source src="video.ogv"></source> <object data="flowplayer.swf" type="application/x-shockwave-flash"> <param name="movie" value="flowplayer.swf" /> <param name="flashvars" value='config={"clip":"video.mp4"}' /> </object> </video> 

(如在几个网站上看到的,例如所有人的video ),那么好。

但现在我也想要一些播放列表/菜单以及video播放器,从中我可以select其他video。 那些应该立即在我的玩家内部打开。 所以我将不得不“dynamic地改变video的来源”(如在dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/上看到的那样) – 让我们看看另一部电影“)与JavaScript。 让我们暂时忘记FlashPlayer(也就是IE)的一部分,稍后我会试着去处理。

所以我的JS改变<source>标签应该是这样的:

 <script> function loadAnotherVideo() { var video = document.getElementsByTagName('video')[0]; var sources = video.getElementsByTagName('source'); sources[0].src = 'video2.mp4'; sources[1].src = 'video2.ogv'; video.load(); } </script> 

问题是,这并不适用于所有的浏览器。 即firefox = O有一个很好的页面,在那里你可以观察到我遇到的问题: http : //www.w3.org/2010/05/video/mediaevents.html

只要我触发load()方法(在Firefox中,请注意),video播放器就会死亡。

现在我已经发现,当我不使用多个<source>标签,而是<video>标签内只有一个src属性,整个事情在Firefox中工作。

所以我的计划是只使用该src属性,并使用canPlayType()函数确定适当的文件。

我做错了不知何故或复杂的事情?

我讨厌所有这些答案,因为他们太短或依赖于其他框架。

这里是“一个”香草JS的做法,在Chrome中工作,请在其他浏览器中testing:

http://jsfiddle.net/mattdlockyer/5eCEu/2/

HTML:

 <video id="video" width="320" height="240"></video> 

JS:

 var video = document.getElementById('video'); var source = document.createElement('source'); source.setAttribute('src', 'http://www.tools4movies.com/trailers/1012/Kill%20Bill%20Vol.3.mp4'); video.appendChild(source); video.play(); setTimeout(function() { video.pause(); source.setAttribute('src', 'http://www.tools4movies.com/trailers/1012/Despicable%20Me%202.mp4'); video.load(); video.play(); }, 3000); 

Modernizr对我来说就像一个魅力。

我所做的是我没有使用<source> 。 不知何故,这个事情搞砸了,因为video只有在第一次调用load()时才起作用。 相反,我使用video标签 – > <video src="blabla.webm" />的source属性,并使用Modernizr来确定浏览器支持的格式。

 <script> var v = new Array(); v[0] = [ "videos/video1.webmvp8.webm", "videos/video1.theora.ogv", "videos/video1.mp4video.mp4" ]; v[1] = [ "videos/video2.webmvp8.webm", "videos/video2.theora.ogv", "videos/video2.mp4video.mp4" ]; v[2] = [ "videos/video3.webmvp8.webm", "videos/video3.theora.ogv", "videos/video3.mp4video.mp4" ]; function changeVid(n){ var video = document.getElementById('video'); if(Modernizr.video && Modernizr.video.webm) { video.setAttribute("src", v[n][0]); } else if(Modernizr.video && Modernizr.video.ogg) { video.setAttribute("src", v[n][1]); } else if(Modernizr.video && Modernizr.video.h264) { video.setAttribute("src", v[n][2]); } video.load(); } </script> 

希望这会帮助你:)

如果您不想使用Modernizr ,则始终可以使用CanPlayType() 。

你原来的计划对我来说听起来不错。 您可能会发现更多的浏览器怪癖,处理dynamicpipe理<source>元素,正如W3规范注释所示:

当元素已经插入到video或audio元素中时,dynamic修改源元素及其属性将不起作用。 要更改正在播放的内容,只需直接使用媒体元素上的src属性,可以使用canPlayType()方法从可用资源中进行select。 通常,在parsing文档之后手动操作源元素是一个非常复杂的方法。

http://dev.w3.org/html5/spec/Overview.html#the-source-element

我用这个简单的方法解决了这个问题

 function changeSource(url) { var video = document.getElementById('video'); video.src = url; video.play(); } 

为了不要让相同的video播放器加载新文件,为什么不擦除整个<video>元素并重新创build它。 如果src是正确的,大多数浏览器会自动加载它。

示例(使用原型 ):

 var vid = new Element('video', { 'autoplay': 'autoplay', 'controls': 'controls' }); var src = new Element('source', { 'src': 'video.ogg', 'type': 'video/ogg' }); vid.update(src); src.insert({ before: new Element('source', { 'src': 'video.mp4', 'type': 'video/mp4' }) }); $('container_div').update(vid); 

根据规格

当元素已经插入到video或audio元素中时,dynamic修改源元素及其属性将不起作用。 要更改正在播放的内容,只需直接使用媒体元素上的src属性,可以使用canPlayType()方法从可用资源中进行select。 通常,在parsing文档之后手动操作源元素是一个非常复杂的方法。

所以你试图做的显然不应该工作。

只要把div和更新内容…

 <script> function setvideo(src) { document.getElementById('div_video').innerHTML = '<video autoplay controls id="video_ctrl" style="height: 100px; width: 100px;"><source src="'+src+'" type="video/mp4"></video>'; document.getElementById('video_ctrl').play(); } </script> <button onClick="setvideo('video1.mp4');">Video1</button> <div id="div_video"> </div> 

Yaur:虽然你所复制和粘贴的东西是很好的build议,但这并不意味着即使在IE9(或IE8)中,也不可能优雅地改变HTML5video元素的源元素(这个解决scheme不涉及取代整个video元素,因为这是不好的编码习惯)。

通过JavaScript在HTML5video标签中更改/切换video的完整解决scheme可在此处find,并在所有HTML5浏览器(Firefox,Chrome,Safari,IE9等)中进行testing。

如果这有帮助,或者如果你有麻烦,请让我知道。

我用这个来dynamic改变video源。 “canplay”事件有时不会在Firefox中触发,因此我添加了“loadedmetadata”。 另外我暂停以前的video,如果有一个…

 var loadVideo = function(movieUrl) { console.log('loadVideo()'); $videoLoading.show(); var isReady = function (event) { console.log('video.isReady(event)', event.type); video.removeEventListener('canplay', isReady); video.removeEventListener('loadedmetadata', isReady); $videoLoading.hide(); video.currentTime = 0; video.play(); }, whenPaused = function() { console.log('video.whenPaused()'); video.removeEventListener('pause', whenPaused); video.addEventListener('canplay', isReady, false); video.addEventListener('loadedmetadata', isReady, false); // Sometimes Firefox don't trigger "canplay" event... video.src = movieUrl; // Change actual source }; if (video.src && !video.paused) { video.addEventListener('pause', whenPaused, false); video.pause(); } else whenPaused(); }; 

在Chrome 14.0.835.202中使用<source />标签certificate很困难,尽pipe它在FireFox中工作的很好。 (这可能是我缺乏知识,但我认为一个备用的解决scheme可能是有用的。)所以,我最终只是使用<video />标记,并在video标记本身设置src属性。 canPlayVideo('<mime type>')函数用于确定特定浏览器是否可以播放inputvideo。 以下工作在FireFox和Chrome。

虽然Chrome推荐使用“webm”,但FireFox和Chrome都使用“ogg”格式。 我首先检查了“ogg”的浏览器支持,因为其他的post都提到过,FireFox首先使用了ogg源代码(即<source src="..." type="video/ogg"/> )。 但是,在video标签上设置“src”时,我还没有testing过(也没有质疑)代码中的顺序是否有任何区别。

HTML

 <body onload="setupVideo();"> <video id="media" controls="true" preload="auto" src=""> </video> </body> 

JavaScript的

 function setupVideo() { // You will probably get your video name differently var videoName = "http://video-js.zencoder.com/oceans-clip.mp4"; // Get all of the uri's we support var indexOfExtension = videoName.lastIndexOf("."); //window.alert("found index of extension " + indexOfExtension); var extension = videoName.substr(indexOfExtension, videoName.length - indexOfExtension); //window.alert("extension is " + extension); var ogguri = encodeURI(videoName.replace(extension, ".ogv")); var webmuri = encodeURI(videoName.replace(extension, ".webm")); var mp4uri = encodeURI(videoName.replace(extension, ".mp4")); //window.alert(" URI is " + webmuri); // Get the video element var v = document.getElementById("media"); window.alert(" media is " + v); // Test for support if (v.canPlayType("video/ogg")) { v.setAttribute("src", ogguri); //window.alert("can play ogg"); } else if (v.canPlayType("video/webm")) { v.setAttribute("src", webmuri); //window.alert("can play webm"); } else if (v.canPlayType("video/mp4")) { v.setAttribute("src", mp4uri); //window.alert("can play mp4"); } else { window.alert("Can't play anything"); } v.load(); v.play(); } 

我已经研究了很长一段时间,我正在尝试做同样的事情,所以希望这会帮助别人。 我一直在使用crossbrowsertesting.com,并在几乎所有人都知道的浏览器中进行testing。 我目前的解决scheme在Opera,Chrome,Firefox 3.5+,IE8 +,iPhone 3GS,iPhone 4,iPhone 4s,iPhone 5,iPhone 5s,iPad 1+,Android 2.3+,Windows Phone 8中都有效。

dynamic变化的来源

dynamic更改video非常困难,如果您想要Flash后备,则必须从DOM /页面中删除video并重新添加video,以便Flash更新,因为Flash无法识别Flash vars的dynamic更新。 如果您要使用JavaScriptdynamic更改它,我会完全删除所有<source>元素,并使用canPlayType来设置JavaScript中的src ,并在第一个支持的videotypes之后breakreturn ,并且不要忘记dynamic更新闪光灯变种mp4。 此外,除非您调用video.load()否则某些浏览器将不会注册您更改了源代码。 我相信您遇到的video.pause()问题可以通过先调用video.pause() 。 删除和添加video元素可能会降低浏览器的速度,因为它会继续caching已删除的video,但有一个解决方法 。

跨浏览器支持

就实际的跨浏览器部分而言,我也是到了Video for Everybody 。 我已经尝试过MediaelementJS WordPress插件,结果导致了比解决更多的问题。 我怀疑这个问题是由于WordPress的插件,而不是实际的库。 如果可能的话,我试图find没有JavaScript的东西。 到目前为止,我想到的是这个纯HTML:

 <video width="300" height="150" controls="controls" poster="http://sandbox.thewikies.com/vfe-generatorhttp://img.dovov.combig-buck-bunny_poster.jpg" class="responsive"> <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv" type="video/ogg" /> <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4" /> <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm" type="video/webm" /> <source src="http://alex-watson.net/wp-content/uploads/2014/07/big_buck_bunny.iphone.mp4" type="video/mp4" /> <source src="http://alex-watson.net/wp-content/uploads/2014/07/big_buck_bunny.iphone3g.mp4" type="video/mp4" /> <object type="application/x-shockwave-flash" data="http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf" width="561" height="297"> <param name="movie" value="http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf" /> <param name="allowFullScreen" value="true" /> <param name="wmode" value="transparent" /> <param name="flashVars" value="config={'playlist':['http://sandbox.thewikies.com/vfe-generatorhttp://img.dovov.combig-buck-bunny_poster.jpg',{'url':'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4','autoPlay':false}]}" /> <img alt="No Video" src="http://sandbox.thewikies.com/vfe-generatorhttp://img.dovov.combig-buck-bunny_poster.jpg" width="561" height="297" title="No video playback capabilities, please download the video below" /> </object> <strong>Download video:</strong> <a href="video.mp4">MP4 format</a> | <a href="video.ogv">Ogg format</a> | <a href="video.webm">WebM format</a> </video> 

重要提示

  • 结束了把ogg作为第一个<source>因为如果Mac OS的Firefox遇到一个MP4作为第一个<source>它将退出尝试播放video。
  • 正确的MIMEtypes很重要.ogv文件应该是video/ogg而不是 video/ogv
  • 如果你有高清video,我发现的高清质量OGG文件的最佳代码转换器是Firefogg
  • .iphone.mp4文件适用于iPhone 4+,它只能播放带有H.264 Baseline 3video和AACaudio的MPEG-4video。 我发现这种格式的最好的代码转换器是Handbrake,使用iPhone和iPod Touch预设可以在iPhone 4+上运行,但为了让iPhone 3GS运行,您需要使用分辨率低得多的iPod预设video.iphone3g.mp4
  • 未来,我们将能够使用<source>元素上的media属性来针对具有媒体查询的移动设备,但是现在的旧版苹果和Android设备不能很好地支持这一点。

编辑

  • 我仍然使用Video For Everyone,但现在我已经转换到使用FlowPlayer来控制Flash后备,Flash后备有一个可以用来控制它的真棒JavaScript API 。

尝试将OGG源移到顶部。 我注意到Firefox有时候会感到困惑,当玩家想要玩的时候,OGG不是第一个。

值得一试。

我有一个类似的networking应用程序,并没有面临这样的问题。 我所做的是这样的:

 var sources = new Array(); sources[0] = /path/to/file.mp4 sources[1] = /path/to/another/file.ogg etc..... 

那么当我想要更改来源我有一个function,如下所示:

 this.loadTrack = function(track){ var mediaSource = document.getElementsByTagName('source')[0]; mediaSource.src = sources[track]; var player = document.getElementByTagName('video')[0]; player.load(); } 

我这样做,以便用户可以通过播放列表,但您可以检查userAgent,然后以这种方式加载适当的文件。 我试过使用多个源标签,就像互联网上的所有人一样,但我发现它更清洁,操作单个源标签的src属性更可靠。 上面的代码是从内存中写的,所以我可能已经掩盖了一些细节,但总体思路是在适当的时候使用javascriptdynamic改变源代码的src属性。