更改html5视频标签上的来源


138

我正在尝试构建一个随处可见的视频播放器。到目前为止,我将与:

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

(在几个网站上都可以看到,例如所有人的视频),到目前为止,一切都很好。

但是现在我也想要某种播放列表/菜单以及视频播放器,从中我可以选择其他视频。这些应该立即在我的播放器中打开。因此,我将不得不“动态地更改视频的来源”(如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中,请注意),视频播放器就会死亡。

现在我发现,当我不使用多个<source>标签,而是在<video>标签中仅使用一个src属性时,整个事情在Firefox中都可以使用。

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

我是某种方式做错了还是使事情复杂化了?


对我来说听起来不错。如何简化标记呢?
Matt Ball

问题是我看到自己遇到了很多JavaScript和案例区别。如果也许我错过了一些东西,比如有一种方法可以使它在带有多个<source>标签的Firefox中工作。那么我想那会更容易
2011年

您是否曾经了解过ie8的Flash部分?
Neeraj 2015年

@Neeraj最终解决方案涉及插件video.js,该插件使用Flash Player作为IE8等的后备。今天可能会有高级插件。使用插件也无法解决有关load()方法的Firefox问题,这是本文的最初动机。今天,这个问题似乎早已解决。
萨申(Sashn)2015年

Answers:


169

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

这是在Chrome上运行的“一种”原始JS方式,请在其他浏览器中进行测试:

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

11
这对我来说是最干净,最有效的。
Phil McCarty 2014年

我无法让Chrome为此玩球。仅当我将video src属性设置为webm路径时
-Adam Hey

2
在某些浏览器策略中,用户手势仅允许使用play方法。
安森

我非常感谢另一个原因!我一直试图建立一个视频页面,直到访问者选择一个视频页面,该页面才显示任何视频。我可以用一个空的源标签设置一个视频标签,但是它始终会在javascript调试控制台上生成失败。现在我知道我可以推迟添加“源”,直到用户选择一个。到现在为止,我还不明白我需要使用CreateElement()来制作源,然后使用appendChild()将其添加到视频元素中!对于后续选择,我可以先检查一下source元素是否存在,因此我不再重复该步骤。
兰迪

如果任何人都面临有效负载响应中的内容类型问题,即使指定的内容类型正确但行为仍然很奇怪,该解决方案也非常有效。
meDeepakJain

63

对我来说,Modernizr就像一种魅力。

我所做的是我没有使用过<source>。由于视频仅在第一次调用load()时才起作用,因此以某种方式使事情搞砸了。相反,我使用了视频标签->中的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]吗?
bergie3000

1
在尝试了其他方法之后,我尝试了这个Modernizr方法,并且效果很好。Chrome(出于某种原因)不会加载mp4,但会加载webm。感谢@MariusEngenHaugen
Adam Hey

很高兴我可以为@AdamHey服务-Marius
Engen Haugen

32

你原来的计划对我来说还不错。<source>如W3规范说明所示,您可能会发现更多处理动态管理元素的浏览器怪癖:

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

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



10

与其让同一个视频播放器加载新文件,不如擦除整个<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
这会大大降低整个浏览器的速度,因为即使在删除了视频标签之后,浏览器仍会加载删除的视频,直到最后。
Moe Sweet,

某些浏览器(移动设备)不允许您在没有用户交互的情况下以编程方式播放媒体,并且由于您已经在该元素上进行了交互,因此,用新的替换它会失去该功能。
马克斯·沃特曼

6

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

6

根据规格

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

因此,您尝试做的事情显然不起作用。


@ greg.kindel我发贴后注意到了...但是我之所以没有注意到的原因是您的介绍文字令人困惑。我们在谈论哪个原始计划?无法使用的原始原始计划或遵循我们双方发布的指南的更新的原始计划?
Yaur 2013年

公平地说,我应该引用。我的意思是他的计划“可以正常使用src属性,并使用canPlayType()函数确定适当的文件”。
greg.kindel

4

Yaur:尽管您复制并粘贴的内容是很好的建议,但这并不意味着即使在IE9(或IE8)中也无法优雅地更改HTML5视频元素的源元素。(此解决方案不涉及替换整个视频元素,因为这是不好的编码习惯)。

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

如果这样做有帮助,或者您遇到麻烦,请告诉我。


辉煌!这是这样做的方法。您甚至不需要jQuery。在链接的代码中,替换为:mp4Vid.setAttribute('src',“ /pathTo/newVideo.mp4”);
Velojet

3

我带有此功能可以动态更改视频源。有时“ 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需要将其添加(并在以后删除)到视频处理程序中:-(
怪胎之王

3

这是我的解决方案:

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

2

<source />尽管在FireFox中对我来说效果很好,但是在Chrome 14.0.835.202中使用标签对我来说确实很困难。(这可能是我缺乏知识,但我认为无论如何都可以使用其他解决方案。)因此,我最终只使用了<video />标签,并在视频标签本身上设置了src属性。的canPlayVideo('<mime type>')功能用于确定特定的浏览器是否可以播放输入的视频。以下内容适用于FireFox和Chrome。

顺便说一句,虽然Chrome浏览器建议使用“ webm”,但FireFox和Chrome都使用“ ogg”格式。我之所以首先检查浏览器是否支持“ 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();
  }

2

我已经对此进行了一段时间的研究,并且正在尝试做同样的事情,因此希望对其他人有所帮助。我一直在使用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>元素,仅用于在JavaScript中和/ 或第一个受支持的视频类型之后canPlayType进行设置,不要忘记动态更新Flash var mp4。此外,除非您致电,否则某些浏览器不会注册您更改了源。我相信这个问题srcbreakreturnvideo.load().load()您遇到可以通过首先致电来解决video.pause()。删除和添加视频元素可能会降低浏览器的速度,因为它会继续缓冲已删除的视频,但是有一种解决方法

跨浏览器支持

至于实际的跨浏览器部分,我也到达了Video For Everybody。我已经尝试了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文件的最佳转码器是Firefogg
  • .iphone.mp4文件适用于iPhone 4+,它将播放带有H.264 Baseline 3 Video和AAC音频的MPEG-4视频。我发现该格式的最佳转码器是Handbrake,使用iPhone和iPod Touch预设可以在iPhone 4+上使用,但是要使iPhone 3GS正常工作,您需要使用分辨率较低的iPod预设,我将其添加为video.iphone3g.mp4
  • 将来,我们将能够media<source>元素上使用属性来通过媒体查询来定位移动设备,但是现在,较早的Apple和Android设备还不够支持它。

编辑

  • 我仍在使用“所有人的视频”,但现在我已经过渡到使用FlowPlayer来控制Flash后备功能,该功能具有强大的JavaScript API,可以用来控制它。

这似乎是“如何播放视频跨浏览器?”问题的答案。而不是“如何为我的视频设置播放列表?”这个问题。
昆汀2014年

@Quentin首先,因为那是我通过Google发现此问题的方式,OP表示他正在尝试构建一个可在任何地方使用的视频播放器。我也更新了答案以解决他的动态问题。
Alex W

2

我有一个类似的Web应用程序,根本没有遇到这种问题。我所做的是这样的:

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,然后以这种方式加载适当的文件。我尝试像Internet上的每个人一样建议使用多个源标签,但是我发现它更整洁,并且操纵单个源标签的src属性更加可靠。上面的代码是从内存中写入的,因此我可能已经掩盖了一些详细信息,但是总体思路是在适当时使用javascript动态更改源标签的src属性。


1

尝试将OGG源移动到顶部。我注意到Firefox有时会感到困惑,并在它不想要播放的OGG不在时停止播放器。

值得一试。


1

您可以在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();
    });

0

使用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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.