「MetaLifeのようなバーチャルオフィスを、自社向けに作れないだろうか」
今回の開発は、そんな一言から始まりました。
最初から詳細な仕様書があったわけではありません。まずは動くものを作り、実際にブラウザで開きながら、
「ここをもっと使いやすくしたい」
「スマートフォンでは表示がおかしい」
「この機能も追加できないか」
と、少しずつ改善を重ねていきました。
結果として、アバターでオフィス内を移動し、近くにいる人や同じブースにいる人と音声通話ができる、独自のバーチャルオフィスが形になりました。
この記事では、最初の試作から現在の形になるまでの制作過程を紹介します。
目指したのは、気軽に声をかけられるオンラインオフィス
一般的なWeb会議ツールでは、会話を始めるために会議URLを発行したり、相手へ連絡を送ったりする必要があります。
一方、実際のオフィスでは、近くにいる人へ気軽に声をかけられます。
今回目指したのは、その感覚をブラウザ上で再現することでした。
主なイメージは次のようなものです。
- アバターでオフィス内を自由に移動できる
- 近くにいる人と自然に会話できる
- 同じ会議ブースに入った人同士で通話できる
- 在席中、集中中、離席中などの状態が分かる
- スマートフォンからも利用できる
- 専用アプリをインストールしなくても使える
単なるWeb会議システムではなく、「オンライン上に人がいることを感じられる場所」を作ることが目的でした。
最初はアバター移動だけのMVPからスタート

最初に作ったのは、必要最低限の機能だけを備えたMVPでした。
MVPとは、サービスの中心となる機能だけを実装した最小限の試作品です。
初期版では、次の機能を実装しました。
- 2Dマップの表示
- アバターの移動
- 複数ユーザーの位置同期
- オンラインユーザー一覧
- テキストチャット
- マイクとカメラのON・OFF
- 近くにいるユーザーとの音声・映像通話
パソコンの矢印キーやWASDキー、マウスクリックによってアバターを移動できる仕組みです。
同じオフィスIDで入室しているユーザー同士では、アバターの位置がリアルタイムで共有されます。
この段階で、バーチャルオフィスの基本的な仕組みは確認できました。

最初につまずいたのは、CSSのパス設定
実際にサーバーへアップロードしてみると、画面がまったくデザインされていない状態で表示されました。
原因はCSSやJavaScriptのパス指定です。
開発時には、次のような絶対パスを使っていました。
<link rel="stylesheet" href="/styles.css">
しかし、実際の設置場所はドメイン直下ではなく、サブディレクトリでした。
https://example.com/virtualoffice/
この場合、絶対パスでは意図したCSSファイルを読み込めません。
そこで、すべてのファイルを相対パスへ変更しました。
<link rel="stylesheet" href="./assets/css/app.css">
これにより、どの階層へ設置しても動作する構成になりました。
https://example.com/virtualoffice/
https://example.com/demo/virtualoffice/
https://example.com/service/test/virtualoffice/
実際にサーバーへ設置してみなければ分からない問題の一つでした。
Node.jsを使わず、PHPだけで設置できる構成へ

初期版では、リアルタイム通信のためにNode.jsとSocket.IOを使用していました。
ただし、この構成では次のようなサーバー設定が必要です。
- Node.jsのインストール
- npm install
- 常時起動プロセスの設定
- リバースプロキシ
- WebSocketの設定
一般的なレンタルサーバーへ設置するには、少しハードルが高い構成です。
そこで、より簡単に設置できるよう、PHPだけで動作する構成へ変更しました。
最終的なフォルダ構成は、次のようなシンプルなものです。
virtualoffice/
index.php
api.php
setup.php
login.php
assets/
css/
js/
avatars/
data/
フォルダをそのままサーバーへアップロードすれば、次のURLで利用できます。
https://任意のURL/virtualoffice/
MySQLの作成も不要です。
アカウントやルーム情報は、サーバー内のデータファイルへ保存する仕組みにしました。
オフィスのデザインも何度も作り直した
初期のマップは、シンプルな図形を並べただけのデザインでした。
しかし、実際に使ってみると、少し無機質でオフィスらしさが足りません。
そこで、ピクセルアート風のバーチャルオフィスを参考にしながら、次のようなエリアを作りました。
- OPEN OFFICE
- ラウンジ
- 集中作業エリア
- 全員で話せる場所
- 6人で話せる場所
- 4人で話せる場所
- 2人で話せる場所
ただし、単に見た目を整えるだけではありません。
座席が重なってクリックできない問題や、会議ブースの縦幅が足りない問題など、実際に操作して初めて分かる問題も多く発生しました。
そのたびに座席の配置や部屋の大きさを調整しました。
会話範囲から、ブース単位の通話へ
最初は、アバターを中心とした円形の可聴範囲を設定していました。
相手が円の中へ入ると通話が始まり、離れると通話が終了する仕組みです。
しかし、会議ブース内でも距離によって声が聞こえたり聞こえなかったりするのは、不自然でした。
そこで、通話条件を次のように変更しました。
オープンエリア

アバター同士が一定距離以内に近づくと通話できます。
会議ブース

同じブース内にいる人全員が、距離に関係なく通話できます。
現在は次の4種類のブースがあります。
- 全員で話せる場所
- 6人用ルーム
- 4人用ルーム
- 2人用ルーム
ブースに入るだけで通話グループへ参加できるため、座席の位置に左右されません。
呼び出し機能も追加
バーチャルオフィスにログインしていても、マイクやカメラをOFFにしていると、相手が話しかけていることに気づかない場合があります。
そこで、ユーザーを呼び出す機能を追加しました。
メンバー一覧の「呼出」ボタンを押すと、相手の画面に通知が表示されます。
通知には次の情報が表示されます。
- 呼び出したユーザー名
- 呼び出した日付
- 呼び出した時刻
通知は、相手が「応答する」または「応答しない」を押すまで消えません。
また、呼び出し時にはチャイム音を鳴らします。
何度も自動的に音が鳴ると煩わしいため、チャイムは一度だけ鳴らし、必要であれば呼び出した側が手動で再呼出できる仕様にしました。
ログインと管理者機能を追加
試作段階では、名前を入力するだけで誰でも入室できる状態でした。
しかし、本番利用を考えると、アカウント管理が必要です。
そこで、メールアドレスとパスワードによるログイン機能を追加しました。
ユーザー登録は承認制です。
利用者が自分でアカウント登録を行い、管理者が承認するとログインできるようになります。
管理者ツールでは、次の操作ができます。
- 登録申請の承認
- 登録申請の却下
- ユーザー追加
- ユーザー削除
- アカウントの停止
- 管理者権限の付与
- パスワードの再設定
右上のヘッダーには「管理者」と表示され、管理者ツールへの導線も設置しました。
ステータスと「ひとこと」で状況を伝える

ユーザーは、次のステータスを選択できます。
- 対応可能
- 取り込み中
- 集中中
- 離席中
当初は色だけで状態を表していました。
しかし、色だけでは分かりにくいため、アバターの上に文字でも表示するようにしました。
[対応可能]
[取り込み中]
[集中中]
[離席中]
さらに、現在行っている作業を表示できる「ひとこと」機能も追加しました。
例えば、次のように入力できます。
見積書を作成中です
15時まで集中作業します
お客様と電話中です
入力した内容は、アバターの上に吹き出しで表示されます。
直接声をかけなくても、その人が何をしているか分かるようになりました。
離席中は音をすべて停止

ステータスを「離席中」にした場合は、単に表示を変えるだけではありません。
離席中は次の処理を行います。
- オフィス画面を暗くする
- 相手の通話音声を停止
- 自分のマイク送信を停止
- 呼び出しチャイムを停止
- 振動通知を停止
- 呼び出しへの応答を停止
離席状態を解除すると、以前のマイク設定や通話音声が復元されます。
「離席中なのに音が鳴り続ける」という状態を防ぐための機能です。
カメラ・マイク設定も本格的に
音声や映像は、端末やブラウザによって動作が変わります。
特にMacでは、複数のマイクやスピーカーが接続されている場合、どのデバイスが選択されているか分かりにくいことがあります。
そこで、音声・カメラ設定画面を追加しました。
設定できる項目は次のとおりです。
- 使用するマイク
- 使用するスピーカー
- 使用するカメラ
- エコー除去
- ノイズ抑制
- 音量自動調整
- 背景ぼかし
- カメラ画質
さらに、マイクボタンの下に「自動検出」ボタンを追加しました。
自動検出では、Macに接続されているマイクを順番に確認し、実際に音声入力があるマイクを選択します。
同じヘッドセットのスピーカーが見つかった場合は、その出力先も選択します。
通信環境に応じてカメラ画質を変更

スマートフォンで屋外から利用する場合、高画質のカメラ映像は通信量を多く消費します。
そこで、カメラ画質を3段階から選べるようにしました。
| 画質 | 解像度 | フレームレート |
|---|---|---|
| 高画質 | 1280×720 | 最大30fps |
| 中画質 | 640×360 | 最大24fps |
| 低画質 | 320×180 | 最大15fps |
スマートフォンや低速回線では、中画質または低画質を推奨します。
通信状態が悪化した場合、自動的に画質を下げる機能も追加しました。
一度画質を下げた後は、通信量が再び増えないよう、勝手に高画質へ戻さない仕様です。
誰が話しているか、音量に合わせて表示
複数人で通話していると、誰が話しているのか分かりにくいことがあります。
そこで、マイク音量をリアルタイムで解析し、話しているユーザーを緑色で表示するようにしました。
発話中は次の部分が緑色になります。
- アバターの枠
- カメラ映像の枠
- 画面共有の枠
- 拡大表示中の映像枠
声の大きさに合わせて、緑色の光り方も変化します。
一般的なWeb会議ツールにある、アクティブスピーカー表示に近い機能です。
カメラの背景ぼかしと画面共有

カメラには背景ぼかし機能も追加しました。
対応ブラウザでは、ブラウザ標準の背景ぼかしを使用します。
標準機能が利用できない場合は、人物と背景を分離して、背景部分へぼかし処理をかけます。
また、画面共有にも対応しています。
共有された画面やカメラ映像は、クリックまたはタップすると拡大表示できます。
映像表示位置も、当初の右下から画面上部中央へ変更しました。
スマートフォン対応で最も苦労したこと

今回、特に修正回数が多かったのがスマートフォン表示です。
パソコンでは問題なく表示されていても、スマートフォンでは次のような問題が発生しました。
- サイドバーが画面を覆って閉じられない
.workspace-shellの空列が残る- オフィス画面が左端へ圧縮される
- 閉じるボタンが画面外へ出る
- ダイアログの横幅が足りない
- 横スクロールが発生する
最終的には、スマートフォンではメンバー・チャット欄を画面上へ重ねるドロワー形式にしました。
初期状態では閉じておき、右上の「開く/閉じる」ボタンで切り替えます。
オフィスの移動は、次の操作に対応しています。
- 方向ボタン
- 床をタップして移動
- ダブルタップで瞬時に移動
- マップのドラッグ
- 拡大・縮小
録音機能も追加
通話内容を端末へ保存できる録音機能も追加しました。
録音開始前には、参加者へ録音することを伝えたか確認します。
録音中は、音声が正しく入力されているか確認できるよう、リアルタイムの波形を表示します。
- 音声入力あり
- 音声が小さい
- 無音
- 自分の音声
- 接続相手の音声
録音後は、その場で再生確認できます。
ファイルはブラウザ内で生成し、利用者の端末へ保存します。録音データをサーバーへ自動送信することはありません。
TEAM BOARDは全員で編集可能に
OPEN OFFICEには、メンバー全員で編集できるTEAM BOARDも設置しました。
ボードをクリックすると、見出しと本文を編集できます。
例えば、次のような内容を共有できます。
今週の重点
顧客対応と新規提案資料の作成
保存した内容は、同じオフィスにいるメンバー全員へ反映されます。
最終更新者と更新日時も表示されます。
簡易的な社内掲示板として利用できます。
完成形を最初から設計しなかったことが、結果的によかった
出来上がったものは以下です。

今回の開発では、最初から完璧な仕様書を作りませんでした。
まず動くものを作り、実際に触りながら改善しています。
その結果、机上では気づかなかった多くの問題を発見できました。
例えば、
- 会話範囲が広すぎる
- ブース内では距離判定が不要
- スマートフォンのサイドバーが閉じられない
- 録音ファイルに音声が入っていない
- マイクの選択が分かりにくい
- 座席同士が重なっている
といった問題です。
どれも、実際に画面を開き、操作してみなければ分からないものでした。
「小さく作る、使う、直す」という進め方が、今回の開発には合っていたと思います。
AIはプログラムを書く道具だけではなかった
今回、ChatGPTは単にコードを生成するだけではなく、次のような役割も担いました。
- 機能要件の整理
- UI構成の検討
- 不具合の原因調査
- PHP構成への変更
- WebRTC処理の実装
- スマートフォン表示の修正
- 管理画面の設計
- 録音や音声解析の実装
- 配布用ZIPファイルの作成
ただし、AIが最初から完成品を作ったわけではありません。
実際の画面を確認し、問題点を具体的に伝え、何度も修正を重ねています。
AI開発では、指示を一度出して終わりではなく、人間が実際に使いながら方向を決めることが重要だと感じました。
今後追加したい機能
現在でも社内向けのバーチャルオフィスとして利用できる状態ですが、今後は次のような機能も検討しています。
- 管理者によるマップ編集
- 会議室の予約
- 部屋ごとの入室制限
- 社内カレンダーとの連携
- SlackやGoogle Chatとの連携
- 通話品質のさらなる改善
- TURNサーバーの導入
- AIによる録音内容の文字起こし
- AIによる会議要約
- 勤怠・在席履歴の表示
バーチャルオフィス単体ではなく、社内情報が集まる場所へ発展させることもできそうです。
まとめ
今回の制作では、MetaLifeのようなバーチャルオフィスを参考にしながら、自社で使いやすい形へ少しずつ機能を追加していきました。
最初はアバターが動くだけの試作品でしたが、現在は次の機能を備えています。
- アバター移動
- 近距離音声通話
- ブース単位のグループ通話
- カメラ通話
- 画面共有
- 背景ぼかし
- 呼び出し通知
- ステータス表示
- ひとこと表示
- 共有TEAM BOARD
- ログイン
- ユーザー承認
- 管理者機能
- カメラ画質調整
- マイク・スピーカー自動検出
- 発話中ユーザーの強調表示
- 通話録音
- スマートフォン対応
完成したシステムだけを見ると、最初からすべて設計されていたように見えるかもしれません。
しかし、実際には小さな改善の積み重ねです。
AIを使った開発では、「何を作りたいか」を伝えるだけでなく、実際に使い、違和感を伝え、修正を繰り返すことが重要です。
今回の制作は、AIと人間が対話しながらWebサービスを育てていく、一つの実例になりました。
