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