modifica della fonte sul tag video html5


138

Sto cercando di costruire un video player, che funzioni ovunque. finora andrei con:

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

(come visto su diversi siti, ad esempio video per tutti ) finora, tutto bene.

ma ora voglio anche una sorta di playlist / menu insieme al video player, dal quale posso selezionare altri video. quelli dovrebbero essere aperti nel mio lettore immediatamente. quindi dovrò "cambiare dinamicamente la fonte del video" (come visto su dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/ - section "Guardiamo un altro film ") con javascript. dimentichiamoci del flashplayer (e quindi di IE) per il momento, cercherò di affrontarlo più tardi.

quindi il mio JS per cambiare i <source>tag dovrebbe essere qualcosa del tipo:

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

il problema è che non funziona in tutti i browser. vale a dire, firefox = O c'è una bella pagina, dove puoi osservare il problema che sto riscontrando: http://www.w3.org/2010/05/video/mediaevents.html

non appena innesco il metodo load () (in Firefox, intendiamoci), il lettore video muore.

ora ho scoperto che quando non uso più <source>tag, ma invece solo un attributo src all'interno del <video>tag, tutto funziona in firefox.

quindi il mio piano è semplicemente quello di usare quell'attributo src e determinare il file appropriato usando la funzione canPlayType () .

sto facendo qualcosa di sbagliato o complicando le cose ??


Suona bene per me. In che modo "complicare" semplificare il markup?
Matt Ball

il problema è che mi vedo imbattermi in molti javascript e distinzione di casi. se forse mi sono perso qualcosa, come se ci fosse un modo per farlo funzionare in Firefox con più <source>tag. allora suppongo che sarebbe più facile
sashn

hai mai pensato alla parte flash su ie8?
Neeraj,

@Neeraj la soluzione finale prevedeva il plug-in video.js che utilizza un flash player come fallback per IE8 e simili. oggi potrebbero esserci plugin superiori. anche l'uso del plugin non ha aiutato con il problema di firefox relativo al metodo load (), che era la motivazione iniziale per questo post. oggi, sembra che il problema sia stato risolto da tempo.
sashn,

Risposte:


169

Odiavo tutte queste risposte perché erano troppo brevi o si basavano su altri framework.

Ecco "un" modo JS vanilla per farlo, lavorando in Chrome, per favore prova in altri browser:

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
Questo è stato il più pulito ed efficiente per me.
Phil McCarty,

Non sono riuscito a far giocare a palla Chrome con questo. SOLO se imposto l'attributo src video sul percorso webm
Adam Hey

2
Il metodo di riproduzione è consentito solo da un gesto dell'utente in alcuni criteri del browser.
Anson

Lo apprezzo così tanto per un altro motivo! Ho cercato di impostare una pagina di video che non mostra NESSUN video fino a quando il visitatore non ne seleziona uno. Potrei impostare un tag video con un tag sorgente vuoto, ma genererebbe sempre un errore su una console di debug javascript. Ora so di poter trattenere l'aggiunta di una "fonte" fino a quando l'utente non ne seleziona una. Fino ad ora, non ho capito che dovevo creare CreateElement () per creare una fonte, quindi aggiungere appendChild () per aggiungerlo all'elemento video! Per la selezione successiva, posso prima verificare se l'elemento sorgente esiste, quindi non ripeto quel passaggio.
Randy,

Questa soluzione funziona benissimo se qualcuno si trova ad affrontare il problema con il tipo di contenuto dalla risposta del payload anche se il tipo di contenuto specificato è corretto ma si comporta comunque in modo strano.
meDeepakJain

63

Modernizr ha funzionato come un incanto per me.

Quello che ho fatto è che non ho usato <source>. In qualche modo questo ha rovinato tutto, dal momento che il video ha funzionato solo la prima volta che è stato chiamato load (). Invece ho usato l'attributo source all'interno del tag video -> <video src="blabla.webm" />e ho usato Modernizr per determinare quale formato supportava il browser.

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

Spero che questo ti possa aiutare :)

Se non vuoi usare Modernizr , puoi sempre usare CanPlayType () .


Non intendi v [n] [1] per il secondo se (Modernizr.video && Modernizr.video.ogg) è vero?
Bergie3000,

1
Dopo aver provato altri metodi, ho provato questo approccio Modernizr e ha funzionato bene. Chrome (per qualche motivo) non caricava un mp4 nel mio caso, ma caricava un webm. Grazie @MariusEngenHaugen
Adam Hey

Sono contento di poter essere al servizio di @AdamHey
Marius Engen Haugen il

32

Il tuo piano originale suona bene per me. Probabilmente troverai più stranezze del browser che si occupano della gestione dinamica degli <source>elementi, come indicato qui dalla nota specifica W3:

La modifica dinamica di un elemento sorgente e del suo attributo quando l'elemento è già inserito in un elemento video o audio non avrà alcun effetto. Per cambiare ciò che sta giocando, usa semplicemente l'attributo src sull'elemento media direttamente, usando eventualmente il metodo canPlayType () per scegliere tra le risorse disponibili. Generalmente, la manipolazione manuale degli elementi sorgente dopo che il documento è stato analizzato è un approccio inutilmente complicato.

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


19

Ho risolto questo con questo semplice metodo

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

10

Invece di ottenere lo stesso lettore video per caricare nuovi file, perché non cancellare l'intero <video>elemento e ricrearlo. La maggior parte dei browser lo caricherà automaticamente se gli SRC sono corretti.

Esempio (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
Ciò rallenta in modo significativo l'intero browser poiché, anche dopo la rimozione del tag video, il browser carica ancora i video rimossi fino alla fine.
Moe Sweet,

Alcuni browser (mobili) non ti consentono di riprodurre in modo programmatico file multimediali senza l'interazione dell'utente e, poiché hai già avuto un'interazione sull'elemento, sostituendolo con uno nuovo perderà tale capacità.
Max Waterman,

6

Basta fare un div e aggiornare il contenuto ...

<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

Secondo le specifiche

La modifica dinamica di un elemento sorgente e del suo attributo quando l'elemento è già inserito in un elemento video o audio non avrà alcun effetto. Per cambiare ciò che sta giocando, usa semplicemente l'attributo src sull'elemento media direttamente, usando eventualmente il metodo canPlayType () per scegliere tra le risorse disponibili. In genere, la manipolazione manuale degli elementi di origine dopo l'analisi del documento è un approccio inutilmente complicato.

Quindi, a quanto pare, ciò che stai cercando di fare non dovrebbe funzionare.


@ greg.kindel Ho notato dopo che ho pubblicato ... ma il motivo per cui non ho notato in primo luogo è che il tuo testo introduttivo è confuso. Di quale piano originale stiamo parlando? Il piano originale originale che non funzionerà o il piano originale aggiornato che segue la guida che entrambi abbiamo pubblicato?
Yaur,

abbastanza giusto, avrei dovuto citare. Intendevo il suo piano per "usare solo quell'attributo src e determinare il file appropriato usando la funzione canPlayType ()" che funziona.
greg.kindel,

4

Yaur: Anche se ciò che hai copiato e incollato è un buon consiglio, ciò non significa che sia impossibile cambiare in modo elegante l'elemento sorgente di un elemento video HTML5, anche in IE9 (o IE8 per quella materia). (Questa soluzione NON prevede sostituendo l'intero elemento video, poiché è una cattiva pratica di codifica).

Una soluzione completa per cambiare / cambiare video nei tag video HTML5 tramite javascript può essere trovata qui ed è testata in tutti i browser HTML5 (Firefox, Chrome, Safari, IE9, ecc.).

Se questo aiuta, o se hai problemi, per favore fatemelo sapere.


Brillante! Questo è il modo di farlo. Non hai nemmeno bisogno di jQuery; nel codice collegato, sostituire: mp4Vid.setAttribute ('src', "/pathTo/newVideo.mp4");
Velojet

3

Vengo con questo per cambiare dinamicamente la sorgente video. L'evento "canplay" a volte non si attiva in Firefox, quindi ho aggiunto "loadedmetadata". Inoltre metto in pausa il video precedente se ce n'è uno ...

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

La soluzione, sicuramente funzionata per me, Firefox non gestisce né la proprietà canplaycanplaythroughe lodedmetadatadeve essere aggiunta (e rimossa in seguito) ai gestori di video :-(
Lord of freaks

3

Questa è la mia soluzione:

<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

L'uso dei <source />tag si è rivelato difficile per me in Chrome 14.0.835.202 in particolare, anche se ha funzionato bene per me in FireFox. (Questa potrebbe essere la mia mancanza di conoscenza, ma ho pensato che una soluzione alternativa potrebbe essere utile comunque.) Quindi, ho finito per usare solo un <video />tag e impostare l'attributo src proprio sul tag video stesso. La canPlayVideo('<mime type>')funzione è stata utilizzata per determinare se il browser specifico poteva o meno riprodurre il video di input. Quanto segue funziona in FireFox e Chrome.

Per inciso, sia FireFox che Chrome stanno riproducendo il formato "ogg", sebbene Chrome consiglia "webm". Ho messo il controllo per il supporto del browser di "ogg" solo perché altri post hanno menzionato che FireFox preferisce prima la sorgente ogg (cioè <source src="..." type="video/ogg"/>). Ma non ho testato (e dubito fortemente) se l'ordine nel codice fa qualche differenza o meno quando si imposta "src" sul tag 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

Ho studiato questo per un bel po 'e sto cercando di fare la stessa cosa, quindi spero che questo possa aiutare qualcun altro. Ho usato crossbrowsertesting.com e testato letteralmente questo in quasi tutti i browser conosciuti dall'uomo. La soluzione che ho attualmente funziona in Opera, Chrome, Firefox 3.5+, IE8 +, iPhone 3GS, iPhone 4, iPhone 4s, iPhone 5, iPhone 5s, iPad 1+, Android 2.3+, Windows Phone 8.

Sorgenti che cambiano dinamicamente

Modificare dinamicamente il video è molto difficile e se si desidera un fallback Flash, sarà necessario rimuovere il video dalla pagina DOM / e aggiungerlo di nuovo in modo che Flash si aggiorni perché Flash non riconoscerà gli aggiornamenti dinamici alle variabili Flash. Se utilizzerai JavaScript per modificarlo in modo dinamico, rimuoverei completamente tutti gli <source>elementi e utilizzerei semplicemente canPlayTypeper impostare srcin JavaScript e breako returndopo il primo tipo di video supportato e non dimenticare di aggiornare dinamicamente il flash var mp4. Inoltre, alcuni browser non registrano che hai cambiato la fonte a meno che non chiami video.load(). Credo che il problema con .load()te che stavi riscontrando possa essere risolto chiamando primavideo.pause(). La rimozione e l'aggiunta di elementi video può rallentare il browser perché continua a eseguire il buffering del video rimosso, ma esiste una soluzione alternativa .

Supporto per più browser

Per quanto riguarda l'attuale porzione cross-browser, sono arrivato anche a Video For Everybody . Ho già provato il plugin MediaelementJS Wordpress, che si è rivelato causa di molti più problemi di quanti ne abbia risolto. Ho il sospetto che i problemi fossero dovuti al plug-in di Wordpress e non alla vera libreria. Sto cercando di trovare qualcosa che funzioni senza JavaScript, se possibile. Finora, quello che ho escogitato è questo semplice 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>

Note importanti :

  • Finì per mettere l'oggetto come il primo <source>perché Mac OS Firefox smette di provare a riprodurre il video se incontra un MP4 come primo <source>.
  • I tipi MIME corretti sono file .ogv importanti che dovrebbero essere video/ogg, no video/ogv
  • Se hai video HD, il miglior transcoder che ho trovato per file OGG di qualità HD è Firefogg
  • Il .iphone.mp4file è per iPhone 4+ che riprodurrà solo video MPEG-4 con video H.264 Baseline 3 e audio AAC. Il miglior transcodificatore che ho trovato per quel formato è Handbrake, l'uso del preset iPhone e iPod Touch funzionerà su iPhone 4+, ma per far funzionare iPhone 3GS devi usare il preset iPod che ha una risoluzione molto più bassa che ho aggiunto video.iphone3g.mp4.
  • In futuro saremo in grado di utilizzare un mediaattributo sugli <source>elementi per indirizzare i dispositivi mobili con query multimediali, ma al momento i vecchi dispositivi Apple e Android non lo supportano abbastanza bene.

Modifica :

  • Sto ancora usando Video per tutti ma ora sono passato all'utilizzo di FlowPlayer, per controllare il fallback di Flash, che ha una fantastica API JavaScript che può essere utilizzata per controllarlo.

Questa sembra essere la risposta alla domanda "Come si riproducono i video cross-browser?" e non questa domanda che è "Come impostare una playlist per il mio video?".
Quentin,

@Quentin Era, per cominciare, perché è così che ho trovato questa domanda tramite Google e OP ha detto che sta cercando di costruire un video player che funzioni ovunque. Ho aggiornato la risposta anche per rispondere alla sua domanda dinamica.
Alex W,

2

Ho un'app Web simile e non sto affrontando questo tipo di problema. Quello che faccio è qualcosa del genere:

var sources = new Array();

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

poi quando voglio cambiare le fonti ho una funzione che fa qualcosa del genere:

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

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

}

Lo faccio in modo che l'utente possa farsi strada attraverso una playlist, ma è possibile verificare userAgent e quindi caricare il file appropriato in quel modo. Ho provato a utilizzare più tag di origine come suggerito da tutti su Internet, ma l'ho trovato molto più pulito e molto più affidabile per manipolare l'attributo src di un singolo tag di origine. Il codice sopra è stato scritto dalla memoria, quindi potrei aver ripassato alcuni dei dettagli hte, ma l'idea generale è quella di cambiare dinamicamente l'attributo src del tag sorgente usando javascript, quando appropriato.


1

Prova a spostare la sorgente OGG verso l'alto. Ho notato che a volte Firefox viene confuso e arresta il lettore quando quello che vuole giocare, OGG, non è il primo.

Vale la pena provare.


1

Un altro modo in cui puoi fare in 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

Utilizzando 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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.