Изменение источника на видео теге 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>

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

но теперь я также хочу какой-нибудь плейлист / меню вместе с видеоплеером, из которого я могу выбирать другие видео. они должны быть сразу открыты в моем плеере. поэтому мне придется "динамически изменять источник видео" (как видно на http://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-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().

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

23 ответа

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

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

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

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

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

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

http://dev.w3.org/html5/spec/Overview.html

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

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

Вместо того, чтобы получить тот же видео плеер для загрузки новых файлов, почему бы не стереть весь <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);

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

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

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

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

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

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

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

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

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

Другой способ сделать это в 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();
    });

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

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, когда это необходимо.

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

Самое чистое решение для изменения источника видео:

          <video id="video" autoplay loop muted>
        <source id="source" src="video/default.mp4" type="video/mp4" />
    </video>
      
    function changeVideo(name) {
        const video = document.getElementById('video');
        const source = document.getElementById('source');
    
        source.setAttribute('src', `video/${name}.mp4`);
        video.load()
    }

    changeVideo('newVideoName')

С использованием <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();
  }

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

Редактировать:

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

На самом деле изменить видео в html очень просто, достаточно метода .load(). Я протестировал его в Google и создал простую страницу изменения видео, чтобы проверить это. Пожалуйста, посмотрите на мой код, здесь я использовал API, чтобы дать мне случайный URL-адрес видео. но иногда он дает мне jpg или другой формат, поэтому мне нужно было попробовать оператор if else

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

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

если у вас уже есть загруженное видео и вы пытаетесь загрузить новое поверх этого, обязательно используйте videoRef.load() на втором, иначе оно не загрузится.

*videoRef должен быть ссылкой отображаемого тега <video></video>

Вы не должны пытаться изменить srcатрибут исходного элемента в соответствии с этим примечанием к спецификации.

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

Допустим, у вас есть:

      <audio>
    <source src='./first-src'/>
</audio>

Чтобы изменить src:

      <audio src='./second-src'/>
    <source src='./first-src'/>
</audio>

В итоге я превратил принятый ответ в функцию и улучшил резюме, чтобы сохранить время. TLDR

          /**
     * https://stackoverflow.com/a/18454389/4530300
     * This inspired a little function to replace a video source and play the video.
     * @param video
     * @param source
     * @param src
     * @param type
     */
    function swapSource(video, source, src, type) {
        let dur = video.duration;
        let t = video.currentTime;
        // var video = document.getElementById('video');
        // var source = document.createElement('source');
        video.pause();
        source.setAttribute('src', src);
        source.setAttribute('type', type);

        video.load();
        video.currentTime = t;
        // video.appendChild(source);
        video.play();
        console.log("Updated Sorce: ", {
            src: source.getAttribute('src'),
            type: source.getAttribute('type'),
        });
    }

Видео хранятся в локальном каталоге веб-сайта и доступны по полному URL-адресу, не требуют преобразования в объект blob и доступа.

HTML5-тег для видео

       <video id="videoHelp" width="560" height="340" controls autoplay 
    muted>
    <source id="videoHelpSRC" src="" type='video/mp4'>
    </video>

Изменить источник видео при нажатии на теги привязки

      <a onclick="changeSource('Video-1.mp4'); return false;" 
href="">Video-1</a>
<a onclick="changeSource('Video-2.mp4'); return false;" 
href="">Video-2</a>

Java-скрипт, который меняет источник видео при нажатии на тег привязки

Используя 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>

Самый простой способ, которым ведьма работает для меня:

HTML-код:

      <video width="100%" id="headerVideo" loop>
       <source src="videos/illustration.mp4" type="video/mp4">
</video>

JS-код:

      function loadDifferentVideo(src){
    headerVideo.getElementsByTagName('source')[0].setAttribute('src',src);
    headerVideo.load();
    headerVideo.play();
}

loadDifferentVideo('videos/illustration.mp4');
Другие вопросы по тегам