LoginSignup
3
1

More than 3 years have passed since last update.

VideoTrackReaderが削除されるようなのでMediaStreamTrackProcessorを使う

Posted at

概要

WebCodecsにて登場したAPIであるVideoTrackReaderはVideoTrackからVideoFrameを取得することができるようになるクラスです。
ですが、MediaStreamTrackProcessorという別のAPIが良いという内容のChromiumのissueGitHubのissueが存在し、M91でVideoTrackReaderは削除されるようです。そのため、新しいAPIを使って書き換えてみます。

具体的にやること

現在のVideoEncoderがチャンクを生成するまでの流れは以下のとおり

  1. navigator.mediaDevices.getUserMedia()でカメラからMediaStreamを取得
  2. getVideoTracks()でMediaStream内のVideoTrackを取得
  3. new VideoTrackReader()でVideoTrackからVideoFrameを取る準備をする
  4. VideoTrackReaderのコールバック関数内でVideoEncoderへVideoFrameを渡す

今回はこの3,4の手順をMediaStreamTrackProcessorを使うように変更します。
従来のVideoTrackReaderを使ったコードを簡略化すると以下のようになります。

VideoTrackReader.js
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を使うように変更すると以下のようになります。

  1. navigator.mediaDevices.getUserMedia()でカメラからMediaStreamを取得
  2. getVideoTracks()でMediaStream内のVideoTrackを取得
  3. new MediaStreamTrackProcessor()でVideoTrackの処理をする準備をする
  4. MediaStreamTrackProcessorからreaderを取得する
  5. readerの処理をするwhile文のループ内でVideoEncoderへVideoFrameを渡す
MediaStreamTrackProcessor.js
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をつける必要があります。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1