PlayCanvasで作った「遊べるMV」を高速化した話

# 前回までのおはなし
こんにちは。ゲーカーナトゥミです。
プログラミングする音楽家として活動しています。
自分の音楽作品プロモーションの一環として、PlayCanvasで「遊べるMV」というWEB3Dコンテンツを作りました。
その時の話は下記に書いてあります。

https://qiita.com/kg_nuts_kg/items/7d16999706d3ea3b5bbc

で、動物をテーマにしたアルバム全曲分の遊べるMVワールドを公開したはいいのですが、とにかく重い。無限にロード時間かかる。
スマホではブラウザ落ちまくるし見れたもんじゃない。PCでもちゃんと見れるか怪しい…というレベルで公開してしまいました。

WEBコンテンツは動作スピード命。
このままだとせっかく作ったのに誰にも見てもらえないや…ということで、徹底的に軽量化を行うことにしました。

## やったこと
やったことはざっくり下記です。
- 3Dモデルで使用するテクスチャ画像の軽量化
- 使用している動画の軽量化
- 3Dモデルの最適化
- UIのHTML化
- CDNの導入

結果、ビルドしたPlayCanvasファイルは104MB(狂気！！！)から38MBへ削減。
スマホでも落ちずにサクサク見られるようになりました。

では一個づつ見ていきましょう。

## 3Dモデルで使用するテクスチャ画像の軽量化
いかんせん3Dは初めてで、右も左もわからん状態でした。
それゆえ、ロイヤリティフリー3D素材を落としてきた状態のまま突っ込んで作っていました。
落としてきた3Dモデルをアップロードすると、なんか画像もついてくるなあ…これがテクスチャかあ…くらいの認識でした。
![スクリーンショット 2023-12-18 17.30.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522080/48a69f2e-d884-38c9-1602-aca6dfe9fe4b.png)

今回、全てのテクスチャ画像について「これは本当にこんなサイズが必要か？？？」と自問自答し、全て1024x 1024px または512 x 512pxにリサイズしました。
中にはちっっっこいサイズでしか使わないのに4000px越えのテクスチャなどもあり阿鼻叫喚。
その上でさらに最適化をかけ、軽量化して再アップロードしました。

画像の最適化にはいつもこのサイトを使っています。

https://imagecompressor.com/ja/

その上でさらに、PlayCanvasエディタ上で「BASIS圧縮」というものをかけています。
![スクリーンショット 2023-12-18 17.31.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522080/92bea311-ea30-33fa-2bb4-a6a07f31be92.png)


BASIS圧縮について詳しくはこちら:

https://developer.playcanvas.com/ja/user-manual/assets/textures/texture-compression/

## 使用している動画の軽量化
こんな感じで、曲を再生すると背景のモニターに動画が映る演出になっています。
![thumnail_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522080/3ba67ef5-779f-2498-8a67-cf0d5691f022.png)

この動画が！また重いんですよ！！！
HLSストリーミング形式なので、mp4直貼りよりはマシかもしれないですが、とにかく重い。
なぜか？？？？
フルHD動画を貼っているからです。

冷静に考えてみましょう。スマホやPCモニターでこのワールドを再生するとします。
このワールド内のモニターをフルHDサイズまで拡大して見ることってそうそうなくないですか？

ということで、画質を落とすことにしました。
SDサイズの854×480pxまで落としたmp4に書き出し直しました。

その上でさらに、mp4を圧縮してくれるというサイトで圧縮かけました。

https://www.mp4compress.com/ja/

このサイト、どういう原理で圧縮してくれてるのかは検証していなくて謎なんですが、確かに軽くはなりました。

ほんでmp4を.tsとm3u8のHLS形式に変換。
fffmpegでやるのが一般的だと思いますが、セットアップをめんどくさがっていつも下記サイトでやっています。

https://www.mp4.to

※上記圧縮系オンラインサービス、個人制作だから俄然気軽に使いますが、企業案件で使う場合はちゃんとセキュリティ周りを確認しましょう。

## 3Dモデルの最適化
画像と動画が軽くなったら次は3Dモデルです。
わりと最近追加されたらしい、「Draco圧縮」という機能を使いました。

>Dracoは、GitHub - dracoで公開されており、メッシュや点群（ポイントクラウド）データ、その他の要素（接続情報、色情報、ジオメトリ関連の属性等）の圧縮を行うことができます。3Dグラフィックを効率的に圧縮および展開するためのライブラリです。

>以前まで、PlayCanvasでは、Draco圧縮を利用すると一律の圧縮レベルが適用されてしまい、モデルによっては利用できませんでしたが、2023年 5月のPlayCanvas Editor v1.30.0のアップデートで「Draco Decode Speed（デコード速度）」と「Draco Mesh Size（メッシュの圧縮率）」の2つの新たなオプションが追加され、これにより圧縮レベルを調整することが可能になりました。

https://support.playcanvas.jp/hc/ja/articles/18802026304537-PlayCanvasエディターのDraco圧縮-メッシュデータの圧縮-について

https://support.playcanvas.jp/hc/ja/articles/16325860201497


ごりごりに圧縮をかけすぎると3Dデータが破綻するらしいです。
今回は全ての3DモデルにDraco Mesh Sizeオプション0.5でかけていきましたが、特に破綻は見られませんでした。
こちらで大幅に3Dモデルの軽量化をすることができました。Draco神。ありがとう。

## UIのHTML化
初期リリース時、音楽再生中のシークバーまわりはPlayCanvasの2DScreen機能で作っていました。
曲名の表示にテキストが必要なので、フォントファイルを読み込ませています。
あれ？？？？？？日本語フォントって、めちゃくちゃ重いのでは？？？？？？
このたった数文字のために、日本語フォントを、丸ごと読み込ませる必要ある…？？？

テキストを画像化するという手もありましたが、レスポンシブなものをサクッと作るならHTMLで作る方が早いというメリットもあったので、これを機にUI周りはHTMLElementに変更しました。
2DScreenにもレスポンシブ対応させる手はありますが、こんな感じでレイアウト変更も伴うデザインにしたかったのでHTML/CSSのが早いという判断です。
![iPhone 14 Pro Max – 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522080/1eb2f99d-5b8e-399e-31d3-761a65c0a37e.png)
![seekbar – 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522080/9fee9221-b1cc-959f-f0c0-63b3c6b2b8ba.png)


## CDNの導入
素材を軽くしたら、最後のダメ押しにサーバー環境の改善です。
今回のプロジェクトは、自分で借りてるレンタルサーバーの一画に素材とHTML一式を置いています。
重くなりそうな動画素材系だけでもロード早くしたいなーと思い、シーディーエヌというものを導入することにしました。

CDNとは？↓

https://www.ntt.com/bizon/glossary/e-c/cdn.html

>CDN（Contents Delivery Network）とは、数多くのキャッシュサーバーなどで構成されたプラットフォームを用いることにより、Webサイト上のコンテンツを迅速にエンドユーザーに届けるための仕組みです。通常のWebサイトでは、コンテンツを配信するためのWebサーバーの処理能力やインターネットに接続されているネットワークの帯域幅などが制約条件となり、大量のユーザーがWebサイトにアクセスするとレスポンスが低下してしまいます。また、物理的に離れた場所からのアクセスに対しては、ネットワークの遅延によってレスポンスが低下する場合があります。こうした課題を解決するのがCDNです。

>各地に配置した多くのキャッシュサーバーにWebサイトのコンテンツを一次的に保存（キャッシュ）し、リクエストしたユーザーから近い場所にあるキャッシュサーバーからコンテンツを配信することで、Webサーバーやネットワークの状態、あるいはユーザーがアクセスする場所との物理的な距離にかかわらず、安定したコンテンツ配信を実現します。

とのことです。

CDNサービスは色々ありますが、今回は下記の理由からAWS CloudFront + S3のお世話になることにしました。
- 無料枠がある
- 従量課金制
- 仕事でちょっとだけS3の管理画面を触ったことがある

現状は大量のアクセスを捌く想定もないし、自己満足程度にCDNに触れてみたい！という理由だったので、無料枠で十分です。

この記事と、ChatGPTくんに教えてもらいながら設定しました。

https://qiita.com/moshi1121/items/97beff9f2c300d868e69

最終的には、動画ファイル + 吐き出されたPlayCanvasファイルのindex.html以外のファイル全部CDN化しました。

吐き出されたファイルのindex.html以外全部まるっとS3にアップして、index.htmlに書いてあるscriptの参照類を全部CloudFrontのURLに書き換えました。
そうするとアセット類もだいたいCloudFront上のものを参照してくれているっぽいです。
ですが、中にはパス書き換えられないものもあるくさかったので、保険として自サーバーのindex.html同階層にもscript類とファイル類を置いてあります。
(この辺はちゃんと検証していません。雑でごめん！！！)

# おわり
お仕事でWEBサイトのパフォーマンス最適化をやった経験がありましたが、結局やることは一緒でした。
結果、スマホでもさくさく動くようになってひとり満足感を噛み締めています。

よかったら体験してみてください。

https://geeker-natsumi.com/zoo

音楽再生中のシークバーをレスポンシブ対応したはいいものの、その辺バグっているのでここは年末年始に直す予定です！！！

WEBサイトのパフォーマンスをよくするって、やってみれば「いやそんなん当たり前じゃん」みたいなことばかりなのですが、右も左もわからずに苦闘して作っている間はそれどころじゃなかったりするものですよね。
今回の知見が皆様の役に立つことを願いつつの投稿でした。