web-dev-qa-db-fra.com

changement de source sur le tag vidéo html5

j'essaie de construire un lecteur vidéo qui fonctionne partout. jusqu'ici j'irais avec:

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

(comme on le voit sur plusieurs sites, par exemple vidéo pour tout le monde ) jusqu'à présent, tout va bien.

mais maintenant, je veux aussi une sorte de playlist/menu avec le lecteur vidéo, à partir duquel je peux sélectionner d'autres vidéos. ceux-ci devraient être ouverts immédiatement dans mon lecteur. donc je devrai "changer dynamiquement la source de la vidéo" (comme on le voit sur dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/ - section "Regardons un autre film") avec javascript. oublions la partie flashplayer (et donc IE) pour le moment, je vais essayer de m'en occuper plus tard.

donc mon JS pour changer les balises <source> devrait être quelque chose comme:

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

le problème est que cela ne fonctionne pas dans tous les navigateurs. à savoir, firefox = O il y a une belle page, où vous pouvez observer le problème que j'ai: http://www.w3.org/2010/05/video/mediaevents.html

dès que je déclenche la méthode load () (dans firefox, remarquez), le lecteur vidéo meurt.

maintenant, j'ai découvert que lorsque je n'utilise pas plusieurs balises <source>, mais plutôt un seul attribut src dans la balise <video>, tout cela fonctionne dans firefox.

mon plan consiste donc simplement à utiliser cet attribut src et à déterminer le fichier approprié à l'aide de la fonction canPlayType () .

est-ce que je me trompe ou complique les choses?

121
sashn

Je détestais toutes ces réponses parce qu'elles étaient trop courtes ou s'appuyaient sur d'autres cadres.

Voici "une" façon de faire cela avec Vanilla JS, fonctionnant sous Chrome, veuillez tester dans d'autres navigateurs:

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

Modernizr a travaillé comme un charme pour moi.

Ce que j'ai fait, c'est que je n'ai pas utilisé <source>. D'une manière ou d'une autre, cela a tout gâché, puisque la vidéo ne fonctionnait que la première fois que load () était appelé. Au lieu de cela, j'ai utilisé l'attribut source à l'intérieur de la balise video -> <video src="blabla.webm" /> et utilisé Modernizr pour déterminer le format pris en charge par le navigateur.

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

Espérons que cela vous aidera :)

Si vous ne voulez pas utiliser Modernizr , vous pouvez toujours utiliser CanPlayType () .

63

Votre plan original me semble bien. Vous constaterez probablement que plus de bizarreries de navigateur traitent de la gestion dynamique des éléments <source>, comme indiqué ici par la note technique W3:

La modification dynamique d'un élément source et de son attribut lorsque l'élément est déjà inséré dans un élément vidéo ou audio n'aura aucun effet. Pour changer ce qui est en train de jouer, utilisez simplement l'attribut src sur l'élément média directement, en utilisant éventuellement la méthode canPlayType () pour choisir parmi les ressources disponibles. Généralement, la manipulation manuelle des éléments source après l'analyse du document est une approche compliquée sans le moindre effort.

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

32
greg.kindel

J'ai résolu ceci avec cette méthode simple

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

Au lieu de charger de nouveaux fichiers dans le même lecteur vidéo, pourquoi ne pas effacer tout l’élément <video> et le recréer. La plupart des navigateurs le chargeront automatiquement si les src sont corrects.

Exemple (en utilisant 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);
10
Stephen Walcher

Selon la spécification

La modification dynamique d'un élément source et de son attribut lorsque l'élément est déjà inséré dans un élément vidéo ou audio n'aura aucun effet. Pour changer ce qui est en train de jouer, utilisez simplement l'attribut src sur l'élément média directement, en utilisant éventuellement la méthode canPlayType () pour choisir parmi les ressources disponibles. En règle générale, la manipulation manuelle des éléments source après l'analyse du document est une approche extrêmement compliquée.

Donc, ce que vous essayez de faire n’est apparemment pas censé fonctionner.

6
Yaur

Il suffit de mettre une div et mettre à jour le contenu ...

<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

Yaur: Bien que ce que vous ayez copié et collé soit un bon conseil, cela ne signifie pas qu'il est impossible de modifier l'élément source d'un élément vidéo HTML5 de manière élégante, même dans IE9 (ou IE8 d'ailleurs). remplacer l’ensemble de l’élément vidéo, car c’est une mauvaise pratique de codage).

Une solution complète pour changer/changer les vidéos dans les balises vidéo HTML5 via javascript peut être trouvée ici et est testée dans tous les navigateurs HTML5 (Firefox, Chrome, Safari, IE9, etc.).

Si cela vous aide ou si vous rencontrez des difficultés, merci de me le faire savoir.

4
mkralla11

Ceci est ma solution:

<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>
3
IT Vlogs

Je viens avec cela pour changer la source vidéo dynamiquement. L'événement "canplay" ne se déclenche parfois pas dans Firefox, j'ai donc ajouté "Loadmetadata". Aussi, j'interromps la vidéo précédente s'il y en a une ...

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

J'ai une application Web similaire et je ne suis pas du tout confronté à ce type de problème. Ce que je fais est quelque chose comme ça:

var sources = new Array();

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

alors quand je veux changer les sources, j'ai une fonction qui fait quelque chose comme ça:

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

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

}

Je le fais pour que l'utilisateur puisse se frayer un chemin dans une liste de lecture, mais vous pouvez rechercher userAgent, puis charger le fichier approprié de cette façon. J'ai essayé d'utiliser plusieurs balises source comme suggéré par tout le monde sur Internet, mais je l'ai trouvée beaucoup plus propre et beaucoup plus fiable pour manipuler l'attribut src d'une seule balise source. Le code ci-dessus a été écrit à partir de la mémoire. Il est donc possible que j'aie dissimulé certains détails, mais l'idée générale est de modifier dynamiquement l'attribut src de la balise source à l'aide de javascript, le cas échéant.

2
aamiri

L’utilisation des balises <source /> s’est révélée difficile pour moi dans Chrome 14.0.835.202, bien que cela ait fonctionné correctement pour moi dans FireFox. (Cela pourrait être mon manque de connaissances, mais je pensais qu'une solution alternative pourrait être utile de toute façon.) Donc, j'ai fini par utiliser simplement une balise <video /> et définir l'attribut src directement sur la balise vidéo elle-même. La fonction canPlayVideo('<mime type>') a été utilisée pour déterminer si un navigateur spécifique pouvait ou non lire la vidéo en entrée. Ce qui suit fonctionne dans FireFox et Chrome.

Incidemment, FireFox et Chrome lisent le format "ogg", bien que Chrome recommande "Webm". Je mets en premier la vérification de la prise en charge de "ogg" par le navigateur, car d'autres publications ont mentionné que FireFox préfère d'abord la source ogg (c'est-à-dire <source src="..." type="video/ogg"/>). Mais, je n’ai pas testé (et doute fort) que l’ordre dans le code fasse une différence lors du réglage du "src" sur la balise video.

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
ItsAllABadJoke

Je fais des recherches à ce sujet depuis un certain temps et j'essaie de faire la même chose, alors j'espère que cela aidera quelqu'un d'autre. J'utilise crossbrowsertesting.com et le teste littéralement dans presque tous les navigateurs connus de l'homme. La solution que j'ai actuellement fonctionne dans Opera, Chrome, Firefox 3.5 et versions ultérieures, IE8 +, iPhone 3GS, iPhone 4, iPhone 4s, iPhone 5, iPhone 5s, iPad 1+, Android 2.3+, Windows Phone 8.

Modification dynamique des sources

Il est très difficile de modifier dynamiquement la vidéo. Si vous souhaitez un repli Flash, vous devez supprimer la vidéo de la page DOM/page et la rajouter afin que Flash se mette à jour, car Flash ne reconnaîtra pas les mises à jour dynamiques des fichiers Flash. Si vous envisagez d'utiliser JavaScript pour le modifier de manière dynamique, je supprimerais complètement tous les éléments <source> et n'utiliserais que canPlayType pour définir le paramètre src en JavaScript et break ou return après la première vidéo prise en charge. tapez et n'oubliez pas de mettre à jour dynamiquement le flash var mp4. De plus, certains navigateurs ne diront pas que vous avez changé de source sauf si vous appelez video.load(). Je pense que le problème avec .load() que vous avez rencontré peut être résolu en appelant d'abord video.pause(). La suppression et l'ajout d'éléments vidéo peuvent ralentir le navigateur car il continue à mettre en mémoire tampon la vidéo supprimée, mais il existe une solution de contournement .

Prise en charge de plusieurs navigateurs

En ce qui concerne la partie de navigation réelle, je suis arrivé à Video For Everybody . J'ai déjà essayé le plugin MediaelementJS Wordpress, qui a posé beaucoup plus de problèmes qu'il n'a résolu. Je soupçonne que les problèmes étaient dus au plug-in Wordpress et non à la bibliothèque. J'essaie de trouver quelque chose qui fonctionne sans JavaScript, si possible. Jusqu'ici, ce que j'ai trouvé est ce HTML simple:

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

Remarques importantes :

  • Nous avons fini par placer l'ogg en tant que premier <source>, car Mac OS Firefox cesse d'essayer de lire la vidéo s'il rencontre un MP4 en tant que premier <source>.
  • Les types MIME corrects sont importants . Les fichiers ogv doivent être video/ogg, et non video/ogv
  • Si vous avez une vidéo HD, le meilleur transcodeur que j'ai trouvé pour les fichiers OGG de qualité HD est Firefogg
  • Le fichier .iphone.mp4 est destiné à l'iPhone 4+ qui ne lit que les vidéos qui sont MPEG-4 avec H.264. Baseline 3 Video et AAC audio. Le meilleur transcodeur que j'ai trouvé pour ce format est Handbrake. L'utilisation du préréglage pour iPhone et iPod Touch fonctionnera sur iPhone 4+, mais pour que l'iPhone 3GS fonctionne, vous devez utiliser le iPod préréglage qui a une résolution beaucoup plus basse que j’ai ajoutée comme video.iphone3g.mp4.
  • À l'avenir, nous pourrons utiliser un attribut media sur les éléments <source> pour cibler les périphériques mobiles avec des requêtes multimédia, mais les anciens Apple et Android don ne le supporte pas assez bien.

Éditer :

  • J'utilise toujours Video For Everybody, mais je suis maintenant passé à FlowPlayer pour contrôler le repli de Flash, qui possède un génial JavaScript API qui peut être utilisé pour le contrôler.
2
Alex W

Essayez de déplacer la source OGG vers le haut. J'ai remarqué que Firefox s'embrouille parfois et arrête le joueur lorsque celui qu'il veut jouer, OGG, n'est pas le premier.

Ça vaut le coup d'essayer.

1
Ian Devlin

Une autre façon de faire dans 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
青木 Japan

Utilisation de JavaScript et de 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>
0
pbies