更改 html5 视频标签上的源
Posted
技术标签:
【中文标题】更改 html5 视频标签上的源【英文标题】:changing source on html5 video tag 【发布时间】:2011-07-11 05:54:07 【问题描述】:我正在尝试构建一个可以在任何地方使用的视频播放器。到目前为止,我会选择:
<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 for everybody) 到目前为止,一切顺利。
但现在我还想要某种播放列表/菜单以及视频播放器,我可以从中选择其他视频。那些应该立即在我的播放器中打开。所以我将不得不用javascript“动态地改变视频的来源”(如dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/ - “让我们看另一部电影”部分)。让我们暂时忘记 Flash 播放器(以及 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 中有一个不错的页面,您可以在其中观察我遇到的问题:http://www.w3.org/2010/05/video/mediaevents.html
只要我触发 load()
方法(在 Firefox 中,请注意),视频播放器就会死掉。
现在我发现,当我不使用多个 <source>
标记,而是在 <video>
标记中只使用一个 src
属性时,整个事情确实在 Firefox 中工作.
所以我的计划是只使用 src
属性并使用 canPlayType() 函数确定适当的文件。
我做错了什么还是让事情复杂化了?
【问题讨论】:
这对我来说听起来不错。简化标记有多“复杂”? 问题是我发现自己遇到了很多 javascript 和区分情况。如果我错过了一些东西,比如有一种方法可以让它在带有多个<source>
标签的 Firefox 中工作。那我想这会更容易
你有想过ie8上的flash部分吗?
@Neeraj 最终解决方案涉及插件video.js,它使用Flash 播放器作为IE8 等的后备。不过今天可能有更好的插件。使用该插件也无助于解决有关 load() 方法的 firefox 问题,这是本文的最初动机。今天,这个问题似乎早已得到解决。
【参考方案1】:
我讨厌所有这些答案,因为它们太短或依赖于其他框架。
这是“一种”香草 JS 的做法,在 Chrome 中工作,请在其他浏览器中测试:
var video = document.getElementById('video');
var source = document.createElement('source');
source.setAttribute('src', 'http://techslides.com/demos/sample-videos/small.mp4');
source.setAttribute('type', 'video/mp4');
video.appendChild(source);
video.play();
console.log(
src: source.getAttribute('src'),
type: source.getAttribute('type'),
);
setTimeout(function()
video.pause();
source.setAttribute('src', 'http://techslides.com/demos/sample-videos/small.webm');
source.setAttribute('type', 'video/webm');
video.load();
video.play();
console.log(
src: source.getAttribute('src'),
type: source.getAttribute('type'),
);
, 3000);
<video id="video" width="320" height="240"></video>
External Link
【讨论】:
这对我来说是最干净、最高效的。 我无法让 Chrome 使用它。仅当我将视频 src 属性设置为 webm 路径时 play 方法仅在某些浏览器策略中被用户手势允许。 我非常感谢这个还有另一个原因!我一直在尝试设置一个视频页面,在访问者选择一个之前不显示任何视频。我可以设置一个带有空源标签的视频标签,但它总是会在 javascript 调试控制台上产生故障。现在我知道我可以推迟添加“源”,直到用户选择一个。直到现在,我才明白我需要使用 CreateElement() 创建一个源,然后使用 appendChild() 将它添加到视频元素中!对于后续选择,我可以先检查源元素是否存在,因此我不再重复该步骤。 如果有人面临来自有效负载响应的内容类型问题,即使指定的内容类型正确但行为仍然很奇怪,此解决方案也很有效。【参考方案2】:Modernizr 对我来说就像一个魅力。
我所做的是我没有使用<source>
。不知何故,这搞砸了,因为视频仅在第一次调用 load() 时才有效。相反,我使用了 video 标签内的 source 属性 -> <video src="blabla.webm" />
并使用 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()。
【讨论】:
如果 (Modernizr.video && Modernizr.video.ogg) 为真,你的意思是第二个 v[n][1] 吗? 在尝试了其他方法后,我尝试了这种 Modernizr 方法,效果很好。在我的情况下,Chrome(出于某种原因)不会加载 mp4,但会加载 webm。谢谢@MariusEngenHaugen 很高兴我能为 @AdamHey 服务【参考方案3】:你最初的计划对我来说听起来不错。您可能会发现更多处理动态管理 <source>
元素的浏览器怪癖,如 W3 规范说明所示:
当元素已插入视频或音频元素时,动态修改源元素及其属性将无效。要更改正在播放的内容,只需直接使用媒体元素上的 src 属性,可能使用 canPlayType() 方法从可用资源中进行选择。通常,在文档被解析后手动操作源元素是一种不必要的[原文如此]复杂的方法。
http://dev.w3.org/html5/spec/Overview.html#the-source-element
【讨论】:
【参考方案4】:我用这个简单的方法解决了这个问题
function changeSource(url)
var video = document.getElementById('video');
video.src = url;
video.play();
【讨论】:
【参考方案5】:与其让同一个视频播放器加载新文件,不如删除整个<video>
元素并重新创建它。如果 src 正确,大多数浏览器会自动加载它。
示例(使用Prototype):
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);
【讨论】:
这会显着降低整个浏览器的速度,因为即使删除了视频标签,浏览器仍然会加载删除的视频直到结束。 一些浏览器(移动)不允许您在没有用户交互的情况下以编程方式播放媒体,并且由于您已经对元素进行了交互,因此用新的元素替换它会失去这种能力.【参考方案6】:根据the spec
动态修改源元素及其属性 元素已插入视频或音频元素将没有 影响。要更改正在播放的内容,只需使用 src 属性 直接媒体元素,可能使用 canPlayType() 从可用资源中挑选的方法。一般来说, 在文档完成后手动操作源元素 parsed 是一种不必要的复杂方法。
所以你正在尝试做的显然不应该工作。
【讨论】:
@greg.kindel 我在发布后注意到了......但我一开始没有注意到的原因是你的介绍文字令人困惑。我们在谈论哪个原始计划?无效的原始原始计划或遵循我们都发布的指导的更新原始计划? 很公平,我应该引用。我的意思是他的计划是“只使用该 src 属性并使用 canPlayType() 函数确定适当的文件”,这确实有效。【参考方案7】:只需放一个 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>
【讨论】:
【参考方案8】:Yaur:虽然您复制和粘贴的内容是个好建议,但这并不意味着无法优雅地更改 HTML5 视频元素的源元素,即使在 IE9(或 IE8 中)也是如此。(此解决方案不涉及替换整个视频元素,因为这是不好的编码习惯)。
通过 javascript 在 HTML5 视频标签中更改/切换视频的完整解决方案可以在 here 找到,并在所有 HTML5 浏览器(Firefox、Chrome、Safari、IE9 等)中进行了测试。
如果这有帮助,或者如果您遇到问题,请告诉我。
【讨论】:
太棒了!这是做到这一点的方法。你甚至不需要 jQuery;在链接代码中,替换为:mp4Vid.setAttribute('src', "/pathTo/newVideo.mp4");【参考方案9】:我有一个类似的网络应用程序,根本没有遇到这种问题。我所做的是这样的:
var sources = new Array();
sources[0] = /path/to/file.mp4
sources[1] = /path/to/another/file.ogg
etc..
然后,当我想更改源时,我有一个功能可以执行以下操作:
this.loadTrack = function(track)
var mediaSource = document.getElementsByTagName('source')[0];
mediaSource.src = sources[track];
var player = document.getElementsByTagName('video')[0];
player.load();
我这样做是为了让用户可以浏览播放列表,但您可以检查 userAgent,然后以这种方式加载适当的文件。我尝试使用互联网上每个人都建议的多个源标签,但我发现它更干净,更可靠地操纵单个源标签的 src 属性。上面的代码是从内存中编写的,所以我可能忽略了一些细节,但总体思路是在适当的时候使用 javascript 动态更改源标记的 src 属性。
【讨论】:
【参考方案10】:您可以在 Jquery 中执行的另一种方式。
HTML
<video id="videoclip" controls="controls" poster="" title="Video title">
<source id="mp4video" src="video/bigbunny.mp4" type="video/mp4" />
</video>
<div class="list-item">
<ul>
<li class="item" data-video = "video/bigbunny.mp4"><a href="javascript:void(0)">Big Bunny.</a></li>
</ul>
</div>
jQuery
>$(".list-item").find(".item").on("click", function()
let videoData = $(this).data("video");
let videoSource = $("#videoclip").find("#mp4video");
videoSource.attr("src", videoData);
let autoplayVideo = $("#videoclip").get(0);
autoplayVideo.load();
autoplayVideo.play();
);
【讨论】:
【参考方案11】:我用它来动态更改视频源。 “canplay”事件有时不会在 Firefox 中触发,所以我添加了“loadedmetadata”。如果有的话,我也会暂停上一个视频...
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();
;
【讨论】:
修复,绝对对我有用,firefox 没有处理属性,canplay
和 canplaythrough
和 lodedmetadata
都需要添加(并稍后删除)到视频处理程序:-(
【参考方案12】:
这是我的解决方案:
<video id="playVideo" controls="controls">
<source id="sourceVideo" src="video.videoHigh" type="video/mp4">
</video>
<br />
<button class="btn btn-warning" id="video.videoHigh" onclick="changeSource(this)">HD</button>
<button class="btn btn-warning" id="video.videoLow" onclick="changeSource(this)">Regular</button>
<script type="text/javascript">
var getVideo = document.getElementById("playVideo");
var getSource = document.getElementById("sourceVideo");
function changeSource(vid)
var geturl = vid.id;
getSource .setAttribute("src", geturl);
getVideo .load()
getVideo .play();
getVideo .volume = 0.5;
</script>
【讨论】:
【参考方案13】:在 Chrome 14.0.835.202 中使用 <source />
标签对我来说特别困难,尽管它在 FireFox 中对我来说效果很好。 (这可能是我缺乏知识,但我认为替代解决方案可能还是有用的。)所以,我最终只使用了<video />
标签并在视频标签本身上设置了 src 属性。 canPlayVideo('<mime type>')
函数用于确定特定浏览器是否可以播放输入视频。以下适用于 FireFox 和 Chrome。
顺便说一句,FireFox 和 Chrome 都在播放“ogg”格式,尽管 Chrome 推荐使用“webm”。我首先检查浏览器对“ogg”的支持只是因为其他帖子提到 FireFox 首先更喜欢 ogg 源(即<source src="..." type="video/ogg"/>
)。但是,我没有测试(并且非常怀疑)在视频标签上设置“src”时,代码中的顺序是否有任何区别。
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();
【讨论】:
【参考方案14】:我已经对此进行了很长时间的研究,并且我正在尝试做同样的事情,因此希望这对其他人有所帮助。我一直在使用 crossbrowsertesting.com 并在几乎所有人类已知的浏览器中进行测试。我目前的解决方案适用于 Opera、Chrome、Firefox 3.5+、IE8+、iPhone 3GS、iPhone 4、iPhone 4s、iPhone 5、iPhone 5s、iPad 1+、android 2.3+、Windows Phone 8。
动态变化的来源
动态更改视频非常困难,如果您想要 Flash 后备,则必须从 DOM/页面中删除视频并重新添加它,以便 Flash 更新,因为 Flash 无法识别 Flash 变量的动态更新.如果您要使用 JavaScript 动态更改它,我将完全删除所有 <source>
元素,只需使用 canPlayType
在 JavaScript 中设置 src
和 break
或 return
在第一个支持的视频类型之后并且不要忘记动态更新 flash var mp4。此外,除非您致电video.load()
,否则某些浏览器不会注册您更改了源。我相信您遇到的.load()
的问题可以通过首先致电video.pause()
来解决。删除和添加视频元素会降低浏览器的速度,因为它会继续缓冲已删除的视频,但there's a workaround。
跨浏览器支持
就实际的跨浏览器部分而言,我也到达了Video For Everybody。我已经尝试过 MediaelementJS Wordpress 插件,但它导致的问题比解决的问题多得多。我怀疑问题是由于 Wordpress 插件而不是实际库引起的。如果可能的话,我正在尝试找到不需要 JavaScript 的东西。到目前为止,我想出的是这个纯 HTML:
<video controls="controls" poster="http://sandbox.thewikies.com/vfe-generator/images/big-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" >
<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-generator/images/big-buck-bunny_poster.jpg','url':'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4','autoPlay':false]" />
<img src="http://sandbox.thewikies.com/vfe-generator/images/big-buck-bunny_poster.jpg" 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>
,它将退出尝试播放视频。
正确的 MIME 类型很重要 .ogv 文件应该是 video/ogg
,不是 video/ogv
如果您有高清视频,我为高清质量 OGG 文件找到的最佳转码器是 Firefogg
.iphone.mp4
文件适用于 iPhone 4+,它将仅播放带有 H.264 Baseline 3 视频和 AAC 音频的 MPEG-4 视频。我为该格式找到的最佳转码器是 Handbrake,使用 iPhone 和 iPod Touch 预设可以在 iPhone 4+ 上运行,但要让 iPhone 3GS 正常工作,您需要使用 iPod em> 预设的分辨率要低得多,我将其添加为video.iphone3g.mp4
。
将来,我们将能够在 <source>
元素上使用 media
属性来定位具有媒体查询的移动设备,但目前较旧的 Apple 和 Android 设备对它的支持不够好。李>
编辑:
我仍在使用 Video For Everyone,但现在我已经过渡到使用 FlowPlayer 来控制 Flash 回退,它有一个很棒的 JavaScript API 可以用来控制它。【讨论】:
这似乎是“如何跨浏览器播放视频?”问题的答案。而不是“如何为我的视频设置播放列表?”这个问题。 @Quentin 首先是,因为这就是我通过谷歌找到这个问题的方式,OP 说他正在尝试构建一个可以在任何地方使用的视频播放器。我也更新了答案以解决他的动态问题。【参考方案15】:尝试将 OGG 源移到顶部。我注意到 Firefox 有时会在它想要播放的 OGG 不是第一个播放器时感到困惑并停止播放器。
值得一试。
【讨论】:
【参考方案16】:使用 JavaScript 和 jQuery:
<script src="js/jquery.js"></script>
...
<video id="vid" src="v/myvideo01.mp4" controls autoplay></video>
...
function chVid(vid)
$("#vid").attr("src",vid);
...
<div onclick="chVid('v/myvideo02.mp4')">See my video #2!</div>
【讨论】:
【参考方案17】:根据this 规范说明,您不应尝试更改源元素的src
属性。
动态修改源元素及其属性 已经插入视频或音频元素将无效。到 更改正在播放的内容,只需使用媒体上的 src 属性 直接元素
假设你有:
<audio>
<source src='./first-src'/>
</audio>
修改src:
<audio src='./second-src'/>
<source src='./first-src'/>
</audio>
【讨论】:
以上是关于更改 html5 视频标签上的源的主要内容,如果未能解决你的问题,请参考以下文章
在android上的html5视频标签中禁用默认的丑陋海报图像
HTML5 视频标签在移动 Chrome 上的奇怪行为,但适用于 SAFARI