更改 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 更改 &lt;source&gt; 标签应该是这样的:

<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 中,请注意),视频播放器就会死掉。

现在我发现,当我不使用多个 &lt;source&gt; 标记,而是在 &lt;video&gt; 标记中只使用一个 src 属性时,整个事情确实在 Firefox 中工作.

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

我做错了什么还是让事情复杂化了?

【问题讨论】:

这对我来说听起来不错。简化标记有多“复杂”? 问题是我发现自己遇到了很多 javascript 和区分情况。如果我错过了一些东西,比如有一种方法可以让它在带有多个&lt;source&gt; 标签的 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);
&lt;video id="video" width="320" height="240"&gt;&lt;/video&gt;

External Link

【讨论】:

这对我来说是最干净、最高效的。 我无法让 Chrome 使用它。仅当我将视频 src 属性设置为 webm 路径时 play 方法仅在某些浏览器策略中被用户手势允许。 我非常感谢这个还有另一个原因!我一直在尝试设置一个视频页面,在访问者选择一个之前不显示任何视频。我可以设置一个带有空源标签的视频标签,但它总是会在 javascript 调试控制台上产生故障。现在我知道我可以推迟添加“源”,直到用户选择一个。直到现在,我才明白我需要使用 CreateElement() 创建一个源,然后使用 appendChild() 将它添加到视频元素中!对于后续选择,我可以先检查源元素是否存在,因此我不再重复该步骤。 如果有人面临来自有效负载响应的内容类型问题,即使指定的内容类型正确但行为仍然很奇怪,此解决方案也很有效。【参考方案2】:

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

我所做的是我没有使用&lt;source&gt;。不知何故,这搞砸了,因为视频仅在第一次调用 load() 时才有效。相反,我使用了 video 标签内的 source 属性 -> &lt;video src="blabla.webm" /&gt; 并使用 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】:

你最初的计划对我来说听起来不错。您可能会发现更多处理动态管理 &lt;source&gt; 元素的浏览器怪癖,如 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】:

与其让同一个视频播放器加载新文件,不如删除整个&lt;video&gt; 元素并重新创建它。如果 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 没有处理属性,canplaycanplaythroughlodedmetadata 都需要添加(并稍后删除)到视频处理程序:-( 【参考方案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 中使用 &lt;source /&gt; 标签对我来说特别困难,尽管它在 FireFox 中对我来说效果很好。 (这可能是我缺乏知识,但我认为替代解决方案可能还是有用的。)所以,我最终只使用了&lt;video /&gt; 标签并在视频标签本身上设置了 src 属性。 canPlayVideo('&lt;mime type&gt;') 函数用于确定特定浏览器是否可以播放输入视频。以下适用于 FireFox 和 Chrome。

顺便说一句,FireFox 和 Chrome 都在播放“ogg”格式,尽管 Chrome 推荐使用“webm”。我首先检查浏览器对“ogg”的支持只是因为其他帖子提到 FireFox 首先更喜欢 ogg 源(即&lt;source src="..." type="video/ogg"/&gt;)。但是,我没有测试(并且非常怀疑)在视频标签上设置“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 动态更改它,我将完全删除所有 &lt;source&gt; 元素,只需使用 canPlayType 在 JavaScript 中设置 srcbreakreturn 在第一个支持的视频类型之后并且不要忘记动态更新 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 作为第一个 &lt;source&gt;,因为如果 Mac OS Firefox 遇到 MP4 作为第一个 &lt;source&gt;,它将退出尝试播放视频。 正确的 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。 将来,我们将能够在 &lt;source&gt; 元素上使用 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 视频标签上的源的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 视频:动态生成的视频标签仅第一次播放

使用 React 更新 HTML5 视频的源 URL

在android上的html5视频标签中禁用默认的丑陋海报图像

HTML5 视频标签在移动 Chrome 上的奇怪行为,但适用于 SAFARI

Jquery更改HTML5的video标签的属性,实现更换视频的效果。或者提供一个可行的思路

HTML5 视频 - 更改多个来源