beek
beek

Reputation: 3750

MSE WebM video with no audio

I've written a MSE video player and it's loading WebMs. These are loading well, however I have a problem with video files with no audio tracks.

I've tried changing the codec depending on if there is audio

mediaSource.addSourceBuffer(`video/webm; ${videoHasAudio(asset) ? 'codecs="vp9,vorbis"' : 'codecs="vp9"'}`)`

And I thought this was working but now isn't. How do I run silent WebMs in MSE?

Upvotes: 1

Views: 305

Answers (1)

thowfeeq
thowfeeq

Reputation: 363

I have added sample MSE project here: https://github.com/thowfeeq178/MediaSourceExtention

checkout the example in the github

overview:

we need to add one for video and one for audio like below:

// BBB : https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd

var baseUrl = "https://dash.akamaized.net/akamai/bbb_30fps/";
var initUrl = baseUrl + "bbb_30fps_480x270_600k/bbb_30fps_480x270_600k_0.m4v";

var initAudioUrl = baseUrl + "bbb_a64k/bbb_a64k_0.m4a";

var templateUrl =
  baseUrl + "bbb_30fps_480x270_600k/bbb_30fps_480x270_600k_$Number$.m4v";
var templateUrlForAudio = baseUrl + "bbb_a64k/bbb_a64k_$Number$.m4a";
var sourceBuffer;
var audioSourceBuffer;
var index = 0;
var audioIndex = 0;
var numberOfChunks = 159;
var video = document.querySelector("video");
var ms = new MediaSource();

function onPageLoad() {
  console.log("page loaded ..");
  if (!window.MediaSource) {
    console.error("No Media Source API available");
    return;
  }
  // making source controlled by JS using MS
  video.src = window.URL.createObjectURL(ms);
  ms.addEventListener("sourceopen", onMediaSourceOpen);
}

function onMediaSourceOpen() {
  // create source buffer
  sourceBuffer = ms.addSourceBuffer('video/mp4; codecs="avc1.4d401f"');
  audioSourceBuffer = ms.addSourceBuffer('audio/mp4; codecs="mp4a.40.5"');
  // when ever one segment is loaded go for next
  sourceBuffer.addEventListener("updateend", nextSegment);
  audioSourceBuffer.addEventListener("updateend", nextAudioSegment);
  // fire init segemnts
  GET(initUrl, appendToBuffer);
  GET(initAudioUrl, appendToAudioBuffer);

  // play
  video.play();
}

// get next segment based on index and append, once everything loaded unlisten to the event
function nextSegment() {
  var url = templateUrl.replace("$Number$", index);
  GET(url, appendToBuffer);
  index++;
  if (index > numberOfChunks) {
    sourceBuffer.removeEventListener("updateend", nextSegment);
  }
}

// get next audio segment based on index and append, once everything loaded unlisten to the event
function nextAudioSegment() {
  var audioUrl = templateUrlForAudio.replace("$Number$", audioIndex);
  GET(audioUrl, appendToAudioBuffer);
  audioIndex++;
  if (index > numberOfChunks) {
    audioSourceBuffer.removeEventListener("updateend", nextAudioSegment);
  }
}

// add to existing source
function appendToBuffer(videoChunk) {
  if (videoChunk) {
    sourceBuffer.appendBuffer(new Uint8Array(videoChunk));
  }
}

function appendToAudioBuffer(audioChunk) {
  if (audioChunk) {
    audioSourceBuffer.appendBuffer(new Uint8Array(audioChunk));
  }
}

// just network thing
function GET(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", url);
  xhr.responseType = "arraybuffer";

  xhr.onload = function(e) {
    if (xhr.status != 200) {
      console.warn("Unexpected status code " + xhr.status + " for " + url);
      return false;
    }
    callback(xhr.response);
  };

  xhr.send();
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>MSE Demo</title>
</head>

<body onload="onPageLoad()">
  <h1>MSE Demo</h1>
  <div>
    <video muted controls width="80%"></video>
  </div>

</body>

</html>

Upvotes: 0

Related Questions