изменение источника на видео тег HTML5


139

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

<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 () .

я делаю что-то неправильно или усложняю вещи ??


Это звучит очень хорошо для меня. Как это «усложняет» упрощение разметки?
Мэтт Болл

проблема в том, что я сталкиваюсь с большим количеством javascript и различий в делах. если, может быть, я что-то пропустил, например, был способ заставить это работать в Firefox с несколькими <source>тегами. тогда я полагаю, что было бы легче
sashn

Вы когда-нибудь разбирались в части вспышки на ie8?
Neeraj

@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 в webm path
Адам Эй,

2
Метод воспроизведения разрешен только жестом пользователя в некоторых политиках браузера.
Anson

Я очень ценю это по другой причине! Я пытался настроить страницу видео, которая не показывает ЛЮБОЕ видео, пока посетитель не выберет его. Я мог бы установить тег видео с пустым тегом источника, но он всегда вызывал бы сбой на консоли отладки JavaScript. Теперь я знаю, что могу удержать добавление «источника», пока пользователь не выберет его. До сих пор я не понимал, что мне нужно использовать CreateElement () для создания источника, а затем использовать appendChild (), чтобы добавить его к элементу video! Для последующего выбора я могу сначала проверить, существует ли исходный элемент, поэтому я не повторяю этот шаг.
Рэнди

Это решение прекрасно работает, если кто-то сталкивается с проблемой с типом контента из ответа полезной нагрузки, даже если указанный тип контента правильный, но все еще ведет себя странно.
meDeepakJain

63

Модернизр работал для меня как оберег.

То, что я сделал, это то, что я не использовал <source>. Каким-то образом это все испортило, так как видео работало только при первом вызове load (). Вместо этого я использовал атрибут источника внутри тега video -> <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
Попробовав другие методы, я попробовал этот подход Modernizr, и он работал хорошо. Chrome (по некоторым причинам) не загружал бы mp4 в моем случае, но загружал бы webm. Спасибо @MariusEngenHaugen
Адам Эй,

Рад, что могу быть полезным @AdamHey
Marius Engen Haugen

32

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

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

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 верны.

Пример (с использованием 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
Это значительно замедляет работу всего браузера, поскольку даже после удаления тега видео браузер по-прежнему загружает удаленные видео до конца.
Мое сладкое

Некоторые браузеры (мобильные) не позволяют программно воспроизводить мультимедиа без взаимодействия с пользователем, и, поскольку вы уже взаимодействовали с элементом, его замена на новый утратит эту способность.
Макс Уотерман

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 Я заметил после того, как отправил сообщение ... но причина, по которой я не заметил в первую очередь, в том, что ваш вводный текст сбивает с толку. О каком первоначальном плане мы говорим? Оригинальный оригинальный план, который не будет работать, или обновленный оригинальный план, который следует руководству, которое мы оба опубликовали?
Яур

достаточно справедливо, я должен был процитировать. Я имел в виду его план «просто использовать этот атрибут src и определить соответствующий файл с помощью функции canPlayType ()», которая действительно работает.
greg.kindel

4

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

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

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


Brilliant! Это способ сделать это. Вам даже не нужен jQuery; в связанном коде замените: mp4Vid.setAttribute ('src', "/pathTo/newVideo.mp4");
Velojet

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

Исправление, определенно сработавшее для меня, Firefox не обрабатывает свойства ни, 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 прямо на самом видео теге. Эта canPlayVideo('<mime type>')функция использовалась для определения, может ли конкретный браузер воспроизводить входное видео. Следующие работы в FireFox и Chrome.

Кстати, и FireFox, и Chrome воспроизводят формат «ogg», хотя Chrome рекомендует «webm». Сначала я поставил проверку поддержки браузером «ogg» только потому, что в других публикациях упоминалось, что FireFox сначала предпочитает источник ogg (т.е. <source src="..." type="video/ogg"/>). Но я не проверял (и сильно сомневаюсь), имеет ли значение порядок в коде при установке «src» для тега 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

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