VPSでセルフホスト型ビデオ会議を運用する方法
VPSでビデオ会議を自ホストする前に、参加者数の2乗で増える帯域幅を計算しましょう。Jitsi、BigBlueButton、GalèneをRAM、UDPポート、NAT越えで比較します。
VPS 上のセルフホスト型ビデオ会議で問題になるのは帯域幅です
小規模なサーバーでセルフホスト型ビデオ会議が失敗する原因はほぼ1つで、インストールであることはほとんどありません。現在の多くのツールが使用するサーバー側のコンポーネントは、SFU(selective forwarding unit)です。SFU は参加者ごとに1本のビデオストリームを受け取り、それを他の各参加者へコピーして転送します。そのため、サーバーから送信されるトラフィックは参加者数の2乗に比例して増加します。共有アップリンク上の1 GB または2 GB のVPSでも、ソフトウェア自体は問題なく動作します。しかし、想定している全員参加の会議に必要な通信量には対応できません。
したがって、次の順序で進めます。参加者数を数え、必要なメガビット数を計算してから、サーバーを選びます。インストール作業は、コピーと貼り付けで20分です。誰の音声が届くかどうかを決めるのは、アップリンクです。
参加者数の2乗に比例して帯域幅が増えるのはなぜですか?
まず、mesh から考えます。各ブラウザーはカメラ映像をエンコードし、ほかの各ブラウザーへ直接コピーを送信します。メディアサーバーは映像に関与しません。2人の mesh 通話に必要なのは signalling server だけです。そのため、1対1の通話はホスティング費用がほとんどかかりません。mesh は4人または5人程度で機能しなくなります。家庭用接続の laptop から、自分の映像を4本または5本に分けて同時にアップロードする必要があるためです。
SFU は異なる方法で動作します。各ブラウザーは映像を1本だけサーバーへアップロードします。サーバーは RTP (real-time transport protocol) ヘッダーを読み取り、映像をデコードせずにパケットをほかの参加者へ転送します。仕組みはこれだけです。そのため、SFU は CPU 負荷が軽く、ネットワーク負荷が大きくなります。
以前は MCU (multipoint control unit) が使われていました。MCU は受信した各ストリームをデコードし、1つの映像に合成してから再エンコードします。送信帯域幅は小さくなります。一方、CPU コストは非常に大きくなります。現在、映像で MCU を使う構成はほとんどありません。このガイドでも使いません。
ここで SFU の計算を見てみます。全員が 1.2 Mbps で映像を送信し、誰もカメラをオフにしていないとします。サーバーの受信量は N × 1.2 Mbps です。これは線形に増加するため、大きな問題にはなりません。サーバーの送信量は N × (N - 1) × 1.2 Mbps です。N 人の各参加者が、残りの N - 1 本のストリームを受信する必要があるためです。プロジェクトを破綻させるのは、この2つ目の数値です。
The data behind this chart
[
{
"label": "4 people",
"sfu_egress_mbps": 14.4,
"egress_gb_per_hour": 6.5,
"monthly_volume_tb": 0.13
},
{
"label": "8 people",
"sfu_egress_mbps": 67.2,
"egress_gb_per_hour": 30.2,
"monthly_volume_tb": 0.6
},
{
"label": "15 people",
"sfu_egress_mbps": 252,
"egress_gb_per_hour": 113.4,
"monthly_volume_tb": 2.3
},
{
"label": "30 people",
"sfu_egress_mbps": "1,044",
"egress_gb_per_hour": 469.8,
"monthly_volume_tb": 9.4
},
{
"label": "50 people",
"sfu_egress_mbps": "2,940",
"egress_gb_per_hour": "1,323",
"monthly_volume_tb": 26.5
}
]これらの行は計算結果であり、特定のサーバーの測定値ではありません。月間の列は、1か月に20時間通話すると仮定しています。まず最後の行を確認してください。50人がカメラをオンにすると、1台のマシンから 2,940 Mbps の送信トラフィックを継続的に送る必要があります。30人では 1,044 Mbps です。4人では 14.4 Mbps であり、これは一般的な VPS なら問題なく処理できます。4人の行から30人の行までで、参加者数は7.5倍に増えます。一方、送信トラフィックは70倍を超えて増加します。
実際の構成では、これらの数値を下回ることがあります。その仕組みを正確に理解しておく価値があります。Jitsi と LiveKit はどちらも simulcast を使用します。送信側は複数の品質レイヤーを同時に公開し、SFU は画面に表示されていない参加者には低品質のレイヤーを転送します。Jitsi には last-N 設定もあり、直近の発言者だけに映像を転送できます。どちらもトラフィックを大幅に削減します。ただし、曲線の形は変わりません。全員がカメラをオンにし、互いの映像をピン留めした時点で、どちらの方法も効果がなくなります。
VPS の uplink で実際に得られるもの
プランページに「1 Gbps port」と記載されていても、それは仮想ネットワークカードの速度であり、次の hop までの速度を保証するものではありません。同じ物理ホスト上の他のテナントとリンクを共有するため、混雑する時間帯に継続して利用できる throughput は port speed より低くなります。conference call は、まさに継続的な負荷です。多くのプランには月間 transfer allowance もあり、上限を超えると帯域制限または従量課金が適用されます。
請求書に大きな差が出るのは、この allowance です。30 人の call を 1 か月に 20 時間行うと、1 時間あたり 469.8 GB の速度で、サーバーから 9.4 TB が送信されます。50 人の call を 20 時間行うと、送信量は 26.5 TB です。RAM の容量を確認する前に transfer allowance を確認してください。プランページにその内容が明確に記載されていない場合、その曖昧さ自体が答えです。この用途では、他のほとんどの用途以上に 安価な VPS プランを正しく読み解くことが重要です。
Jitsi Meet: デフォルトの選択肢と必要な要件
Jitsi Meet は、多くの人が最初に選ぶべき製品です。プロジェクト独自の Debian リポジトリからインストールでき、インストール中に nginx と証明書を設定します。また、ビデオブリッジ(JVB)が使用する UDP ポートは 1 つだけなので、ファイアウォールルールを簡潔に保てます。Debian 11 以降、または Ubuntu 22.04 以降が必要です。
sudo apt update
sudo apt install -y apt-transport-https curl gnupg
sudo add-apt-repository universe
sudo apt update
sudo curl -sL https://prosody.im/files/prosody-debian-packages.key -o /usr/share/keyrings/prosody-debian-packages.key
echo "deb [signed-by=/usr/share/keyrings/prosody-debian-packages.key] http://packages.prosody.im/debian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/prosody-debian-packages.list
sudo apt install -y lua5.2
curl -sL https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
echo "deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/" | sudo tee /etc/apt/sources.list.d/jitsi-stable.list
sudo apt update
sudo apt install -y jitsi-meetインストーラーはホスト名を尋ね、その後で証明書の選択肢を表示します。Let's Encrypt を選び、このサーバーのパブリックアドレスにすでに解決されるドメイン名を指定します。証明書は HTTP チャレンジで発行されるため、別の場所を指す名前ではこの手順に失敗します。
次にポートを開きます。以下はハンドブックに記載されているポートです。ufw enable によって接続できなくならないよう、SSH を最初に記述しています。
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 10000/udp
sudo ufw allow 3478/udp
sudo ufw allow 5349/tcp
sudo ufw enableTCP 80 と 443 は Web アプリケーションを提供し、証明書の更新にも使用します。UDP 10000 はすべての音声と映像を運びます。このポートを忘れる人が多いため、特に注意が必要です。UDP 3478 と TCP 5349 は、Jitsi パッケージがブリッジとともにインストールする coturn サーバー用です。これは、ネットワークによって UDP がブロックされている場合のフォールバック経路になります。
sudo systemctl status jitsi-videobridge2
sudo ss -ulnp | grep 10000最初のコマンドでは、サービスが active と表示されるはずです。2 番目のコマンドでは、ブリッジが UDP 10000 で待ち受けていることを確認できます。何も表示されない場合、ブリッジは起動していません。/var/log/jitsi/jvb.log で原因を確認できます。
サイジングについては、Jitsi のハンドブックが独自の開始点を示しており、BigBlueButton はそれより大幅に大きい値を示しています。
The data behind this chart
[
{
"label": "Jitsi Meet",
"ram_gb": 8,
"cpu_cores": 4,
"uplink_mbps": "1,000"
},
{
"label": "BigBlueButton 3.0",
"ram_gb": 16,
"cpu_cores": 8,
"uplink_mbps": 250
}
]Jitsi のハンドブックでは、本格的なサーバーには 8 GB の RAM と 4 個の専用コアを推奨しています。ネットワーク帯域は 1,000 Mbps で十分なことが多く、小規模な構成では 4 GB または 2 GB でも動作すると説明しています。このページには、覚えておくべき点が 1 つあります。シグナリングを処理する XMPP サーバーの Prosody は、1 コアしか使用できません。追加のコアはブリッジには役立ちますが、シグナリングには効果がありません。
なぜ全員が通話に参加できるのに、誰も映像を見られないのですか?
これは VPS でよくある Jitsi の障害です。参加者一覧は表示され、チャットも動作しますが、すべての映像タイルが黒いままになります。Videobridge は、自身のインターフェース上で検出したアドレスを通知します。プロバイダーが仮想マシンにプライベートアドレスを割り当て、そこにパブリックアドレスをマッピングする構成では、JVB が検出できるのはプライベートアドレスだけです。そのため、各クライアントは 10.0.0.5 のようなアドレスへメディアを送ろうとしますが、パケットは到達しません。
ブリッジに両方のアドレスを指定します。/etc/jitsi/videobridge/jvb.conf に静的マッピングを追加します。
ice4j {
harvest {
mapping {
static-mappings = [
{
local-address = "10.0.0.5"
public-address = "203.0.113.10"
}
]
}
}
}sudo systemctl restart jitsi-videobridge2 で再起動します。ローカルアドレスは ip -4 addr show から取得し、パブリックアドレスはプロバイダーのコントロールパネルで確認します。古いガイドでは、/etc/jitsi/videobridge/sip-communicator.properties に org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS と org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS のキーを設定しています。これらも引き続き使用できますが、新規インストールでは上記のマッピングブロックを使用してください。
もう 1 つの原因は、設定していないファイアウォールです。多くのプロバイダーは、サーバー上の ufw とは別に、コントロールパネルでネットワークファイアウォールを提供しています。UDP 10000 は両方で許可する必要があります。どの層でパケットが破棄されているかを調べるには、外部から誰かが参加している間にサーバー上で sudo tcpdump -ni any udp port 10000 を実行します。パケットがまったく届かない場合、サーバーまで到達していないため、ブロック箇所はオペレーティングシステムより上流です。タイルが黒いままでもパケットが到着する場合、ブリッジはクライアントから到達できないアドレスを返しています。この場合はマッピングが原因です。ufw 自体に不明点がある場合は、VPS で実際に必要な ufw ルールで、問題になりやすいルールの順序を説明しています。
BigBlueButton: 高負荷で独自要件が多く、サーバー全体を必要とする
BigBlueButton は授業向けに設計されています。ホワイトボード、ブレイクアウトルーム、投票、プレゼンテーション領域を備え、録画パイプラインも追加機能ではなく中核機能として提供されます。一方で、この中では大幅に高負荷な選択肢です。既存のサーバーに追加するパッケージではありません。
2026 年 8 月時点でサポートされる構成は、Ubuntu 22.04 上の BigBlueButton 3.0 です。jammy-300 version flag で選択します。プロジェクトが示す本番要件は、swap を有効にした 16 GB のメモリ、シングルスレッド性能が高い 8 CPU コア、250 Mbps の対称帯域幅です。録画を保持する場合は 500 GB、無効にする場合は 50 GB のディスクが必要です。ポートは TCP 80 と 443、および UDP 16384 から 32768 の範囲です。
wget -q https://raw.githubusercontent.com/bigbluebutton/bbb-install/v3.0.x-release/bbb-install.sh
less bbb-install.sh
bash bbb-install.sh -w -v jammy-300 -s bbb.example.com -e info@example.com -gプロジェクト独自の例では、このスクリプトをそのまま bash にパイプしています。ただし、先にダウンロードして内容を確認してください。このスクリプトは nginx の設定を書き換え、独自のメディアおよび音声スタックをインストールし、パッケージのバージョンを固定して、ホスト名を取得します。これは欠陥ではなく設計上の仕様です。BigBlueButton はマシン全体を管理することを前提としています。-w flag はファイアウォールを設定し、-s はホスト名、-e は Let's Encrypt が登録するアドレスです。-g を指定すると Greenlight フロントエンドが追加されます。同じホストで他のサービスの TLS 終端も担う場合は、BigBlueButton を別の場所に移すか、スクリプトが編集する前に nginx リバースプロキシの設定内容を理解していることを確認してください。
この表の 2 行は注意して比較してください。BigBlueButton が求めるメモリとコア数は、Jitsi の提案値の 2 倍です。一方、帯域幅は 4 分の 1 です。2 つの数値は同じ方法で測定されておらず、想定するルーム規模も異なります。そのため、単純な比較ではなく、それぞれのプロジェクトにおける開始点として扱ってください。CPU 要件の差は実際に存在します。これは、BigBlueButton が動画の転送以外にも多くの処理を行うためです。
Galène: 小規模構成向けの選択肢
Galène は Go で書かれたコンパクトな SFU です。単一の静的バイナリとしてビルドでき、Web クライアントを内蔵し、TURN サーバーも含まれています。そのため、常時稼働させる XMPP サーバー、Java ランタイム、Rails アプリケーションは必要ありません。控えめなスペックのサーバーで安定した10人規模の通話を実現したい場合は、より高性能なハードウェアが必要だと判断する前に、これを試してください。
sudo apt update && sudo apt install -y git golang-go
git clone https://github.com/jech/galene
cd galene
CGO_ENABLED=0 go build -ldflags='-s -w'
mkdir groupsUbuntu 24.04 の golang-go パッケージは Go 1.22 です。go build がモジュールに新しい Go が必要だと報告する場合は、ディストリビューションのパッケージと格闘せず、go.dev から最新のツールチェーンをインストールしてください。
グループは Galène でルームを指す用語です。グループは JSON ファイルで定義します。
echo '{"users": {"vimes": {"password":"sybil", "permissions":"op"}}}' > groups/night-watch.json
./galene &https://your.server:8443/group/night-watch/ を開き、vimes としてログインします。この認証情報はプロジェクトの README にそのまま記載されているため、ポートを外部から到達可能にする前に変更してください。実運用では、プロジェクトが systemd unit を用意しています。
[Unit]
Description=Galene
After=network.target
[Service]
Type=simple
WorkingDirectory=/home/galene
User=galene
Group=galene
ExecStart=/home/galene/galene
LimitNOFILE=65536
[Install]
WantedBy=multi-user.targetポートは、Web インターフェース用の TCP 8443、組み込み TURN サーバー用の TCP と UDP 1194、メディア用の高位 UDP ポート範囲です。ファイアウォールルールを1つにまとめられるよう、その範囲を固定します。
./galene -udp-range 40000-40100VPS で重要なのは -turn オプションです。-turn ':1194' はすべてのパブリック IPv4 アドレスで待ち受けます。-turn '203.0.113.1:1194' は、クライアントから実際に見えるアドレスを Galène に指定します。マシン自体のアドレスがプライベートである場合に必要です。-turn '' は組み込みサーバーを無効にし、data/ice-servers.json を通じて外部サーバーを指定できるようにします。デフォルトは auto です。ice-servers.json が存在しない場合は、:1194 と同じ動作になります。
data/config.json で proxyURL を設定し、WebSocket の upgrade ヘッダーを付けて /ws location をプロキシすれば、Web インターフェースの前段に nginx を配置できます。ただし、対象範囲を正しく理解してください。クライアントは TURN ポートに対して、直接 UDP フローと直接 TCP 接続を開きます。そのため、リバースプロキシが処理するのはページとシグナリングだけです。メディアはリバースプロキシを通りません。
Galène のドキュメントには、必要なサーバーリソースは非常に少ないと記載されていますが、具体的な数値は示されていません。そのため、具体的な数値を期待しないでください。上記の帯域幅の計算は、そのまま全面的に適用されます。削減できるのは、SFU 以外の要素に必要なメモリと運用上の構成要素です。
Owncast: 1 対多で帯域幅が線形に増える構成
「ビデオ会議」が必要だと思われている要件の多くは、実際には 1 人が視聴者に向けて発表し、視聴者がチャットに入力する構成です。その用途であれば、SFU は適切なツールではなく、コスト構造も大きく変わります。Owncast は OBS などのエンコーダーから RTMP ストリームを受け取り、通常の HTTPS で HLS を配信します。視聴者ごとの帯域幅は二次関数ではなく線形に増加します。また、出力は通常の HTTP セグメントなので、object storage や CDN の背後に移し、origin 側での配信コストをなくせます。
curl -sL https://owncast.online/install.sh -o install-owncast.sh
less install-owncast.sh
bash install-owncast.shプロジェクトのドキュメントでは、root で実行しないことと、リモートスクリプトを実行する前に内容を確認することが推奨されています。そのため、上ではダウンロードを別の手順にしています。インストーラーは、既存の ffmpeg がない場合、最新のリリースと ffmpeg バイナリを取得します。インストールディレクトリで ./owncast を実行し、ポート 8080 の /admin で管理パネルを開きます。デフォルトのログインユーザーは admin で、パスワードにはデフォルトのストリームキー abc123 を使います。ドメインをサーバーに向ける前に変更してください。
HLS の設計から、2 つの結果が生じます。HLS はセグメント全体を配信するため、視聴者にはライブ映像から数秒または数分の遅延が生じます。そのため、双方向の会話には向きません。また、経路上で UDP も TURN も使わないため、WebRTC の通話を接続できないネットワークにも到達できます。
Owncast は、この中で意図的にトランスコードを行う唯一のツールでもあります。有効にした出力品質ごとに、入力ストリームを別途 ffmpeg でエンコードします。この処理は配信中ずっと実行されます。小規模な VPS では、品質を 1 つまたは 2 つにしてください。5 つにすると、ネットワークがアイドル状態でも CPU が飽和します。
すでに運用している Matrix サーバーでの Element Call
すでに Matrix を運用している場合、ビデオ機能は別の製品を運用するのではなく、既存環境への追加として扱えます。ただし、必要なパッケージは1つではありません。Element Call では、homeserver の背後に2つのコンポーネントが必要です。1つ目はメディア転送を行う LiveKit SFU です。2つ目は MatrixRTC 認可サービスの element-hq/lk-jwt-service です。このサービスは、接続に使用する LiveKit WebSocket URL と署名済み JWT (JSON web token) をクライアントに渡します。このサービスは Matrix federation API を使用するため、その前段に TLS リバースプロキシが必要です。また、federation から到達できる名前も必要です。
LiveKit のドキュメントに記載されているポートは次のとおりです。
- API とクライアント WebSocket 用の TCP 7880。TLS を終端するプロキシの背後で使用します
- ICE over TCP 用の TCP 7881。クライアントが UDP で外部へ接続できない場合に使用します
- メディア用の UDP 50000 から 60000。ルーム内の各参加者が2つのポートを使用します
- 組み込み TURN サーバーを有効にする場合は UDP 3478 と TCP 5349。ロードバランサーを前段に置かない場合、5349 は 443 に移動する必要があります
参加者1人につき2つのポートが必要だと聞くと不安に感じますが、問題ありません。10,000ポートの範囲で数千人の参加者に対応でき、範囲を使い切る前に uplink が限界に達します。それでも範囲全体を開放してください。範囲の一部だけを開放すると、一部のユーザーでは動作する一方で、別のユーザーでは失敗します。このような障害は切り分けが最も困難です。homeserver 側の設定は別途必要です。詳しくは VPS で Synapse homeserver を運用する を参照してください。
1 人だけ接続できないのはなぜか。TURN と UDP をブロックするネットワーク
まず、今回だけ使用する用語を説明します。ICE(interactive connectivity establishment)は、2 つの WebRTC エンドポイントが通信可能な経路を見つけるための処理です。STUN(session traversal utilities for NAT)は、外部から見たクライアント自身のパブリックアドレスをクライアントに伝える小規模なサービスです。TURN(traversal using relays around NAT)はリレーです。直接の経路がない場合、双方がメディアを TURN サーバーへ送り、TURN サーバーが転送します。
把握できないネットワークにいる参加者には TURN が必要です。1 人は、送信 UDP が完全にブロックされた企業ネットワークまたはキャンパスネットワークに接続しています。別の 1 人は、宛先ごとに異なる送信元ポートを割り当てるキャリアグレード NAT の背後にいます。これは symmetric NAT と呼ばれ、STUN が報告したアドレスを使えなくします。
症状には明確な特徴があります。ほとんどの人は参加でき、すべて正常に動作します。1 人だけが参加者一覧とチャットを確認できる一方で、黒いタイルとスピナーが表示されます。そのブラウザーは候補を収集しましたが、どの候補ペアも機能せず、ICE は失敗状態で終了しています。Chrome では、試行中に chrome://webrtc-internals を開くと、候補ペアと失敗状況を確認できます。その人に、モバイルデータ通信中のスマートフォンから再試行してもらいます。そこで動作するなら、原因はその人のネットワークであり、TURN が解決策です。
443 または 5349 の TCP 上で動作する TURN は、ほぼどの環境でも機能するフォールバックです。443 の TLS をブロックするネットワークは、Web もブロックしているためです。Jitsi のパッケージは coturn をインストールして設定するため、ドキュメントに UDP 3478 と TCP 5349 のファイアウォールルールが記載されています。Galène には 1194 で動作する TURN が組み込まれています。LiveKit には、設定で有効にできる組み込み TURN サーバーがあります。coturn を自分で実行する場合は、次のようにします。
sudo apt install -y coturn
sudo systemctl enable --now coturnlistening-port=3478
tls-listening-port=5349
fingerprint
use-auth-secret
static-auth-secret=REPLACE_WITH_A_LONG_RANDOM_STRING
realm=turn.example.com
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
min-port=49152
max-port=65535
no-multicast-peersDebian と Ubuntu では、/etc/default/coturn に TURNSERVER_ENABLED=1 を設定するまで、パッケージのサービスは起動しません。インストール済みでも有効化されていない coturn は、外部から見ると TURN がまったくない場合と同じに見えます。そのため、この 1 行の設定だけで何時間も調査することになります。
次に、記録されにくいコストについて説明します。リレーは、リレーされるすべての参加者の全メディアを双方向に転送します。coturn を SFU と同じホストで動かす場合、そのトラフィックの大部分は loopback を通るため、アップリンクではなく CPU を消費します。また、TLS リスナーは、メディアがすでに使用している DTLS に加えて、すべてのパケットをもう一度暗号化します。TURN を専用マシンへ移す場合、そのマシンにも SFU と同じ方法で見積もった帯域幅プランが必要です。さらに、TCP 上の TURN はリアルタイムメディアを信頼性のあるストリームに変換します。そのため、失われたパケットはスキップされず再送され、損失の多いリンク上のリレー参加者では、一時的な乱れではなく遅延が蓄積します。リレーは接続を成立させるフォールバックですが、品質は直接経路を下回ります。
SFU がトランスコードするのはいつで、どの程度のコストがかかるか
SFU はパケットを転送するだけで、動画をデコードしません。そのため、仕様上は処理が難しそうな規模の会議でも、4 コアで対応できる場合があります。ただし、この特性を崩す機能が2つあります。どちらも、チェックボックスで有効にした人を驚かせます。
1つ目は録画です。Jitsi は Jibri で録画します。Jibri の公式ドキュメントには、動作内容が明確に説明されています。Jibri は仮想フレームバッファー上で描画した Chrome インスタンスを起動し、その出力を ffmpeg でキャプチャーしてエンコードします。これは、会議全体を描画する完全なブラウザーと動画エンコーダーを、通話中ずっと継続的に動かす処理です。同じドキュメントには、1台の Jibri で同時に録画できるのは1件だけであること、また Jibri はディスプレイやオーディオデバイスを使用する他のアプリケーションがない別の物理マシンまたは仮想マシンで実行することが想定されていると記載されています。録画には別のサーバーが必要です。チェックボックスで済む機能ではありません。
2つ目は電話からのダイヤルインです。電話回線を会議に接続するには、Opus の 48 kHz を電話網が受け付ける形式(通常は G.711 の 8 kHz)へ、通話全体を通じて双方向に変換する必要があります。音声のトランスコードは動画のトランスコードより大幅に低コストですが、通話レッグごとに実行され、停止することもありません。そのため、コストは発信者数に応じて増加します。ダイヤルイン番号が必要な場合は、自己ホスト型 VoIP サーバーがこの処理を担います。Jibri と同じ理由で、専用のマシンに配置してください。
実際には、どの程度のスペックのサーバーが必要ですか?
2 人なら、ほとんど必要ありません。Jitsi は参加者がちょうど 2 人の場合、デフォルトで P2P モードを有効にします。このモードでは、会議のデータを videobridge 経由で送信せず、直接接続を使用します。3 人目が参加すると、videobridge 経由に戻ります。そのため、Jitsi を実行する 1 GB VPS は 1 対 1 の通話サーバーとしては十分ですが、4 人の通話には適しません。これが、「テストしたときは動いた」という報告が非常に多い理由です。
カメラをオンにした参加者が約 10 人までであれば、8 人参加時の 67.2 Mbps は、一般的な VPS のアップリンクで維持できる範囲に収まります。録画しない限り、2 個の仮想 CPU と 4 GB で、その規模の Jitsi または Galène を実行できます。CPU グラフではなく、転送量のカウンターを監視してください。
30 人の場合、最悪時の持続帯域幅は 1,044 Mbps で、これを 20 時間使用すると 9.4 TB になります。この規模では、サーバー本体より先に帯域幅の料金を見積もってください。last-N を有効にして、直近の発言者だけを videobridge が転送するようにします。参加者のカメラはデフォルトでオフにし、計算した転送量に耐えられる転送量上限を持つ環境に SFU を配置してください。
それを超える場合、1 台の VPS という構成は適していません。実際には配信であるなら、Owncast と CDN の組み合わせのほうが、この構成の数分の 1 の費用で済みます。そうでなければ、単一のシグナリング層の背後に複数の videobridge が必要です。これは、最初に始めた構成とは別のプロジェクトになります。
最後に、ルーティングについてもう 1 つ説明します。多くのチームでは、ビデオよりもチャットが必要な時間のほうがはるかに長く、チャットは安価にホストでき、稼働も維持しやすいものです。日常の通信には 自ホスト型の Slack 代替サービス を用意し、予定した通話だけに会議サーバーを使用する構成が、小規模な VPS の予算でも無理なく運用できます。
FAQ
なぜ Jitsi の会議には参加できるのに、お互いの映像や音声が見えたり聞こえたりしないのですか?
チャットと参加者一覧は TCP の 443 番ポートを使うシグナリングチャネルを通ります。一方、音声と映像は UDP の 10000 番ポートを使って videobridge に送られます。参加者一覧が表示され、すべてのタイルが黒いままなら、シグナリング経路は正常ですが、メディア経路に問題があります。2 つのファイアウォールで UDP 10000 番ポートを確認してください。確認対象は、サーバー上のファイアウォールと、プロバイダーのコントロールパネルにある別のネットワークファイアウォールです。次に、bridge がパブリックアドレスを認識しているか確認します。プライベートアドレスと、それにマッピングされたパブリックアドレスを持つ仮想マシンでは、/etc/jitsi/videobridge/jvb.conf 内の ice4j.harvest.mapping に静的マッピングを追加して、jitsi-videobridge2 を再起動します。誰かが参加している間に sudo tcpdump -ni any udp port 10000 を実行すると、どちらが原因か分かります。パケットがまったく届かない場合、ブロック箇所はオペレーティングシステムより上流にあります。
30 人のビデオ通話では、どの程度の帯域幅を使いますか?
全員がカメラをオンにし、SFU が全員に最高品質のレイヤーを転送する最悪のケースでは、サーバーからおよそ 1,044 Mbps が送信されます。これは 1 時間あたり 469.8 GB です。この値は、1.2 Mbps のストリームが N × (N - 1) 本ある場合の計算値であり、実際の環境の測定値ではありません。通常の利用では、simulcast と last-N の設定によって大幅に減ります。任意の時点で画面に表示されていない参加者が多いためです。それでも、最悪のケースに近い容量を確保してください。全員が同時にカメラをオンにする全体会議が、最悪のケースになるためです。
1 GB の VPS で Jitsi Meet を実行できますか?
インストールでき、2 人の通話も動作します。Jitsi は参加者がちょうど 2 人の場合に peer to peer モードを使い、videobridge を完全に省略するためです。ただし、グループ通話用のサーバーとしては実用的ではありません。Prosody、videobridge、Java runtime はいずれもメモリを必要とします。公式ハンドブックが本格的なデプロイに推奨するメモリは 8 GB です。また、帯域幅の計算上、メモリより先に帯域幅が問題になります。利用できるサーバーが 1 GB しかない場合、その容量には Jitsi より Galène のほうが適しています。
VPS にパブリック IP アドレスがある場合でも、TURN サーバーは必要ですか?
はい。TURN が解決する問題は、通話の相手側にあります。送信 UDP をブロックする企業ネットワーク上の参加者や、宛先ごとに異なる送信元ポートを割り当てるキャリアグレード NAT の背後にいる参加者は、サーバーのアドレスがパブリックであっても、直接のメディア経路を確立できません。443 または 5349 の TCP 上で TURN を使うと、ファイアウォールから通常の Web トラフィックに見えるリレーを提供できます。Jitsi のパッケージインストールでは、デフォルトでこの用途の coturn が設定されます。そのため、公式のファイアウォールルールでは UDP 3478 と TCP 5349 を開放します。
なぜ BigBlueButton には Jitsi Meet より大幅に多くのハードウェアが必要なのですか?
映像を転送するだけでなく、より多くの処理を行うためです。BigBlueButton の公開されている本番要件は 16 GB の RAM と 8 コアです。一方、Jitsi のハンドブックでは 8 GB と 4 コアが必要とされています。BigBlueButton は、完全な音声会議スタック、共有ホワイトボードとプレゼンテーション層、録画と後処理のパイプライン、ユーザーアカウントを備えた Web フロントエンドを、すべて同じマシン上で実行します。また、プラットフォームの要件も厳格です。2026 年 8 月時点でサポートされるインストールは、Ubuntu 22.04 上の version 3.0 です。これらの数値はどちらも各プロジェクトの公式ドキュメントに基づくもので、利用環境の測定値ではなく、開始点としての目安です。