Media Source Extensions (MSE)とは、HTTPベースのメディアストリーミングにおけるソースハンドリングAPIのこと(ブラウザ用)。
- 実装的な意味合い
- ブラウザ用のHLSやDASH実装は、最終的にこのMSE経由でメディアチャンクをブラウザに渡す
- 逆に、MSEでは受け取ったメディアチャンクを再生処理するだけであり、アダプティブストリーミング等の高度な処理はdash.js等で実装する
- ドキュメント
実装サンプル
実装するチャンクダウンロード処理の概要
- バッファに10秒分のチャンクが溜まるようにダウンロード
- 最初の10秒分は連続ダウンロード
- ダウンロード終了時に新しいダウンロードを開始させる
- それ以降は、再生位置が変わるたびにダウンロード
- ブラウザが250ms毎に発行するtimeUpdateイベント毎にダウンロードすべきか判断
- 最初の10秒分は連続ダウンロード
処理概要
- 初期処理
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
- 概要
- 属性
- creationTime
- totalVideoFrames
- droppedVideoFrames
- corruptedVideoFrames
- totalFrameDelay
- TrackDefault
- 属性
- type
- byteStreamTrackID
- language
- label
- kinds
- 属性
- TrackDefautList
- 属性
- length
- メソッド
- TrackDefault
- 属性