alteração da fonte na tag de vídeo html5


138

Estou tentando criar um player de vídeo que funcione em qualquer lugar. até agora eu estaria indo com:

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

(como visto em vários sites, por exemplo, vídeo para todos ) até agora, tudo bem.

mas agora também quero algum tipo de playlist / menu junto com o player de vídeo, no qual posso selecionar outros vídeos. esses devem ser abertos dentro do meu player imediatamente. então terei que "mudar dinamicamente a fonte do vídeo" (como pode ser visto em dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/ - section "Vamos ver outro filme ") com javascript. vamos esquecer a parte do flashplayer (e, portanto, o IE) por enquanto, tentarei lidar com isso mais tarde.

então meu JS para alterar as <source>tags deve ser algo como:

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

O problema é que isso não funciona em todos os navegadores. ou seja, firefox = O existe uma página agradável, onde você pode observar o problema que estou tendo: http://www.w3.org/2010/05/video/mediaevents.html

Assim que eu acionar o método load () (no firefox, lembre-se), o player de vídeo morre.

agora descobri que quando não uso várias <source>tags, mas apenas um atributo src dentro da <video>tag, tudo funciona no firefox.

portanto, meu plano é apenas usar esse atributo src e determinar o arquivo apropriado usando a função canPlayType () .

estou fazendo errado de alguma forma ou complicando as coisas?


Isso soa bem para mim. Como é "complicado" simplificar a marcação?
Matt Bola

o problema é que me vejo correndo em um monte de javascript e distinção de casos. se talvez eu perdi alguma coisa, como se houvesse uma maneira de fazê-lo funcionar no firefox COM várias <source>tags. Então suponho que seria mais fácil
sashn

você já descobriu sobre a parte do flash no ie8?
26415 Neeraj

@Neeraj, a solução final envolveu o plugin video.js, que usa um flash player como substituto do IE8 e similares. embora possa haver plugins superiores hoje em dia. O uso do plug-in também não ajudou no problema do firefox referente ao método load (), que foi a motivação inicial para este post. hoje, esse problema foi corrigido há muito tempo, ao que parece.
sashn

Respostas:


169

Eu odiava todas essas respostas porque eram muito curtas ou dependiam de outras estruturas.

Aqui está o "one" modo JS de baunilha JS de fazer isso, trabalhando no Chrome, teste em outros navegadores:

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
Este foi o mais limpo e mais eficiente para mim.
22615 Phil McCarty

Não consegui fazer o Chrome jogar bola com isso. SOMENTE se eu definir o atributo src do vídeo como o caminho do webm
Adam Hey

2
O método play é permitido apenas por um gesto do usuário em algumas políticas do navegador.
Anson

Eu aprecio muito isso por outro motivo! Eu tenho tentado configurar uma página de vídeo que não mostre QUALQUER vídeo até que o visitante selecione uma. Eu poderia configurar uma tag de vídeo com uma tag de origem vazia, mas sempre gerava uma falha em um console de depuração de javascript. Agora eu sei que posso adiar a adição de uma 'fonte' até que o usuário selecione uma. Até agora, eu não entendia que precisava usar CreateElement () para criar uma fonte e, em seguida, usar appendChild () para adicioná-lo ao elemento de vídeo! Para seleção subseqüente, posso verificar primeiro se o elemento source existe, para não repetir essa etapa.
Randy

Essa solução funciona bem se alguém estiver enfrentando o problema com o tipo de conteúdo da resposta da carga útil, mesmo que o tipo de conteúdo especificado esteja correto, mas ainda se comporte de forma estranha.
meDeepakJain

63

Modernizr funcionou como um encanto para mim.

O que eu fiz é que não usei <source>. De alguma forma, isso estragou tudo, pois o vídeo funcionou apenas na primeira vez em que load () foi chamado. Em vez disso, usei o atributo source dentro da tag video -> <video src="blabla.webm" />e usei o Modernizr para determinar qual formato o navegador suportava.

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

Espero que isso ajude você :)

Se você não quiser usar o Modernizr , sempre poderá usar CanPlayType () .


Você não quer dizer v [n] [1] pelo segundo se (Modernizr.video && Modernizr.video.ogg) é verdadeiro?
precisa saber é o seguinte

1
Depois de tentar outros métodos, tentei essa abordagem do Modernizr e funcionou bem. O Chrome (por algum motivo) não carregaria um mp4 no meu caso, mas carregaria um webm. Obrigado @MariusEngenHaugen
Adam Hey

Ainda bem que pude ser de @AdamHey serviço
Marius Engen Haugen

32

Seu plano original soa bem para mim. Você provavelmente encontrará mais peculiaridades do navegador que lidam com o gerenciamento dinâmico dos <source>elementos, conforme indicado aqui na nota de especificação do W3:

Modificar dinamicamente um elemento de origem e seu atributo quando o elemento já estiver inserido em um elemento de vídeo ou áudio não terá efeito. Para alterar o que está sendo reproduzido, basta usar o atributo src diretamente no elemento media, possivelmente usando o método canPlayType () para escolher entre os recursos disponíveis. Geralmente, manipular elementos de origem manualmente após a análise do documento é uma abordagem desnecessariamente [sic] complicada.

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


19

Eu resolvi isso com este método simples

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

10

Em vez de fazer com que o mesmo player de vídeo carregue novos arquivos, por que não apagar o <video>elemento inteiro e recriá-lo. A maioria dos navegadores irá carregá-lo automaticamente se os src's estiverem corretos.

Exemplo (usando 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
Isso diminui significativamente o navegador geral, pois mesmo após a remoção da tag de vídeo, o navegador ainda carrega os vídeos removidos até o final.
Moe Sweet

Alguns navegadores (móveis) não permitem reproduzir programaticamente mídia sem uma interação do usuário e, como você já teve uma interação com o elemento, substituí-lo por um novo perderá essa capacidade.
Max Waterman

6

Basta colocar uma div e atualizar o conteúdo ...

<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

De acordo com as especificações

Modificar dinamicamente um elemento de origem e seu atributo quando o elemento já estiver inserido em um elemento de vídeo ou áudio não terá efeito. Para alterar o que está sendo reproduzido, basta usar o atributo src diretamente no elemento media, possivelmente usando o método canPlayType () para escolher entre os recursos disponíveis. Geralmente, manipular elementos de origem manualmente após a análise do documento é uma abordagem desnecessariamente complicada.

Então, aparentemente, o que você está tentando fazer não deve funcionar.


@ greg.kindel notei depois que postei ... mas o motivo pelo qual não percebi em primeiro lugar é que o texto de introdução é confuso. De qual plano original estamos falando? O plano original original que não funcionará ou o plano original atualizado que segue as orientações que ambos publicamos?
precisa saber é

justo o suficiente, eu deveria ter citado. Eu quis dizer que o plano dele era "apenas usar esse atributo src e determinar o arquivo apropriado usando a função canPlayType ()", que funciona.
amigos estão dizendo sobre greg.kindel

4

Yaur: Embora o que você copiou e colou seja um bom conselho, isso não significa que é impossível alterar o elemento de origem de um elemento de vídeo HTML5 com elegância, mesmo no IE9 (ou IE8). (Esta solução NÃO envolve substituindo todo o elemento de vídeo, pois é uma prática ruim de codificação).

Uma solução completa para alterar / alternar vídeos em tags de vídeo HTML5 via javascript pode ser encontrada aqui e é testada em todos os navegadores HTML5 (Firefox, Chrome, Safari, IE9, etc.).

Se isso ajudar, ou se você estiver com problemas, entre em contato.


Brilhante! É assim que se faz. Você nem precisa do jQuery; no código vinculado, substitua: mp4Vid.setAttribute ('src', "/pathTo/newVideo.mp4");
Velojet 16/03/19

3

Eu venho com isso para mudar a fonte de vídeo dinamicamente. O evento "canplay" em algum momento não é acionado no Firefox, então eu adicionei "loadingmetadata". Também faço uma pausa no vídeo anterior, se houver um ...

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

A correção, definitivamente funcionou para mim, firefox não está a lidar com propriedade nem canplaynem canplaythroughe lodedmetadatanecessidades a ser adicionado (e removido mais tarde) para os manipuladores de vídeo :-(
Senhor de aberrações

3

Esta é a minha solução:

<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

O uso das <source />tags foi difícil para mim no Chrome 14.0.835.202 especificamente, embora tenha funcionado bem no FireFox. (Essa pode ser minha falta de conhecimento, mas achei que uma solução alternativa poderia ser útil de qualquer maneira.) Então, acabei usando uma <video />tag e definindo o atributo src diretamente na tag de vídeo. ocanPlayVideo('<mime type>') função foi usada para determinar se o navegador específico poderia ou não reproduzir o vídeo de entrada. O seguinte funciona no FireFox e no Chrome.

Incidentemente, o FireFox e o Chrome estão reproduzindo o formato "ogg", embora o Chrome recomende "webm". Marquei primeiro o suporte ao navegador "ogg" apenas porque outras postagens mencionaram que o FireFox prefere a fonte ogg primeiro (ou seja <source src="..." type="video/ogg"/>). Mas não testei (e duvido muito) se a ordem no código faz alguma diferença ao definir o "src" na tag de vídeo.

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

Eu tenho pesquisado isso por um bom tempo e estou tentando fazer a mesma coisa, então espero que isso ajude outra pessoa. Eu tenho usado o crossbrowsertesting.com e literalmente testando isso em quase todos os navegadores conhecidos pelo homem. A solução que tenho atualmente funciona no Opera, Chrome, Firefox 3.5+, IE8 +, iPhone 3GS, iPhone 4, iPhone 4s, iPhone 5, iPhone 5s, iPad 1+, Android 2.3+, Windows Phone 8.

Fontes de mudança dinâmica

A alteração dinâmica do vídeo é muito difícil e, se você quiser um substituto do Flash, será necessário remover o vídeo do DOM / página e adicioná-lo novamente para que o Flash seja atualizado, pois o Flash não reconhecerá atualizações dinâmicas nos vars do Flash. Se você usar o JavaScript para alterá-lo dinamicamente, eu removeria completamente todos os <source>elementos e apenas canPlayTypeo srcdefiniria em JavaScript e / breakou returnapós o primeiro tipo de vídeo suportado, e não esqueça de atualizar dinamicamente o flash var mp4. Além disso, alguns navegadores não registram que você alterou a fonte, a menos que você ligue video.load(). Acredito que o problema que .load()você estava enfrentando pode ser corrigido ligando primeirovideo.pause(). A remoção e a adição de elementos de vídeo podem desacelerar o navegador, porque ele continua armazenando o buffer do vídeo removido, mas há uma solução alternativa .

Suporte entre navegadores

Quanto à parte real do navegador, cheguei ao Video For Everybody também. Eu já experimentei o plugin MediaelementJS Wordpress, que acabou causando muito mais problemas do que resolveu. Eu suspeito que os problemas foram devido ao plug-in Wordpress e não a biblioteca realmente. Estou tentando encontrar algo que funcione sem JavaScript, se possível. Até agora, o que eu vim é esse HTML simples:

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

Notas importantes :

  • Acabou colocando o ogg como o primeiro <source>porque o Mac OS Firefox pára de tentar reproduzir o vídeo se encontrar um MP4 como o primeiro <source>.
  • Os tipos MIME corretos são arquivos .ogv importantes video/ogg, não devem ser video/ogv
  • Se você possui vídeo HD, o melhor transcodificador que encontrei para arquivos OGG de qualidade HD é o Firefogg
  • O .iphone.mp4arquivo é para o iPhone 4+, que reproduz apenas vídeos MPEG-4 com vídeo H.264 Baseline 3 Video e áudio AAC. O melhor transcodificador que encontrei para esse formato é o Handbrake, usando a predefinição do iPhone e iPod Touch funcionará no iPhone 4+, mas para que o iPhone 3GS funcione, é necessário usar a predefinição do iPod, que possui uma resolução muito mais baixa que eu adicionei video.iphone3g.mp4.
  • No futuro, poderemos usar um mediaatributo nos <source>elementos para segmentar dispositivos móveis com consultas de mídia, mas agora os dispositivos Apple e Android mais antigos não o suportam o suficiente.

Editar :

  • Ainda estou usando o Video For Everybody, mas agora mudei para o FlowPlayer, para controlar o fallback do Flash, que possui uma incrível API JavaScript que pode ser usada para controlá-lo.

Essa parece ser a resposta para a pergunta "Como reproduzo o vídeo em vários navegadores?" e não a pergunta "Como configurar uma playlist para o meu vídeo?".
Quentin

@Quentin Foi, para começar, porque foi assim que encontrei essa pergunta via Google e OP e disse que ele está tentando construir um player de vídeo que funcione em qualquer lugar. Atualizei a resposta para abordar sua pergunta dinâmica também.
18780 Alex W

2

Eu tenho um aplicativo da web semelhante e não estou enfrentando esse tipo de problema. O que eu faço é algo como isto:

var sources = new Array();

sources[0] = /path/to/file.mp4
sources[1] = /path/to/another/file.ogg
etc..

Então, quando eu quero mudar as fontes, tenho uma função que faz algo como isto:

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

    var player = document.getElementsByTagName('video')[0];
    player.load();

}

Eu faço isso para que o usuário possa percorrer uma lista de reprodução, mas você pode verificar o userAgent e carregar o arquivo apropriado dessa maneira. Tentei usar várias tags de origem, como todo mundo sugeriu na internet, mas achei muito mais limpo e muito mais confiável manipular o atributo src de uma única tag de origem. O código acima foi gravado a partir da memória, portanto, posso ter encoberto alguns detalhes do hte, mas a idéia geral é alterar dinamicamente o atributo src da tag de origem usando javascript, quando apropriado.


1

Tente mover a fonte OGG para o topo. Notei que o Firefox às vezes fica confuso e para o player quando o que ele quer tocar, OGG, não é o primeiro.

Vale a pena tentar.


1

Outra maneira de fazer no 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

Usando JavaScript e 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>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.