Изменение источника на теге html5

Я пытаюсь создать видеоплеер, который работает повсюду. до сих пор я собираюсь:

<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. давайте забудем о flashplayer (и, таким образом, 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().

Я делаю это неправильно или как-то усложнять вещи

Ответ 1

Я ненавидел все эти ответы, потому что они были слишком короткими или полагались на другие рамки.

Вот "один" ванильный способ 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);

Ответ 2

Modernizr работал как прелесть для меня.

Что я сделал, так это то, что я не использовал <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().

Ответ 3

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

Динамическое изменение исходного элемента и его атрибута, когда элемент уже вставлен в видео или аудио элемент, не будет иметь никакого эффекта. Чтобы изменить то, что воспроизводится, просто используйте атрибут src для элемента мультимедиа напрямую, возможно, используя метод canPlayType(), чтобы выбрать из доступных ресурсов. Как правило, манипулирование исходными элементами вручную после анализа документа представляет собой необоснованный [sic] сложный подход.

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

Ответ 4

Я решил это с помощью этого простого метода

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

Ответ 5

Вместо того, чтобы один и тот же видеоплеер загружал новые файлы, почему бы не стереть весь элемент <video> и не заново создать его. Большинство браузеров автоматически загружают его, если src верны.

Пример (используя 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

Согласно спецификация

Динамическое изменение исходного элемента и его атрибута, когда элемент уже вставлен в видео или аудио элемент не будет эффект. Чтобы изменить то, что играет, просто используйте атрибут src на элемент мультимедиа напрямую, возможно, используя canPlayType() метод для выбора из доступных ресурсов. В общем, манипулирование исходными элементами вручную после того, как документ был синтаксический анализ является чрезмерно сложным подходом.

То, что вы пытаетесь сделать, видимо, не должно работать.

Ответ 7

Просто поместите 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>

Ответ 8

Yaur: Хотя то, что вы скопировали и вставили, является хорошим советом, это не означает, что невозможно изменить элемент-источник элемента видео HTML5 элегантно, даже в IE9 (или IE8, если на то пошло). (Это решение НЕ включает замену всего видеоэлемента, так как это неправильная практика кодирования).

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

Если это поможет, или если у вас возникли проблемы, сообщите мне.

Ответ 9

Я пришел с этим, чтобы динамически менять источник видео. Событие "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();
};

Ответ 10

Это мое решение:

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

Ответ 11

У меня есть похожее веб-приложение, и я вообще не сталкиваюсь с подобной проблемой. Что я делаю, это что-то вроде этого:

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 одного тега источника. Приведенный выше код был написан из памяти, поэтому я мог бы замять некоторые подробности, но общая идея состоит в том, чтобы динамически изменять атрибут src исходного тега с использованием javascript, когда это необходимо.

Ответ 12

Использование тегов <source /> оказалось трудным для меня в Chrome 14.0.835.202, хотя это прекрасно работало для меня в FireFox. (Это может быть моя нехватка знаний, но я думал, что альтернативное решение может быть полезно в любом случае.) Итак, я закончил использование тега <video /> и установил атрибут src прямо на сам тег видео. Функция canPlayVideo('<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 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();
  }

Ответ 13

Я изучал это довольно долго, и я пытаюсь сделать то же самое, поэтому, надеюсь, это поможет кому-то другому. Я использую crossbrowsertesting.com и буквально тестирую это почти в каждом браузере, известном человеку. Решение, которое я получил в настоящее время, работает в Opera, Chrome, Firefox 3.5+, IE8 +, iPhone 3GS, iPhone 4, iPhone 4, iPhone 5, iPhone 5, iPad 1+, Android 2.3+, Windows Phone 8.

Динамическое изменение источников

Динамическое изменение видео очень сложно, и если вы хотите получить резервную копию Flash, вам придется удалить видео с DOM/страницы и повторно добавить его, чтобы Flash обновлялся, поскольку Flash не распознает динамические обновления для Flash vars, Если вы собираетесь использовать JavaScript для его динамического изменения, я бы полностью удалил все элементы <source> и просто использовал canPlayType, чтобы установить src в JavaScript и 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 Video и аудио AAC. Лучший транскодер, который я нашел для этого формата, - Handbrake, использование iPhone и iPod Touch будет работать на iPhone 4+, но для того, чтобы заставить iPhone 3GS работать, вам нужно использовать предустановку iPod, которая имеет гораздо более низкое разрешение, которое я добавил как video.iphone3g.mp4.
  • В будущем мы сможем использовать атрибут media для элементов <source> для таргетинга мобильных устройств на медиа-запросы, но сейчас старые устройства Apple и Android не поддерживают его достаточно хорошо.

Edit

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

Ответ 14

Попробуйте переместить источник OGG в начало. Я заметил, что Firefox иногда путается и останавливает игрока, когда тот, который он хочет играть, OGG, не первый.

Стоит попробовать.

Ответ 15

Использование 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>