在 html5视频标签上改变源代码

我正在尝试建立一个视频播放器,可以在任何地方使用。到目前为止,我会这样做:

<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>

(在一些网站上可以看到,例如 每个人都能看到) 目前为止,一切顺利。

但是现在我还想要一些播放列表/菜单与视频播放器,从中我可以选择其他视频。这些应该立刻在我的播放器中打开。因此,我将不得不使用 Javascript“动态更改视频源”(正如在 Dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/-section“ Let’s look at another film”中看到的那样)。让我们暂时忘记 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 ()函数确定适当的文件。

我是做错了还是把事情搞复杂了?

406174 次浏览

尝试将 OGG 源代码移到顶部。我注意到 Firefox 有时候会感到困惑,当它想要玩的 OGG 不是第一个时,它就会停止播放器。

值得一试。

现代化对我来说就像一种魅力。

我所做的是我没有使用 <source>。不知何故,这搞砸了事情,因为视频只有在第一次 load ()被调用时才能工作。相反,我使用 video 标记-> <video src="blabla.webm" />中的 source 属性,并使用 现代化来确定浏览器支持的格式。

<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>

希望这能帮到你:)

如果不想使用 现代化,可以使用 CanPlayType ()

与其让同一个视频播放器加载新文件,不如擦除整个 <video>元素并重新创建它。如果 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);

我有一个类似的网络应用程序,并没有面临这种问题。我的工作是这样的:

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 属性更干净,也更可靠。上面的代码是从内存中编写的,所以我可能忽略了一些 hte 细节,但是总的思想是在适当的时候使用 javascript 动态地更改源标记的 src 属性。

在 Chrome14.0.835.202中使用 <source />标签对我来说很困难,尽管在 FireFox 中它工作得很好。(这可能是因为我缺乏知识,但我认为另一种解决方案可能还是有用的。)因此,我最终只使用了一个 <video />标记,并在 video 标记本身上设置了 src 属性。canPlayVideo('<mime type>')函数用于确定特定浏览器是否可以播放输入视频。下面的代码可以在 FireFox 和 Chrome 中使用。

另外,FireFox 和 Chrome 都在使用“ ogg”格式,尽管 Chrome 推荐使用“ webm”。我把检查“ ogg”的浏览器支持放在第一位,只是因为其他帖子提到 FireFox 更喜欢将 ogg 源放在第一位(即 <source src="..." type="video/ogg"/>)。但是,我还没有测试(并且非常怀疑)在设置 video 标签上的“ src”时,代码中的顺序是否会产生任何差异。

超文本标示语言

<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();
}

我觉得你原来的计划不错。您可能会发现更多关于动态管理 <source>元素的浏览器怪异之处,正如这里的 W3规范说明所指出的:

如果源元素已经插入到视频或音频元素中,则动态修改该元素及其属性将不会产生任何效果。要更改正在播放的内容,只需直接使用 media 元素上的 src 属性,可以利用 canPlayType ()方法从可用资源中进行选择。通常,在解析文档之后手动操作源元素是一种不必要的复杂方法。

Http://dev.w3.org/html5/spec/overview.html#the-source-element

根据 说明书

时动态修改源元素及其属性 元素已插入视频或音频元素将没有 要更改正在播放的内容,只需在 直接使用 media 元素,可能会利用 canPlayType () 从现有资源中挑选的方法。一般来说, 之后手动操作源元素 解析是一种不必要的复杂方法。

所以你想做的显然不应该起作用。

Yaur: 虽然你复制和粘贴的东西是个不错的建议,但这并不意味着不可能优雅地改变 HTML5视频元素的源元素,即使是在 IE9(或 IE8)中也是如此。(这个解决方案不涉及替换整个视频元素,因为这是糟糕的编码实践)。

通过 javascript 在 HTML5视频标签中更改/切换视频的完整解决方案可以找到 给你,并在所有 HTML5浏览器(Firefox、 Chrome、 Safari、 IE9等)中进行测试。

如果这有帮助,或者你有麻烦,请告诉我。

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

这里有一个普通的 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

我已经研究这个很长一段时间了,我正在尝试做同样的事情,所以希望这将有助于其他人。我一直在使用 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 和 breakreturn中的 src,并且不要忘记动态更新 flash var mp4。另外,有些浏览器不会注册您更改了源代码,除非您调用 video.load()。我相信您所遇到的 .load()的问题可以通过首先拨打 video.pause()来解决。删除和添加视频元素会降低浏览器的速度,因为浏览器会继续缓冲删除的视频,但是 有个办法

跨浏览器支持

至于实际的跨浏览器部分,我也到了 每个人的视频。我已经试过 MediaelementJS Wordpress 插件,结果发现它引起的问题比解决的问题多得多。我怀疑这些问题是由 WordPress 插件引起的,而不是由于实际的库引起的。如果可能的话,我试图找到一些不使用 JavaScript 也能工作的东西。到目前为止,我想到的是这个简单的 HTML:

<video width="300" height="150" 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" 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-generator/images/big-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-generator/images/big-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>时会放弃播放视频。
  • 正确的 MIME 类型是重要的 。 ogv文件应该是 video/ogg没有 video/ogv
  • 如果你有高清视频,最好的代码转换器我已经找到了高清质量的 OGG 文件是 火雾
  • .iphone.mp4文件适用于 iPhone4 + ,它将播放带有 H.264基准3视频和 AAC 音频的 MPEG-4视频。我发现这种格式最好的代码转换器是手刹,使用 IPhone & iPod Touch预设将在 iPhone 4 + 上工作,但要让 iPhone 3GS 工作,你需要使用 IPod预设,它有更低的分辨率,我添加了作为 video.iphone3g.mp4
  • 在未来,我们将能够使用 <source>元素上的 media属性来针对带有媒体查询的移动设备,但是目前较老的苹果和 Android 设备还不能很好地支持它。

编辑 :

  • 我仍然使用视频为每个人,但现在我已经过渡到使用 FlowPlayer,以控制 Flash 后备,其中有一个很棒的 JavaScript API,可以用来控制它。

只要放一个 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>

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

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

我用这个来动态更改视频源。“ canplay”事件有时在 Firefox 中不会触发,所以我添加了“ loadedmeta”。另外,我暂停以前的视频,如果有一个..。

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();
};

这是我的解决办法:

<video id="playVideo" width="680" height="400" 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>

使用 JavaScript 和 jQuery:

<script src="js/jquery.js"></script>
...
<video id="vid" width="1280" height="720" 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>

在 Jquery 中的另一种方法。

超文本标示语言

<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();
});

根据 这个规范说明,您不应该尝试更改源元素的 src属性。

时动态修改源元素及其属性 已插入到视频或音频元素中的 更改正在播放的内容,只需在媒体上使用 src 属性 元素直接

假设你有:

<audio>
<source src='./first-src'/>
</audio>

修改 src:

<audio src='./second-src'/>
<source src='./first-src'/>
</audio>

我最终将接受的答案变成了一个函数,并改进了简历以保持时间

    /**
* https://stackoverflow.com/a/18454389/4530300
* This inspired a little function to replace a video source and play the video.
* @param video
* @param source
* @param src
* @param type
*/
function swapSource(video, source, src, type) {
let dur = video.duration;
let t = video.currentTime;
// var video = document.getElementById('video');
// var source = document.createElement('source');
video.pause();
source.setAttribute('src', src);
source.setAttribute('type', type);


video.load();
video.currentTime = t;
// video.appendChild(source);
video.play();
console.log("Updated Sorce: ", {
src: source.getAttribute('src'),
type: source.getAttribute('type'),
});
}


如果您已经有一个加载的视频,并尝试上传一个新的一个,确保使用的 video Ref.load ()对第二个,否则它不会加载。

* video Ref 应为显示的 < video > 标签的参考