зміна джерела на html5 відеотег


138

Я намагаюся створити відеоплеєр, який працює скрізь. поки що я б ішов із:

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

(як видно на кількох сайтах, наприклад, відео для всіх) ) поки що, так добре.

але тепер я також хочу певний список відтворення / меню разом із відеоплеєром, з якого я можу вибрати інші відео. їх слід відкрити в моєму плеєрі відразу. тому мені доведеться "динамічно змінювати джерело відео" (як це видно на dev.opera.com/articles/everything-you-need-to-know-html5-video-audio/ - розділ "Давайте подивимось на інший фільм ") з JavaScript. забудьмо про частину флешплеєра (і, отже, IE) на даний момент, я спробую розібратися з цим пізніше.

тому мій JS для зміни <source>тегів повинен бути чимось на кшталт:

<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 = O є приємна сторінка, на якій ви можете спостерігати за проблемою, яку я маю: http://www.w3.org/2010/05/video/mediaevents.html

Як тільки я запускаю метод load () (у firefox, пам'ятаю), відеоплеєр гине.

Тепер я з'ясував, що коли я не використовую декілька <source>тегів, а замість цього лише один атрибут src у <video>тезі, все це працює у Firefox.

тому мій план - просто використовувати цей атрибут src та визначити відповідний файл за допомогою функції canPlayType () .

я щось роблю неправильно чи ускладнюю речі ??


Це звучить мені просто чудово. Як "ускладнювати" спрощення розмітки?
Метт Бал

Проблема полягає в тому, що я бачу, що я стикаюся з великою кількістю javascript і розрізненням випадків. якщо, можливо, я щось пропустив, наче був спосіб змусити його працювати у firefox З декількома <source>тегами. то я гадаю, що це буде простіше
Sashn

Ви коли-небудь розбиралися про флеш-частину на ie8?
Неєрай

@Neeraj остаточне рішення включало плагін video.js, який використовує флеш-плеєр як резервний IE8 та подібні. сьогодні можуть бути чудові плагіни. використання плагіна також не допомогло з проблемою firefox щодо методу load (), що було початковою мотивацією для цієї публікації. сьогодні, здається, це питання вже давно вирішене.
сашн

Відповіді:


169

Я ненавидів усі ці відповіді, оскільки вони були занадто короткими або опиралися на інші рамки.

Ось "один" спосіб ванільного JS для цього, працюючи в Chrome, будь ласка, протестуйте в інших браузерах:

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
Це було для мене найчистішим та найефективнішим.
Філ Маккарті

Я не міг змусити Chrome зіграти з цим м'ячем. ТІЛЬКИ, якщо я встановив атрибут video src на шлях веб-сайтів
Адам Ей,

2
Метод відтворення дозволений лише жестом користувача в деяких політиках браузера.
Ансон

Я дуже ціную це з іншої причини! Я намагався створити сторінку відео, яка не показує жодного відео, поки відвідувач не вибере її. Я міг би встановити відеотег із порожнім тегом джерела, але він завжди генерував би збій на консолі налагодження javascript. Тепер я знаю, що можу відмовитись від додавання "джерела", поки користувач не вибере його. До цього часу я не розумів, що мені потрібно використовувати CreateElement () для створення джерела, а потім використовую appendChild (), щоб додати його до відеоелементу! Для подальшого вибору я можу спочатку перевірити, чи існує вихідний елемент, щоб я не повторював цей крок.
Ренді

Це рішення чудово працює, якщо хтось стикається з проблемою типу вмісту з відповіді корисного навантаження, навіть якщо вказаний тип вмісту правильний, але все ще ведеться дивно.
meDeepakJain

63

Модернізр працював як шарм для мене.

Що я зробив, це те, що я не використовував <source>. Якось це накрутило речі, оскільки відео працювало лише під час першого виклику завантаження (). Натомість я використав атрибут source всередині тегу відео -> <video src="blabla.webm" />та використав 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 () .


Ви не маєте на увазі секунди v [n] [1], якщо (Modernizr.video && Modernizr.video.ogg) вірно?
bergie3000

1
Спробувавши інші методи, я спробував цей підхід Модернізра, і він добре працював. Chrome (чомусь) не завантажує mp4 у моєму випадку, але завантажує webm. Спасибі @MariusEngenHaugen
Адам Ей,

Радий, що можу послужити @AdamHey
Marius Engen Haugen

32

Ваш оригінальний план мені добре звучить. Напевно ви знайдете більше примх браузера, що займаються динамічним керуванням <source>елементами, як тут зазначено у примітці W3

Динамічна модифікація вихідного елемента та його атрибута, коли елемент вже вставлений у відео- чи аудіоелемент, не матиме ефекту. Щоб змінити те, що відтворюється, просто використовуйте атрибут src на медіа-елементі безпосередньо, можливо, використовуючи метод canPlayType (), щоб вибрати серед доступних ресурсів. Взагалі, маніпулювання вихідними елементами вручну після розбору документа - це несильно [sic] складний підхід.

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


19

Я вирішив це цим простим методом

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

10

Замість того, щоб той самий відеоплеєр завантажував нові файли, чому б не стерти весь <video>елемент і відтворити його. Більшість браузерів автоматично завантажить його, якщо src є правильним.

Приклад (з використанням прототипу ):

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
Це значно сповільнює загальний браузер, оскільки навіть після видалення тегу відео браузер все ще завантажує вилучені відео до кінця.
Moe Sweet

Деякі веб-переглядачі (мобільні) не дозволяють програмувати медіа без взаємодії з користувачем, і оскільки ви вже мали взаємодію з елементом, заміна його на новий втратить цю здатність.
Макс Вотерман

6

Просто поставте 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>

6

За даними спец

Динамічна модифікація вихідного елемента та його атрибута, коли елемент вже вставлений у відео- чи аудіоелемент, не матиме ефекту. Щоб змінити те, що відтворюється, просто використовуйте атрибут src на медіа-елементі безпосередньо, можливо, використовуючи метод canPlayType (), щоб вибрати серед доступних ресурсів. Як правило, маніпулювання вихідними елементами вручну після розбору документа - це нескінченно складний підхід.

Отже, те, що ви намагаєтеся зробити, мабуть, не повинно працювати.


@ greg.kindel Я помітив після публікації ... але причина, яку я не помітила в першу чергу, полягає в тому, що ваш вступний текст заплутаний. Про який оригінальний план ми говоримо? Початковий оригінальний план, який не працюватиме, або оновлений оригінальний план, що відповідає вказівкам, які ми обидва розмістили?
Yaur

досить чесно, я повинен був би процитувати. Я мав на увазі його план "просто використовувати цей атрибут src та визначити відповідний файл за допомогою функції canPlayType ()", яка працює.
greg.kindel

4

Яур: Хоча те, що ви скопіювали та вставили, є гарною порадою, це не означає, що неможливо елегантно змінити вихідний елемент відео-елемента HTML5 навіть у IE9 (або з цього приводу IE8). (Це рішення НЕ передбачає заміна всього відеоелемента, оскільки це погана практика кодування).

Повне рішення щодо зміни / перемикання відео в HTML5 теги відео через JavaScript можна знайти тут і перевірено у всіх браузерах HTML5 (Firefox, Chrome, Safari, IE9 тощо).

Якщо це допомагає або у вас виникають проблеми, будь ласка, повідомте мене про це.


Блискуче! Це спосіб це зробити. Вам навіть не потрібен jQuery; у зв'язаному коді замініть: mp4Vid.setAttribute ('src', "/pathTo/newVideo.mp4");
Велоджет

3

Я прийшов із цим, щоб динамічно змінювати джерело відео. Подія "canplay" колись не запускається у Firefox, тому я додав "завантажені дані". Також я призупиняю попереднє відео, якщо є таке ...

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

Виправлення, безумовно , працював для мене, світлячок і не виконує жодних властивість ні canplayні canplaythroughі lodedmetadataпотреби , які будуть додані (і видалені пізніше) до відео обработчиками :-(
Лорд виродків

3

Це моє рішення:

<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

Використання <source />тегів виявилося важким для мене в Chrome 14.0.835.202, хоча це було добре для мене у FireFox. (Це може бути мій недолік знань, але я подумав, що альтернативне рішення все-таки може бути корисним.) Отже, я закінчив просто використовувати <video />тег і встановити атрибут src прямо на самому відеотезі. ThecanPlayVideo('<mime type>') функція використовується для визначення, чи може конкретний браузер відтворювати вхідне відео чи ні. Наступні роботи у FireFox та Chrome.

Між іншим, і FireFox, і Chrome відтворюють формат "ogg", хоча Chrome рекомендує "webm". Я поставив перевірку на підтримку браузера "ogg" спочатку лише тому, що в інших публікаціях згадується, що FireFox спочатку віддає перевагу джерелу ogg (тобто <source src="..." type="video/ogg"/>). Але я не перевіряв (і дуже сумніваюся), чи має це порядок у коді взагалі якусь різницю при встановленні "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();
  }

2

Я досліджував це досить довгий час, і намагаюся зробити те саме, тому, сподіваюся, це допоможе комусь іншому. Я використовую 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 vars. Якщо ви збираєтесь використовувати JavaScript, щоб змінити її динамічно, я б повністю видалив усі <source>елементи, а просто застосував би canPlayTypeдля встановлення srcJavaScript і / breakабо returnпісля першого підтримуваного типу відео і не забудьте динамічно оновити flash var mp4. Також деякі веб-переглядачі не реєструють, що ви змінили джерело, якщо не дзвоните video.load(). Я вважаю, що проблему, з якою .load()ви стикалися, можна вирішити, зателефонувавши спочаткуvideo.pause(). Видалення та додавання відео елементів може уповільнити веб-переглядач, оскільки він продовжує буферизувати видалене відео, але існує спосіб вирішення .

Підтримка крос-браузера

Що стосується фактичної частини перехресного веб-переглядача, я також завітав на Video For Everybody . Я вже спробував плагін MediaelementJS Wordpress, який виявився набагато більшим, ніж вирішено. Я підозрюю, що проблеми виникли через плагін Wordpress, а не насправді бібліотеку. Я намагаюся знайти щось, що працює без JavaScript, якщо це можливо. Поки що я придумав, це звичайний 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>

Важливі примітки :

  • Закінчилося ставити ogg як перше, <source>тому що Mac OS Firefox припиняє спробувати відтворити відео, якщо він зіштовхується з MP4 як перший <source>.
  • Правильні типи MIME важливі .ogv файли повинні бути video/ogg, не video/ogv
  • Якщо у вас є HD відео, найкращим транскодером, який я знайшов для файлів OGG якості HD, є Firefogg
  • .iphone.mp4Файл для iPhone 4+ , який буде тільки відтворювати відео, які MPEG-4 з H.264 Baseline 3 відео і AAC аудіо. Найкращим транскодером, який я знайшов для цього формату, є Handbrake, використовуючи попередньо встановлений iPhone & iPod Touch, буде працювати на iPhone 4+, але для роботи iPhone 3GS потрібно використовувати попередньо встановлений iPod, який має значно нижчу роздільну здатність, яку я додав video.iphone3g.mp4.
  • В майбутньому ми зможемо використовувати mediaатрибут <source>елементів для націлювання на мобільні пристрої з медіа-запитами, але зараз старі пристрої Apple і Android не підтримують його досить добре.

Редагувати :

  • Я все ще використовую Video For Everybody, але тепер я перейшов на використання FlowPlayer, щоб керувати резервним запасом Flash, який має приголомшливий JavaScript API, який можна використовувати для управління ним.

Це, здається, є відповіддю на питання "Як я можу відтворити перехресний веб-переглядач?" а не це питання: "Як встановити список відтворення для свого відео?".
Квентін

@Quentin Для початку, адже саме так я знайшов це запитання через Google і OP сказав, що він намагається створити відеоплеєр, який працює скрізь. Я оновив відповідь і на своє динамічне запитання.
Alex W

2

У мене є подібний веб-додаток, і я взагалі не стикаюся з такою проблемою. Що я роблю, це щось подібне:

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 одного тегу-джерела. Код, написаний вище, був написаний з пам'яті, тому я, можливо, переглянув деякі деталі hte, але загальна ідея полягає в динамічній зміні атрибута src вихідного тегу, використовуючи javascript, коли це доречно.


1

Спробуйте перемістити джерело OGG до вершини. Я помітив, що Firefox іноді плутається і зупиняє гравця, коли той, на кого хоче грати, OGG, не перший.

Варто спробувати.


1

Ще один спосіб, як це можна зробити в 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

Використання JavaScript та 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.