Media Source Extensions


Media Source Extensions (MSE)とは、HTTPベースのメディアストリーミングにおけるソースハンドリングAPIのこと(ブラウザ用)。

  • 実装的な意味合い
    • ブラウザ用のHLSやDASH実装は、最終的にこのMSE経由でメディアチャンクをブラウザに渡す
    • 逆に、MSEでは受け取ったメディアチャンクを再生処理するだけであり、アダプティブストリーミング等の高度な処理はdash.js等で実装する
  • ドキュメント

実装サンプル

mse-sample.html

実装するチャンクダウンロード処理の概要

  • バッファに10秒分のチャンクが溜まるようにダウンロード
    • 最初の10秒分は連続ダウンロード
      • ダウンロード終了時に新しいダウンロードを開始させる
    • それ以降は、再生位置が変わるたびにダウンロード
      • ブラウザが250ms毎に発行するtimeUpdateイベント毎にダウンロードすべきか判断

処理概要

  • 初期処理
window.onload = function() {
    if (!window.MediaSource) {
        console.error('No Media Source API available');
        return;
    }
    if (typeof video.getVideoPlaybackQuality == 'function') {
        quality = video.getVideoPlaybackQuality();
    }

    video.ontimeupdate = function() {timeUpdated();} ;

    mediaSource = new MediaSource();
    video.src = window.URL.createObjectURL(mediaSource);
    mediaSource.addEventListener('sourceopen', mediaSourceOpened);
}
  • MediaSourceアタッチ完了後の処理
function mediaSourceOpened() {
    sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc3.4D401E"');
    sourceBuffer.addEventListener('updateend', getNext);
    GET(initUrl, gotFile);
    video.play();
}
  • 視聴位置変更時の処理
function timeUpdated() {
    getNext();
    var str ="Current Position "+video.currentTime;
    if (videoPlaybackQuality) {
        str = str + ", "+videoPlaybackQuality.creationTime+","+videoPlaybackQuality.totalVideoFrames+","+videoPlaybackQuality.droppedVideoFrames+","+videoPlaybackQuality.corruptedVideoFrames+","+videoPlaybackQuality.totalFrameDelay;
    }
    console.log(str);
}
  • チャンクファイルのダウンロード完了時
function gotFile(videoChunk) {
    getting = 0;
    if (videoChunk) {
        sourceBuffer.appendBuffer(new Uint8Array(videoChunk));
    }
}
  • チャンクファイルのダウンロード処理(
function getNext() {
    if (!getting && !fullload && ((bufferedLength - video.currentTime)<10)) { 
        var url = templateUrl.replace('$Number$', index); 
        getting = 1; 
        console.log("downloading:"+index); 
        GET(url,gotFile); 
        index++; 
        if (index > numberOfChunks) {
            sourceBuffer.removeEventListener('updateend', getNext);
            fullload = 1;
        }
        var length = sourceBuffer.buffered.length;
        bufferedLength += length;
    }
}
  • ファイル取得関数
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('error');
            return false;
        } else {
        }
        callback(xhr.response);
    };
    xhr.send();
}

API

  • MediaSource
    • 概要
      • メディアストリームの実体
      • srcフィールドに設定するメディアファイルに相当
      • 各種ステイタスのコンテナ
    • 属性
      • sourceBuffers
      • activeSourceBuffers
      • readyState
      • duration
    • イベントハンドラ
      • onsourceclose
      • onsourceended
      • onsourceopen
    • メソッド
      • addSourceBuffer
      • removeSourceBuffer
      • endOfStream
      • setLiveSeekableRange
      • clearLiveSeekableRange
  • SourceBuffer
    • 概要
      • ひとつのメディアチャンクを表現
    • 属性
      • mode
      • updating
      • buffered
      • timestampOffset
      • audioTracks
      • videoTracks
      • textTracks
      • appendWindowStart
      • appendWindowEnd
      • trackDefaults
    • イベントハンドラ
      • onabort
      • onerror
      • onupdate
      • onupdateend
      • onupdatestart
    • メソッド
      • appendBuffer
      • appendStream
      • abort
      • remove
  • SourceBufferList
    • 属性
      • length
    • イベントハンドラ
      • onaddsourcebuffer
      • onremovesourcebuffer
    • メソッド
      • SourceBuffer
  • VideoPlaybackQuality
  • TrackDefault
    • 属性
      • type
      • byteStreamTrackID
      • language
      • label
      • kinds
  • TrackDefautList
    • 属性
      • length
    • メソッド
      • TrackDefault