2016-08-19 96 views
3

如果我有HTML5 videoaudio元素,是否有乾淨的方式來保持它們的同步?它們應該像一個包含音頻軌道的視頻文件,因此,手動推進一個軌道應該使另一個軌道與它一起。假設這兩條曲目的持續時間相同。同步視頻和音頻(最好不使用JavaScript)

我想要一個跨瀏覽器的解決方案,但我並不特別在意它是否適用於舊版瀏覽器。如果可能的話,避免使用JavaScript也會很好。否則,一個簡單的JavaScript庫將是最好的 - 這隻會要求同步哪些音軌並處理其餘的音軌。

我查看了mediagroup ...但它看起來只能在Safari中使用。我查看了audioTracks ...但用戶必須在Firefox中啓用該功能。

我查看了Popcorn.js,這是一個看起來專爲這項任務而設計的JavaScript框架......但看起來好像在一年內還沒有任何活動。除此之外,我能找到的唯一示範是將諸如文本或幻燈片之類的內容與視頻同步,而不是音頻與視頻之間的同步。

+0

它是在所有可能的音頻事先添加到您的視頻在外部程序?這將是同步這兩者的最可靠方法。 –

+0

*「without JavaScript」*,我會說這是不可能的,但您基本上都要監聽兩個元素上的緩衝區事件,並將它們都停止。然後,在加載足夠的數據時繼續播放。重複。 –

+0

@Glen Despaux我也希望避免這種情況... – user1475412

回答

1

您可以使用Promise.all()fetch()檢索媒體資源爲BlobURL.createObjectURL()創建資源的Blob URL; canplaythrough事件和Array.prototype.every()來檢查每個資源是否可以播放;在兩個資源都可以播放時在每個資源上撥打.play()

我在問題中沒有說清楚。我的意思是這兩條曲目 應該保持同步,就像播放帶有音頻的常規視頻文件一樣。

一種方法可能是創建一個時間戳變量,利用seeked事件來更新元素的.currentTime時設定變量大於一個最小延遲,以防止.currentTime被稱爲遞歸更大。

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
</head> 
 
<body> 
 
    <button>load media</button> 
 
    <br> 
 
    <div id="loading" style="display:none;">loading media...</div> 
 
    <script> 
 
    var mediaBlobs = []; 
 
    var mediaTypes = []; 
 
    var mediaLoaded = []; 
 
    var button = document.querySelector("button"); 
 
    var loading = document.getElementById("loading"); 
 
    var curr = void 0; 
 
    var loadMedia =() => { 
 
     loading.style.display = "block"; 
 
     button.setAttribute("disabled", "disabled"); 
 
     return Promise.all([ 
 
     // `RETURN` by smiling cynic are licensed under a Creative Commons Attribution 3.0 Unported License 
 
     fetch("https://ia600305.us.archive.org/30/items/return_201605/return.mp3") 
 
     , fetch("http://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4") 
 
     ]) 
 
     .then(responses => responses.map(media => ({ 
 
      [media.headers.get("Content-Type").split("/")[0]]: media.blob() 
 
     }))) 
 
     .then(data => { 
 
      for (var currentMedia = 0; currentMedia < data.length; currentMedia++) { 
 
      (function(i) { 
 
       var type = Object.keys(data[i])[0]; 
 
       mediaTypes.push(type); 
 
       console.log(data[i]); 
 
       var mediaElement = document.createElement(type); 
 
       mediaElement.id = type; 
 
       var label = document.createElement("label"); 
 
       mediaElement.setAttribute("controls", "controls"); 
 
       mediaElement.oncanplaythrough =() => { 
 
       mediaLoaded.push(true); 
 
       if (mediaLoaded.length === data.length 
 
        && mediaLoaded.every(Boolean)) { 
 
        loading.style.display = "none"; 
 
        for (var track = 0; track < mediaTypes.length; track++) { 
 
         document.getElementById(mediaTypes[track]).play(); 
 
         console.log(document.getElementById(mediaTypes[track])); 
 
        } 
 
       } 
 
       } 
 
       var seek = (e) => { 
 
       if (!curr || new Date().getTime() - curr > 20) { 
 
        document.getElementById(
 
        mediaTypes.filter(id => id !== e.target.id)[0] 
 
       ).currentTime = e.target.currentTime; 
 
        curr = new Date().getTime(); 
 
       } 
 
       } 
 
       mediaElement.onseeked = seek; 
 
       mediaElement.onended =() => { 
 
       for (var track = 0; track < mediaTypes.length; track++) { 
 
        document.getElementById(mediaTypes[track]).pause() 
 
       } 
 
       } 
 
       mediaElement.ontimeupdate = (e) => { 
 
       e.target.previousElementSibling 
 
       .innerHTML = `${mediaTypes[i]} currentTime: ${Math.round(e.target.currentTime)}<br>`; 
 
       } 
 
       data[i][type].then(blob => { 
 
       mediaBlobs.push(URL.createObjectURL(blob)); 
 
       mediaElement.src = mediaBlobs[mediaBlobs.length - 1]; 
 
       document.body.appendChild(mediaElement); 
 
       document.body.insertBefore(label, mediaElement); 
 
       }) 
 
      }(currentMedia)); 
 
      } 
 
     }) 
 
    }; 
 
    button.addEventListener("click", loadMedia); 
 
    </script> 
 
</body> 
 
</html>

plnkr http://plnkr.co/edit/r51oh7KsZv8DEYhpRJlL?p=preview

+0

我認爲這裏缺失的部分是*保持*兩個軌道同步。他們不應該失去同步,手動推進一個軌道應該帶來另一個軌道。 – user1475412

+0

@ user1475412 _「並手動推進一個軌道應該使另一個跟着它一起。」_此實際需求的描述不出現在實際問題中? – guest271314

+0

對不起,我沒有在問題中說清楚。我的意思是這兩個音軌應該保持同步,就好像播放帶有音頻的常規視頻文件一樣。我會修改這個問題。 – user1475412

0

據我所知,純HTML是不可能的。

您可以使用<video><audio>元素的currentTime屬性來同步時間。

var video = document.getElementById("your-video"); 
var audio = document.getElementByid("your-audio"); 
audio.currentTime = video.currentTime; 

如果需要,您還可以使用timeupdate事件不斷重新同步視頻和音頻。

+0

我認爲這種方法不能很好地工作...查看http://html5demos.com/two-videos – user1475412

+0

看看該演示的來源,看起來時間只能同步一次。如果'timeupdate'事件被用來連續地重新同步它們,它可能會更好。 – Shadowfacts