VPSでセルフホスト型ビデオ会議を運用する方法
VPSの必要帯域を参加者数から計算し、Jitsi、BigBlueButton、GalèneをRAM、開放UDPポート、NAT環境での問題まで比較します。
VPS 上でセルフホストするビデオ会議では帯域幅が問題になります
小規模なサーバーでセルフホストのビデオ会議が失敗する理由は 1 つです。ほとんどの場合、インストールが原因ではありません。現在の多くのツールが使用するサーバー側の機能は SFU(selective forwarding unit)です。SFU は参加者ごとに 1 本の映像ストリームを受け取り、そのコピーを他のすべての参加者へ転送します。そのため、サーバーから出ていくトラフィックは参加者数の 2 乗に比例して増加します。共有アップリンク上の 1 GB または 2 GB の VPS でも、ソフトウェア自体は問題なく動作します。ただし、想定している全員参加の会議を支えられるとは限りません。
したがって、作業はこの順番で進めます。参加者数を数え、必要なメガビット数を算出してから、サーバーを選びます。インストールは、コピーと貼り付けで 20 分かかります。誰もあなたの声を聞けるかどうかは、アップリンクで決まります。
参加者数の2乗に比例して帯域幅が増えるのはなぜですか?
まず、メッシュ構成を考えます。各ブラウザーはカメラ映像をエンコードし、ほかの各ブラウザーへ直接コピーを送信します。メディアサーバーは映像に関与しません。2 人のメッシュ通話にはシグナリングサーバーが必要です。また、2 つのブラウザーが直接接続できない場合は TURN リレーも必要です。そのため、1 対 1 の通話はほとんどコストをかけずにホストできます。メッシュ構成は、4 人または 5 人程度で機能しなくなります。自宅回線に接続したラップトップが、自分の映像を 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 つ目の値です。
このグラフのデータ
[
{
"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」と記載されていても、それは仮想ネットワークカードの速度であり、次のホップまでの速度を保証するものではありません。同じ物理ホスト上の他のテナントとリンクを共有するため、混雑する時間帯の持続的なスループットは port speed を下回ります。conference call はまさに持続的な負荷です。ほとんどのプランには月間転送量の上限もあり、超過すると帯域制限または追加課金が発生します。
請求書上で問題になるのは、この転送量の上限です。30 人の call を 1 か月に 20 時間行うと、9.4 TB がサーバーから送信されます。送信量は 1 時間あたり 469.8 GB です。50 人の call を 20 時間行うと、26.5 TB が送信されます。RAM の容量を確認する前に、転送量の上限を確認してください。プランページにその内容が明確に記載されていない場合、その曖昧さ自体が答えです。この用途では、安価な VPS の提供内容を正しく読むことが、ほかのほとんどの用途より重要です。
Jitsi Meet: 標準的な選択肢と必要な条件
Jitsi Meet は、まず試すべき製品です。プロジェクト独自の Debian リポジトリからインストールでき、インストール中に nginx と証明書を設定します。また、ビデオブリッジ (JVB) は単一の UDP ポートを使用するため、ファイアウォールルールを少なくできます。2026 年 10 月時点で、handbook は Debian 12 (Bookworm) 以降と Ubuntu 24.04 (Noble Numbat) 以降をサポート対象として記載しており、OpenJDK 17 が必要です。
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 challenge によって発行されるため、別の場所を指す名前ではこの手順が失敗します。
次にポートを開放します。以下は handbook に記載されているポートです。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 は、ブリッジを経由するすべての通話の音声と映像を運びます。このポートは忘れられやすいため注意が必要です。TCP 5349 は、Jitsi パッケージがブリッジとともにインストールする coturn サーバーのポートです。UDP をブロックするネットワークを使用するユーザー向けのフォールバック経路になります。UDP 3478 は coturn の STUN ポートです。handbook ではオプション扱いです。Jitsi は config.js を変更した後にのみこのポートを使用するためです。
sudo systemctl status jitsi-videobridge2
sudo ss -ulnp | grep 10000最初のコマンドでは、サービスが active と表示されるはずです。2 番目のコマンドでは、ブリッジが UDP 10000 で待ち受けていることを確認できます。何も表示されない場合、ブリッジは起動していません。/var/log/jitsi/jvb.log に原因が記録されています。
サイジングについては、Jitsi の handbook が独自の開始点を示し、BigBlueButton はそれより大きな要件を示しています。
このグラフのデータ
[
{
"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 の handbook では、通常 8 GB の RAM を推奨し、基本的なサーバーであれば 4 個の専用コアで十分な場合があると説明しています。友人同士または小規模組織向けのサーバーでは 1,000 Mbps のネットワーク帯域で十分なことが多く、本格的なサーバーには 10 Gbps を推奨しています。また、小規模な会議は 4 GB、テストサーバーは 2 GB で運用できるとしています。このページで押さえておくべき点が 1 つあります。シグナリングを処理する XMPP サーバーの Prosody は、1 コアしか使用できない場合があります。追加のコアはブリッジには役立ちますが、シグナリングには効果がありません。
参加者全員が通話に入れるのに、誰も映像を見られないのはなぜですか?
これは VPS でよく発生する Jitsi の障害です。参加者一覧は埋まり、チャットも機能しますが、すべての映像タイルが黒いままになります。videobridge は、自身のインターフェースで検出したアドレスと、検出できたパブリックアドレスを通知します。パッケージを新規インストールすると、この検出のために Jitsi が運用する STUN サーバーが設定されます。また、ハンドブックでは、NAT の背後にある bridge は起動時に自動設定されると説明されています。STUN サーバーへの外向きトラフィックがブロックされている場合など、検出に失敗すると、プライベートアドレス上の bridge はそのアドレスだけを通知します。そのため、各クライアントは 10.0.0.5 のようなアドレスへメディアを送ろうとし、パケットは到達しません。ハンドブックに記載されているこの症状は、2 人なら通話できるのに 3 人目が参加すると失敗するというものです。2 人の場合は peer to peer モードが使われ、bridge を経由しないためです。
検出だけでは不十分な場合は、両方のアドレスを bridge に手動で指定します。/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 を実行します。パケットがまったく表示されない場合、パケットはマシンに到達していないため、ブロック箇所はオペレーティングシステムより上流にあります。タイルが黒いままでもパケットが到着している場合、bridge はクライアントから到達できないアドレスを応答しています。つまり、問題はマッピングにあります。ufw 自体の設定に不安がある場合は、VPS に実際に必要な ufw ルールで、問題になりやすいルールの順序を確認できます。
BigBlueButton: 高負荷で構成の自由度が低く、サーバー全体を必要とする
BigBlueButton は授業向けに設計されています。ホワイトボード、ブレイクアウトルーム、投票、プレゼンテーション領域を備え、録画パイプラインも追加機能ではなく中核機能として提供されます。一方で、この中では大幅に負荷が高く、既存サーバーに追加するパッケージではありません。
2026 年 10 月時点でサポートされる構成は、Ubuntu 22.04 上で動作する BigBlueButton 3.0 です。バージョンは jammy-300 フラグで指定します。Ubuntu 24.04 に移行する BigBlueButton 4.0 はリリース候補版としてのみ提供されており、プロジェクトは本番環境では 3.0.x を引き続き推奨しています。プロジェクトが示す本番要件は、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 -v jammy-300 -s bbb.example.com -e info@example.com -gプロジェクトの例では、このスクリプトをそのまま bash にパイプします。ただし、先にダウンロードして内容を確認してください。このスクリプトは nginx の設定を書き換え、独自のメディアおよび音声スタックをインストールし、パッケージのバージョンを固定して、ホスト名を取得するためです。これは欠陥ではなく、設計上の動作です。BigBlueButton はサーバー全体を自分で管理することを前提としています。現在のスクリプトはデフォルトで ufw ファイアウォールもインストールします(無効にする場合は -W を渡します。古い -w フラグも引き続き受け付けますが、何も実行しません)。-s はホスト名、-e は Let's Encrypt が登録するアドレス、-g は Greenlight フロントエンドを追加するための指定です。同じサーバーで他のサービスの TLS 終端も行う場合は、BigBlueButton を別のサーバーへ移すか、スクリプトが編集する前に nginx リバースプロキシの設定内容を把握してください。
この表の 2 つの行を注意深く比較してください。BigBlueButton は、Jitsi の推奨値の 2 倍のメモリと 2 倍のコアを求める一方、帯域幅は 4 分の 1 です。2 つの数値は同じ方法で測定されたものではなく、想定するルーム規模も異なります。そのため、単純な比較ではなく、それぞれのプロジェクトにおける導入時の目安として扱ってください。CPU の差は実際に存在します。これは、BigBlueButton が映像の転送以外にも多くの処理を行うためです。
Galène: 小規模構成の選択肢
Galène は Go で実装されたコンパクトな SFU です。単一の static binary としてビルドでき、独自の web client を内蔵し、TURN server も含まれています。そのため、XMPP server、Java runtime、Rails application を常時稼働させる必要がありません。控えめなサーバーで 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 package は Go 1.22 ですが、Galène の go.mod は現在 Go 1.24 を要求します。go build が module に新しい Go が必要だと報告する場合は、distribution package と格闘せず、go.dev から現行の toolchain をインストールしてください。
group は Galène で room を表す用語で、group は JSON file です。
echo '{"users": {"vimes": {"password":"sybil", "permissions":"op"}}}' > groups/night-watch.json
./galene &https://your.server:8443/group/night-watch/ を開き、vimes としてログインします。この認証情報はプロジェクトの README にそのまま記載されているため、他の場所から port に到達できるようになる前に変更してください。本番運用では、プロジェクトの install guide に従って専用の galene user を使用し、その home に binary と static、data、groups directories を配置します。./galene & で起動したテスト用の copy を停止し、ビルドした directory で次を実行します。
sudo useradd --system --create-home --home-dir /home/galene --shell /usr/sbin/nologin galene
mkdir -p data
sudo cp -r galene static data groups /home/galene/
sudo chown -R galene:galene /home/galeneプロジェクトでは、次の 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.targetport は、web interface 用の TCP 8443、組み込み TURN server 用の TCP および UDP 1194、media 用の広い範囲の high UDP ports です。install guide では数万 port 程度の広い範囲を求めているため、広い範囲を固定し、その範囲に対して firewall rule を 1 つ作成します。
./galene -udp-range 30000-65000VPS で重要なのは -turn option です。-turn ':1194' はすべての public IPv4 addresses で listen します。-turn '203.0.113.1:1194' は、client から実際に見える address を Galène に指定します。マシン自身の address が private の場合に必要です。-turn '' は組み込み server を無効にするため、data/ice-servers.json を介して外部 server を指定できます。default は auto で、ice-servers.json が存在しない場合は :1194 と同じ動作になります。
data/config.json で proxyURL を設定し、WebSocket upgrade headers を付けて /ws location を proxy すれば、web interface の前段に nginx を配置できます。この構成で処理される範囲を理解しておいてください。client は引き続き TURN port に対して direct UDP flows と direct TCP connections を確立します。reverse proxy が処理するのは page と signalling だけです。media は reverse proxy を通りません。
Galène の README では、必要な server resources は非常に少ないと説明されています。プロジェクトの home page では、おおよその値として、1 つの meeting では 1 core あたり約 20 participants、lecture では 1 core あたり約 300 participants としています。meeting の負荷は参加者数の 2 乗に比例して増えるためです。上記の bandwidth の計算は、そのまま完全に適用されます。削減できるのは、SFU 以外のすべてに必要な memory と運用要素です。
Owncast: 1 対多で帯域幅が線形に増加
「ビデオ会議」の要件の多くは、実際には 1 人が発表し、視聴者がチャットに入力する構成です。その場合、SFU は適切なツールではなく、コスト構造も大きく変わります。Owncast は OBS などのエンコーダーから RTMP ストリームを受け取り、通常の HTTPS で HLS を配信します。視聴者 1 人あたりの帯域幅は二次関数ではなく線形に増加します。出力は通常の HTTP セグメントであるため、オブジェクトストレージや CDN の背後に移し、オリジン側での配信コストをなくすこともできます。
curl -sL https://owncast.online/install.sh -o install-owncast.sh
less install-owncast.sh
bash install-owncast.shプロジェクトのドキュメントでは、root で実行しないことと、リモートスクリプトを実行前に確認することが推奨されています。そのため、上ではダウンロードを別の手順にしています。インストーラーは、現在のリリースと、まだ用意されていない場合は ffmpeg バイナリを取得します。インストールディレクトリで ./owncast を実行し、ポート 8080 の /admin で管理パネルを開きます。デフォルトのログインユーザーは admin、パスワードは abc123 です。デフォルトのストリームキーも 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 です。このサービスは、Matrix ユーザーが LiveKit SFU に提示する署名済み JWT(JSON web token)を発行します。現在のバージョンは、homeserver 上の application service として動作し、client API と federation API の両方で LiveKit のエンドポイントをプロキシする構成を前提としています。client がサービスと直接通信する従来の standalone モードも引き続きサポートされていますが、非推奨です。どちらの構成でも、プロジェクトは手前に TLS reverse proxy を置くことを推奨しています。また、.well-known/matrix/client で client がその reverse proxy を参照するように設定する必要があります。
LiveKit でドキュメントに記載されているポートは次のとおりです。
- API と client WebSocket に使用する TCP 7880。TLS を終端する proxy の背後で運用します
- ICE over TCP に使用する TCP 7881。client が UDP で外部へ接続できない場合に使われます
- メディアに使用する UDP 50000 to 60000。room 内の参加者 1 人につき 2 ポートを使用します
- 組み込み TURN server を有効にする場合の UDP 3478 と TCP 5349。5349 は、手前に load balancer がない限り 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 は failed 状態で終了しています。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-peersこれらの設定は /etc/turnserver.conf に記述します。Debian と Ubuntu では、標準状態のこのファイルを使って、パッケージのインストール直後に coturn が起動します。そのため、上記の enable --now を実行しても、すでに起動していることが検出され、何も変更されません。設定は sudo systemctl restart coturn を実行すると有効になります。その後、ファイルを編集するたびに同じ restart が必要です。古いガイドでは、/etc/default/coturn で TURNSERVER_ENABLED=1 を設定するよう指示していることもあります。このスイッチを読み取るのは古い init script だけです。現在のパッケージが実行する systemd unit は読み取らないため、その行は何も変更しません。また、再起動していない coturn は引き続き標準のファイルを使います。
次に、記載されないコストがあります。リレーは、リレー経由のすべての参加者のメディア全体を双方向に転送します。coturn を SFU と同じホストで実行すると、そのトラフィックの大部分は loopback を通過するため、uplink ではなく CPU を消費します。また、TLS listener は、メディアがすでに使用している DTLS に加えて、すべてのパケットをもう一度暗号化します。TURN を専用マシンに移す場合、そのマシンにも SFU と同じ考え方で容量を決めた帯域幅プランが必要です。さらに、TCP 経由の TURN はリアルタイムメディアを信頼性のあるストリームに変えます。そのため、失われたパケットは破棄されずに再送され、パケット損失の多い接続上のリレー参加者では、一時的な乱れではなく遅延が蓄積します。リレーは接続を確立するためのフォールバックですが、品質は直接経路のほうが優れています。
SFU がトランスコードするのはどのような場合で、どれほどのコストがかかりますか?
SFU はパケットを転送するだけで、映像をデコードしません。そのため、机上では処理が難しそうなルームでも、4 コアで処理できる場合があります。この性質を損なう機能が 2 つあります。どちらも、チェックボックスで有効にした人を驚かせます。
1 つ目は録画です。Jitsi は Jibri で録画します。Jibri の公式ドキュメントには、その動作が正確に説明されています。Jibri は仮想フレームバッファー上で描画した Chrome インスタンスを起動し、出力を ffmpeg でキャプチャしてエンコードします。これは、会議全体をブラウザーで描画し、さらにビデオエンコーダーを実行する処理です。通話中は継続的に動作します。同じドキュメントには、1 台の Jibri で同時にサポートされる録画は 1 件だけであり、ディスプレイやオーディオデバイスを使用する他のアプリケーションがない別のマシンまたは仮想マシンで Jibri を実行することが想定されている、と記載されています。録画には別のサーバーが必要です。チェックボックスだけでは済みません。
2 つ目は電話のダイヤルインです。電話回線を会議に接続するには、48 kHz の Opus を、通常は 8 kHz の G.711 など、電話網が受け付ける形式に変換する必要があります。変換は双方向で、通話中は継続的に行われます。音声のトランスコードは映像より大幅に低コストですが、通話レッグごとに実行され、停止することがありません。そのため、コストは発信者数に応じて増加します。ダイヤルイン番号が必要な場合、セルフホスト型 VoIP サーバーがこの処理を担うコンポーネントです。Jibri と同じ理由で、専用のマシンで運用してください。
実際に必要なサーバーの規模はどの程度か
2 人で使うなら、ほとんど必要ありません。Jitsi は参加者がちょうど 2 人の場合、デフォルトで peer to peer モードを有効にします。このモードでは、カンファレンスのデータを videobridge 経由で送信せず、直接接続を使用します。直接接続できない場合は TURN relay を使用します。3 人目が参加すると、bridge 経由に戻ります。そのため、Jitsi を実行する 1 GB VPS は 1 対 1 の通話サーバーとしては十分ですが、4 人での利用には不向きです。「テストしたときは動いた」という報告が多いのはこのためです。
カメラを有効にした参加者が最大で約 10 人の場合、8 人参加時の 67.2 Mbps は、一般的な VPS の uplink で維持できる範囲です。録画しないのであれば、2 仮想 CPU と 4 GB で、その規模の Jitsi または Galène を実行できます。CPU グラフではなく、転送量カウンターを監視してください。
30 人の場合、最悪時の継続的な転送量は 1,044 Mbps で、これを 20 時間続けると 9.4 TB になります。この規模では、サーバーの料金より先に帯域幅の料金を見積もります。last-N を有効にして、bridge が直近の発話者だけを転送するようにします。参加者のカメラをデフォルトでオフにし、計算上必要な転送量を許容できる転送枠のある場所に SFU を配置します。
それを超える場合、1 台の VPS では構成が適切ではありません。イベントの実態がブロードキャストであれば、Owncast と CDN の組み合わせで、この構成の何分の 1 かの費用に抑えられます。そうでなければ、単一の signalling layer の背後に複数の videobridge が必要です。これは、最初に始めたものとは別のプロジェクトになります。
最後に、トラフィックの振り分けについて説明します。多くのチームでは、ビデオを必要とする時間よりもチャットを必要とする時間のほうがはるかに長くなります。チャットはホスティング費用が安く、運用も容易です。日常の通信には セルフホスト型の Slack 代替サービス を用意し、予定された通話だけにカンファレンスサーバーを使用する構成が、小規模な VPS の予算でも無理なく維持できます。
FAQ
Jitsi の会議には参加できるのに、参加者同士で映像や音声を確認できないのはなぜですか?
チャットと参加者一覧は TCP の 443 を使うシグナリングチャネルを経由します。一方、音声と映像は UDP の 10000 を使って videobridge に送信されます。参加者一覧が埋まり、すべてのタイルが黒いままなら、シグナリング経路は正常ですが、メディア経路に問題があります。ホスト上のファイアウォールと、プロバイダーのコントロールパネルにある別のネットワークファイアウォールの両方で、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 ランタイムはいずれもメモリを必要とします。handbook で通常推奨されている容量は 8 GB です。また、メモリ不足より先に帯域幅の計算が問題になる可能性があります。1 GB のホストしかない場合は、その容量では Jitsi より Galène のほうが適しています。
VPS にパブリック IP アドレスがある場合でも、TURN サーバーは必要ですか?
はい。TURN が解決する問題は、通話相手側で発生するためです。送信 UDP をブロックする企業ネットワーク上の参加者や、宛先ごとに異なる送信元ポートを割り当てる carrier-grade NAT の背後にいる参加者は、サーバーのアドレスがパブリックであっても、直接のメディア経路を構築できません。443 または 5349 上の TCP による TURN は、ファイアウォールから通常の Web トラフィックに見えるリレーを提供します。Jitsi のパッケージインストールでは、デフォルトで coturn が設定されます。そのため、ドキュメントに記載されたファイアウォールルールでは UDP 3478 と TCP 5349 が開かれています。
BigBlueButton には、Jitsi Meet よりはるかに多くのハードウェアが必要なのはなぜですか?
映像を転送するだけでなく、より多くの処理を行うためです。BigBlueButton の公開されている本番要件は 16 GB の RAM と 8 コアです。これに対し、Jitsi の handbook では 8 GB と 4 コアが必要とされています。BigBlueButton は、完全な音声会議スタック、共有ホワイトボードとプレゼンテーション層、録画と後処理のパイプライン、ユーザーアカウントを備えた Web フロントエンドを、すべて同じマシン上で実行します。また、対応プラットフォームも限定されています。2026 年 10 月時点で、対応するインストールは Ubuntu 22.04 上の version 3.0 です。どちらの数値も各プロジェクトの公式ドキュメントに基づく開始点であり、実際のワークロードを測定した値ではありません。