6
6

More than 1 year has passed since last update.

Three.jsで動画テクスチャの切り替える際に必要だったこと

Last updated at Posted at 2023-02-07

概要

Three.jsでHTMLVideoElementをThree.js空間の特定のオブジェクトのテクスチャとして扱う際に複数の動画を任意のタイミングで切り替える際に切り替え時に稀に動画再生がされない問題に悩まされたので、対策として有効だったことを備忘録として記します。(検証端末:モバイルブラウザ(Android Chrome1049, iOS Safari))

Three.js空間上で不必要になったインスタンスの解放処理

Three.jsで作成したインスタンスは自動的には解放されないので、明示的に解放処理を入れてください。
私の場合は、動画の切り替えの際に前回の動画を貼り付けているテクスチャに対してThree.jsのtexture.dispose()することで対処しました。これをしない場合、iOS SafariでWebGL context lostエラーに苦しめられました。

HTMLVideoElementのpreload属性を設定

結論からいうと以下のようにHTMLVideoElementのpreload属性をmetadataに設定してください。

const videoElement: HTMLVideoElement = document.createElement('video')
videoElement.preload = 'metadata'

HTMLVideoElementのpreload属性にはnone|metadata|autoの3つがあります。このpreload属性は、HTMLが読み込まれた場合に動画がデータをどこまで読み込むかの設定になります。preload属性を何も設定しない場合は、autoが設定され可能な限り複数の動画のプリロード時にHTMLVideoElement.play()が実行できるように読み込みがされるようです。metadataに設定された場合は、動画のサイズ、トラックリスト、再生時間をプリロードするようです。また、noneに設定された場合は、プリロードがされず動画再生のタイミングで全ての動画データを読み込むようです。
今回のように複数動画がある場合にautoを設定すると以下のようにエラーが発生します。

video MEDIA_ERR_DECODE occurs randomly

HTML5の仕様書によるとこのエラーはメディアリソースが使用可能であることが確認された後、メディアリソースをデコードする際に何らかのエラーが発生した。場合に発生するようです。(エラー詳細)

HTMLVideoElementのリソースの解放処理

ブラウザ上で動画を複数扱う場合は、以下のように前回の動画リソースを削除することが推奨されています。具体的には、以下のようにしてください。

const videoElement: HTMLVideoElement = document.createElement('video')
videoElement.src = 'prevVideoSource'
...// 何らかの処理
// 前回の動画が必要無くなったタイミングでリソースの解放処理をする
videoElement.src = '' 
// 今回使う動画リソースの登録
videoElement.src = 'currentVideoSource'

おわりに

最近は、重いコンテンツのWebアプリを作る機会が増えてきたこともあり、今回のようにブラウザでも解放処理が必要だったりと面白いですね。

6
6
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
6
6