概要
WebCodecsにて登場したAPIであるVideoTrackReader
はVideoTrackからVideoFrameを取得することができるようになるクラスです。
ですが、MediaStreamTrackProcessor
という別のAPIが良いという内容のChromiumのissueやGitHubのissueが存在し、M91でVideoTrackReader
は削除されるようです。そのため、新しいAPIを使って書き換えてみます。
具体的にやること
現在のVideoEncoderがチャンクを生成するまでの流れは以下のとおり
-
navigator.mediaDevices.getUserMedia()
でカメラからMediaStreamを取得 -
getVideoTracks()
でMediaStream内のVideoTrackを取得 -
new VideoTrackReader()
でVideoTrackからVideoFrameを取る準備をする - VideoTrackReaderのコールバック関数内でVideoEncoderへVideoFrameを渡す
今回はこの3,4の手順をMediaStreamTrackProcessorを使うように変更します。
従来のVideoTrackReaderを使ったコードを簡略化すると以下のようになります。
const stream = await navigator.mediaDevices.getUserMedia();
const [videoTrack] = stream.getVideoTracks();
const videoEncoder = new VideoEncoder();
await videoEncoder.configure();
const videoReader = new VideoTrackReader(videoTrack);
videoReader.start((videoFrame) => {
videoEncoder.encode(videoFrame, {keyFrame: false});
});
MediaStreamTrackProcessorを使うように変更すると以下のようになります。
-
navigator.mediaDevices.getUserMedia()
でカメラからMediaStreamを取得 -
getVideoTracks()
でMediaStream内のVideoTrackを取得 -
new MediaStreamTrackProcessor()
でVideoTrackの処理をする準備をする - MediaStreamTrackProcessorからreaderを取得する
- readerの処理をするwhile文のループ内でVideoEncoderへVideoFrameを渡す
const stream = await navigator.mediaDevices.getUserMedia();
const [videoTrack] = stream.getVideoTracks();
const videoEncoder = new VideoEncoder();
await videoEncoder.configure();
const processor = new MediaStreamTrackProcessor(videoTrack);
const frameReader = processor.readable.getReader();
const reader = async () => {
while (true) {
const { done, value: videoFrame } = await frameReader.read();
if (done) return;
videoEncoder.encode(videoFrame, {keyFrame: false});
}
};
reader();
VideoTrackReaderではコールバック関数に処理を書いていましたが、MediaStreamTrackProcessorではStream APIになっており、WebTransportなどと同じようなAPIで利用できるようになっています。
違いとして引数でVideoFrameを取得していたのがread()
で取得するようになっています。
注意点としてはコールバックではなくasyncな関数内で処理をしている点です。
もし以下のようにVideoTrackReaderの処理と同じ場所に書くと無限ループになりその後ろに処理を書いていても動かなくなります。
const frameReader = processor.readable.getReader();
while (true) {
const { done, value: videoFrame } = await frameReader.read();
if (done) return;
videoEncoder.encode(videoFrame, {keyFrame: false});
}
// ここ以降はreadしている限り実行されない
起動時の注意点
WebCodecsのAPIを有効にするにはChromeの起動時のフラグに--enable-blink-features=WebCodecs
が必要でしたが、MediaStreamTrackProcessorを利用するには代わりに--enable-blink-features=WebCodecs,MediaStreamInsertableStreams
をつける必要があります。