changer la source sur la balise vidéo html5

j'essaie de construire un lecteur vidéo, qui fonctionne partout. jusqu'à présent, je dirais:

<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 vu sur plusieurs sites, par exemple vidéo pour tout le monde ) pour l'instant, donc bon.

mais maintenant je veux aussi une sorte de sélection/menu avec le lecteur vidéo, à partir duquel je peux sélectionner d'autres vidéos. ceux-ci devraient être ouverts dans mon lecteur. donc je vais devoir "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/ - la section "regardons un autre film") avec javascript. oublions la partie flashplayer (et donc IE) pour le moment, j'essaierai de m'en occuper plus tard.

donc mon JS pour changer les étiquettes <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>

problème est, cela ne fonctionne pas dans tous les navigateurs. à savoir, firefox =O il y a un nice 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, attention), le lecteur vidéo meurt.

maintenant j'ai découvert que lorsque je n'utilise pas plusieurs <source> tags, mais à la place juste un attribut src dans le <video> tags, Le Tout fonctionne dans firefox.

donc mon plan est de juste utilisez cet attribut src et déterminez le fichier approprié en utilisant la fonction canPlayType() .

suis-je en train de faire quelque chose de mal ou de compliquer les choses??

101
demandé sur Caramiriel 2011-03-08 19:15:48

14 réponses

j'ai détesté toutes ces réponses parce qu'elles étaient trop courtes ou reposaient sur d'autres cadres.

voici" un "vanilla js façon de le faire, en travaillant dans Chrome, s'il vous plaît 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);
116
répondu mattdlockyer 2017-11-07 10:18:25

Modernizr a fonctionné 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 fait foirer, puisque la vidéo n'a fonctionné que la première fois que load() a été appelé. J'ai plutôt utilisé l'attribut source à l'intérieur de la balise vidéo -> <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 () .

60
répondu Marius Engen Haugen 2013-09-23 12:40:32

votre plan original me semble bien. Vous trouverez probablement d'autres bizarreries de navigateur traitant de la gestion dynamique des éléments <source> , comme indiqué ici par la note de spécification W3:

modifier dynamiquement un élément source et son attribut lorsque l'élément est déjà inséré dans un élément vidéo ou audio n'aura aucun effet. Pour modifier ce qui est lu, il suffit d'utiliser l'attribut src sur l'élément media directement, en utilisant éventuellement le méthode canPlayType () à choisir parmi les ressources disponibles. En règle générale, la manipulation manuelle des éléments sources après l'analyse du document est une approche inutilement compliquée.

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

29
répondu greg.kindel 2012-04-11 16:36:06

j'ai résolu ce problème avec cette méthode simple

function changeSource(url) {
   var video = document.getElementById('video');
   video.src = url;
   video.play();
}
12
répondu Joaquin Iurchuk 2015-02-18 03:27:15

au lieu d'obtenir le même lecteur vidéo pour charger de nouveaux fichiers, 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 (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);
9
répondu Stephen Walcher 2011-03-20 22:37:00

Selon spec

modifiant dynamiquement un élément source et son attribut lorsque le élément est déjà inséré dans un élément vidéo ou audio n'aura pas effet. Pour changer ce qui est joué, il suffit d'utiliser l'attribut src sur le élément média directement, en utilisant éventuellement le canPlayType() méthode pour choisir parmi les ressources disponibles. Généralement, la manipulation manuelle des éléments de source après la le document a été parsed est une approche inutilement compliquée.

pour ce que vous essayez de faire est apparemment pas censé travailler.

6
répondu Yaur 2016-11-03 00:55:56

Yaur: bien que ce que vous avez copié et collé soit un bon conseil, cela ne signifie pas qu'il est impossible de changer élégamment l'élément source d'un élément vidéo HTML5, même dans IE9 (ou IE8 d'ailleurs).(Cette solution ne consiste pas à remplacer tout l'élément vidéo, car il s'agit d'une mauvaise pratique de codage).

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

si cela vous aide, ou si vous avez des problèmes, faites-le moi savoir.

4
répondu mkralla11 2017-05-23 11:33:26

il suffit de mettre un 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>
4
répondu Jose Antonio Galeano 2014-11-25 14:29:47

je viens avec ceci pour changer dynamiquement la source vidéo. parfois, l'événement" canplay "ne se déclenche pas dans Firefox, j'ai donc ajouté"loadedmetadata". Je mets aussi en pause 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
répondu molokoloco 2015-02-19 15:47:29

C'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
répondu Dung Vu 2017-12-01 23:02:16

utilisant les étiquettes <source /> s'est avéré difficile pour moi dans Chrome 14.0.835.202 spécifiquement, bien qu'il ait fonctionné très bien pour moi dans FireFox. (Cela pourrait être mon manque de connaissances, mais j'ai pensé qu'une solution alternative pourrait être utile de toute façon.) Donc, j'ai fini par juste utiliser une balise <video /> et paramétrer 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 le navigateur en question pouvait ou non lire la vidéo d'entrée. Les travaux suivants dans FireFox et Chrome.

incidemment, FireFox et Chrome jouent le format" ogg", bien que Chrome recommande"webm". J'ai mis la vérification de la prise en charge du navigateur de "ogg" en premier seulement parce que D'autres postes ont mentionné que FireFox préfère la source ogg en premier (i.e. <source src="..." type="video/ogg"/> ). Mais, je n'ai pas testé (et je doute fortement) si oui ou non l'ordre dans le code fait une différence lors de la mise en place du "src" sur la balise vidéo.

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
répondu ItsAllABadJoke 2011-10-17 20:51:52

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

Sources En Évolution Dynamique

changer dynamiquement la vidéo est très difficile, et si vous voulez un flash repli, vous devrez supprimer la vidéo du DOM/page et de le ré-ajouter de sorte que Flash sera mise à jour parce que Flash ne sera pas reconnaître les mises à jour dynamiques de Flash vars. Si vous allez utiliser JavaScript pour le changer dynamiquement, je supprimerais complètement tous les éléments <source> et juste utiliser canPlayType pour définir le src en JavaScript et break ou return après le premier type de vidéo pris en charge et n'oubliez pas de mettre à jour dynamiquement le flash var mp4. En outre, certains navigateurs ne s'enregistreront pas que vous avez changé la source à moins que vous appeliez video.load() . Je crois que le problème avec .load() que vous éprouviez peut être corrigé en appelant d'abord video.pause() . Supprimer et ajouter des éléments vidéo peut ralentir le navigateur car il continue à tamponner la vidéo retirée, mais Il ya une solution de contournement .

Cross-browser Support

en ce qui concerne la partie réelle de cross-browser, je suis arrivé à vidéo pour tout le monde aussi bien. J'ai déjà essayé le plugin Wordpress MediaelementJS, qui s'est avéré causer beaucoup plus de problèmes qu'il n'en a résolu. Je soupçonne que les problèmes étaient dus au plug-in Wordpress et pas la bibliothèque en fait. J'essaie de trouver quelque chose qui fonctionne sans JavaScript, si possible. Si loin, 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 :

  • a fini par mettre l'ogg comme le premier <source> parce que Mac OS Firefox quitte en essayant de jouer la vidéo si elle rencontre un MP4 comme le premier <source> .
  • les types MIME corrects sont importants .ogv les fichiers devraient être video/ogg , 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 pour iPhone 4+ qui sera seulement lire des vidéos qui sont MPEG-4 avec H. 264 Baseline 3 Vidéo et audio AAC. Le meilleur transcodeur que j'ai trouvé pour ce format est Frein À Main, En utilisant le iPhone et iPod Touch preset fonctionnera sur iPhone 4+, mais pour obtenir iPhone 3GS pour travailler, vous avez besoin d'utiliser le iPod preset qui a une résolution beaucoup plus faible que j'ai ajouté comme video.iphone3g.mp4 .
  • à l'avenir, nous serons en mesure d'utiliser un attribut media sur les éléments <source> pour cibler les appareils mobiles avec des requêtes médias, mais à l'heure actuelle, les anciens appareils Apple et Android ne le prennent pas suffisamment en charge.

Modifier :

  • j'utilise toujours la vidéo pour tout le monde mais maintenant j'ai fait la transition à L'aide de FlowPlayer, pour contrôler le retour de flamme, qui a un impressionnant API JavaScript qui peut être utilisé pour le contrôler.
2
répondu Alex W 2017-05-23 12:26:33

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

Vaut la peine d'essayer.

1
répondu Ian Devlin 2011-03-08 17:12:40

j'ai une application web similaire et je ne suis pas face à ce genre de problème du tout. Ce que je fais est quelque chose comme ceci:

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 fais cela pour que l'utilisateur puisse faire son chemin à travers une liste de lecture, mais vous pouvez vérifier pour userAgent et puis Charger le fichier approprié de cette façon. J'ai essayé d'utiliser plusieurs tags source comme tout le monde sur le internet a suggéré, mais je l'ai trouvé beaucoup plus propre et beaucoup plus fiable pour manipuler l'attribut src d'une source unique balise. Le code ci-dessus a été écrit de mémoire, de sorte que j'ai peut-être glissé sur certains des détails hte, mais l'idée générale est de changer dynamiquement l'attribut src de la balise source en utilisant javascript, le cas échéant.

1
répondu aamiri 2018-07-06 11:13:14