Tự host video conference trên VPS: Tính băng thông
Tính băng thông theo số người trước khi chọn VPS, rồi đối chiếu Jitsi, BigBlueButton và Galène về RAM, UDP cần mở và lỗi NAT thường gặp.
Tự host video conferencing trên VPS là bài toán băng thông
Video conferencing tự host thất bại trên các server nhỏ vì một lý do, và gần như không bao giờ là do quá trình cài đặt. Thành phần server mà mọi công cụ hiện đại đều sử dụng là SFU (selective forwarding unit). SFU nhận một video stream từ mỗi người tham gia rồi chuyển tiếp một bản sao đến tất cả những người tham gia khác, nên traffic rời server tăng theo bình phương số người. VPS 1 GB hoặc 2 GB trên uplink dùng chung vẫn chạy phần mềm bình thường. Nhưng nó không thể tải nổi buổi họp toàn công ty mà bạn đang hình dung.
Vì vậy, hãy thực hiện theo thứ tự này. Đếm số người, tính số megabit cần dùng, rồi chọn server. Cài đặt chỉ mất hai mươi phút copy và paste. Uplink mới quyết định liệu mọi người có nghe được bạn hay không.
Băng thông tăng theo bình phương số người tham gia vì sao?
Hãy bắt đầu với mesh. Mỗi trình duyệt mã hóa camera của mình rồi gửi trực tiếp một bản sao đến từng trình duyệt khác; không có media server nào xử lý video. Một cuộc gọi mesh hai người chỉ cần signalling server, không cần gì khác. Vì vậy, chi phí host cuộc gọi một-một gần như bằng 0. Mesh không còn hiệu quả khi có khoảng bốn hoặc năm người, vì laptop dùng kết nối gia đình phải upload đồng thời bốn hoặc năm bản sao riêng của video từ chính nó.
SFU hoạt động khác. Mỗi trình duyệt upload một bản sao lên server. Server đọc header RTP (real-time transport protocol), rồi forward các packet đó đến những người tham gia khác mà không decode video. Đó là toàn bộ cơ chế, và cũng là lý do SFU nhẹ về CPU nhưng nặng về network.
Mô hình cũ hơn là MCU (multipoint control unit). Nó decode mọi stream đến, ghép chúng thành một hình ảnh rồi encode lại hình ảnh đó. Băng thông outbound rất thấp. Chi phí CPU cực lớn. Hiện nay gần như không có hệ thống nào dùng MCU cho video, và guide này cũng không dùng.
Bây giờ tính toán cho một SFU. Giả sử mỗi người gửi video ở tốc độ 1.2 Mbps và không ai tắt camera. Server nhận N lần 1.2 Mbps. Mức này tăng tuyến tính và không đáng lo. Server gửi N lần (N trừ 1) lần 1.2 Mbps, vì mỗi người trong số N người phải nhận N trừ 1 stream còn lại. Chính con số thứ hai này thường khiến các dự án phải dừng lại.
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
}
]Các dòng trên là phép tính, không phải số đo của một server cụ thể nào. Cột theo tháng giả định có hai mươi giờ gọi trong một tháng. Hãy đọc dòng cuối trước. Năm mươi người bật camera cần 2,940 Mbps lưu lượng outbound liên tục từ một máy duy nhất. Ba mươi người cần 1,044 Mbps. Bốn người cần 14.4 Mbps; bất kỳ VPS nào cũng xử lý được mà hầu như không nhận thấy tải. Từ dòng bốn người đến dòng ba mươi người, số người tăng gấp bảy phẩy năm lần, trong khi lưu lượng outbound tăng hơn bảy mươi lần.
Các deployment thực tế thường thấp hơn những con số này. Bạn cần biết chính xác lý do. Jitsi và LiveKit đều dùng simulcast: sender publish nhiều quality layer cùng lúc, còn SFU forward layer thấp cho những người không nằm trên màn hình. Jitsi cũng có setting last-N, chỉ forward video của những speaker gần đây nhất. Cả hai cách đều tiết kiệm rất nhiều traffic. Nhưng không cách nào thay đổi dạng của đường cong. Cả hai cũng không còn giúp được gì ngay khi mọi người bật camera và pin video của nhau.
VPS uplink thực sự cung cấp cho bạn điều gì?
Trang gói dịch vụ ghi “cổng 1 Gbps”. Đây là tốc độ của card mạng ảo, không phải cam kết về hop tiếp theo. Đường truyền được chia sẻ với các tenant khác trên cùng máy chủ vật lý, nên throughput duy trì trong giờ cao điểm sẽ thấp hơn tốc độ cổng. Cuộc gọi hội nghị chính là một tải duy trì như vậy. Hầu hết gói dịch vụ cũng có hạn mức transfer hằng tháng. Sau khi vượt hạn mức, bạn sẽ bị throttle hoặc tính phí.
Hạn mức đó thường là khoản tăng bất ngờ trên hóa đơn. Trong một tháng, 20 giờ cuộc gọi 30 người sẽ truyền 9.4 TB ra khỏi server, với tốc độ 469.8 GB mỗi giờ. 20 giờ cuộc gọi 50 người sẽ truyền 26.5 TB. Hãy kiểm tra hạn mức transfer trước khi kiểm tra dung lượng RAM. Nếu trang gói dịch vụ mô tả mơ hồ về hạn mức này, chính sự mơ hồ đó đã là câu trả lời. Đọc đúng một gói VPS giá rẻ quan trọng với workload này hơn hầu hết các workload khác.
Jitsi Meet: lựa chọn mặc định và các yêu cầu
Jitsi Meet là lựa chọn mà hầu hết mọi người nên bắt đầu. Phần mềm cài đặt từ Debian repository của dự án, tự cấu hình nginx và certificate trong quá trình cài đặt, còn videobridge (JVB) chỉ dùng một UDP port nên firewall rule rất ngắn. Phần mềm cần Debian 11 trở lên hoặc Ubuntu 22.04 trở lên.
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-meetTrình cài đặt yêu cầu hostname rồi đưa ra lựa chọn certificate. Hãy chọn tùy chọn Let's Encrypt và cung cấp domain name đã phân giải đến public address của server này. Certificate được cấp thông qua HTTP challenge, nên nếu hostname trỏ đến nơi khác thì bước này sẽ thất bại.
Sau đó mở các port. Đây là các port được handbook ghi rõ; hãy đặt SSH lên trước để ufw enable không khóa bạn khỏi server:
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 và 443 phục vụ web app và cho phép gia hạn certificate. UDP 10000 truyền toàn bộ audio và video; đây là port mọi người thường quên. UDP 3478 và TCP 5349 thuộc về coturn server mà Jitsi package cài cùng bridge. Đây là đường dự phòng cho những người dùng có network chặn UDP.
sudo systemctl status jitsi-videobridge2
sudo ss -ulnp | grep 10000Lệnh đầu tiên phải báo service đang active. Lệnh thứ hai phải hiển thị bridge đang listen trên UDP 10000. Nếu không in ra gì, bridge chưa khởi động và /var/log/jitsi/jvb.log sẽ cho biết nguyên nhân.
Về sizing, handbook của Jitsi công bố một mức khởi điểm riêng, còn BigBlueButton công bố mức lớn hơn nhiều:
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
}
]Handbook của Jitsi đề xuất 8 GB RAM và 4 core chuyên dụng cho một server vận hành nghiêm túc; network 1,000 Mbps thường là đủ. Tài liệu cũng ghi nhận rằng các setup nhỏ hơn có thể chạy với 4 GB hoặc 2 GB. Có một chi tiết đáng lưu ý trên trang đó: Prosody, XMPP server xử lý signalling, chỉ có thể dùng một core. Các core bổ sung giúp bridge nhưng không giúp xử lý signalling.
Vì sao mọi người đều tham gia cuộc gọi nhưng không ai thấy video?
Đây là lỗi Jitsi thường gặp trên VPS. Danh sách người tham gia hiển thị đầy đủ, chat hoạt động, nhưng mọi ô video đều màu đen. Videobridge quảng bá các địa chỉ mà nó tìm thấy trên những interface của chính nó. Với nhà cung cấp cấp cho máy ảo một địa chỉ private rồi ánh xạ một địa chỉ public vào đó, JVB chỉ tìm thấy địa chỉ private. Vì vậy, mọi client đều cố gửi media đến địa chỉ như 10.0.0.5, nhưng packet không đi đến đâu.
Hãy khai báo cả hai địa chỉ cho bridge. Thêm static mapping vào /etc/jitsi/videobridge/jvb.conf:
ice4j {
harvest {
mapping {
static-mappings = [
{
local-address = "10.0.0.5"
public-address = "203.0.113.10"
}
]
}
}
}Khởi động lại bằng sudo systemctl restart jitsi-videobridge2. Lấy địa chỉ local từ ip -4 addr show và địa chỉ public từ control panel của nhà cung cấp. Các guide cũ cấu hình cùng nội dung trong /etc/jitsi/videobridge/sip-communicator.properties bằng các key org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS và org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS. Các key này vẫn hoạt động, nhưng cài đặt mới nên dùng block mapping ở trên.
Nguyên nhân còn lại là firewall bạn chưa cấu hình. Hầu hết nhà cung cấp có network firewall trong control panel, tách biệt với ufw trên máy chủ. UDP 10000 phải được mở ở cả hai nơi. Để xác định layer nào đang drop packet, chạy sudo tcpdump -ni any udp port 10000 trên server trong khi có người từ bên ngoài tham gia. Nếu không có packet nào đến, nghĩa là packet chưa tới máy chủ và block nằm phía trước operating system. Nếu packet vẫn đến nhưng các ô video vẫn màu đen, bridge đang trả về một địa chỉ mà client không thể truy cập. Khi đó, lỗi nằm ở mapping. Nếu bạn chưa chắc phần ufw, các rule ufw mà một VPS thực sự cần giải thích thứ tự rule thường gây nhầm lẫn.
BigBlueButton: nặng, có nhiều cấu hình cố định và cần toàn bộ máy chủ
BigBlueButton được thiết kế cho việc giảng dạy. Nó có whiteboard, breakout room, poll và khu vực trình chiếu. Pipeline ghi hình là tính năng chính thức, không phải add-on. Đây cũng là lựa chọn nặng nhất trong các phương án ở đây với chênh lệch lớn. Bạn không cài nó như một package bổ sung vào server hiện có.
Tính đến tháng 8 năm 2026, phương án được hỗ trợ là BigBlueButton 3.0 trên Ubuntu 22.04, được chọn bằng version flag jammy-300. Yêu cầu production do dự án công bố là 16 GB memory với swap được bật, 8 CPU core có hiệu năng single-thread cao, 250 Mbps băng thông đối xứng và 500 GB disk nếu bạn giữ recording (50 GB nếu bạn tắt recording). Các port cần mở là TCP 80 và 443, cùng với dải UDP từ 16384 đến 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 -gCác ví dụ của dự án pipe script đó trực tiếp vào bash. Thay vào đó, hãy download và đọc script trước. Script này ghi đè cấu hình nginx, cài stack media và audio riêng, ghim version của package và nhận hostname. Đây là thiết kế của BigBlueButton, không phải lỗi: BigBlueButton cần toàn quyền quản lý máy. Flag -w cấu hình firewall, -s là hostname, -e là địa chỉ mà Let's Encrypt đăng ký, còn -g thêm frontend Greenlight. Nếu cùng một máy cũng thực hiện TLS termination cho các service khác, hãy chuyển BigBlueButton sang máy khác hoặc chắc chắn bạn hiểu cấu hình nginx reverse proxy đang hoạt động như thế nào trước khi script chỉnh sửa nó.
Hãy so sánh kỹ hai dòng trong biểu đồ đó. BigBlueButton yêu cầu gấp đôi memory và gấp đôi số core so với đề xuất của Jitsi, nhưng chỉ yêu cầu một phần tư băng thông. Hai con số này không được đo theo cùng một cách và giả định room có kích thước khác nhau. Vì vậy, hãy xem mỗi con số là điểm bắt đầu riêng của dự án tương ứng, không phải phép so sánh trực tiếp. Chênh lệch về CPU là có thật. Nguyên nhân là BigBlueButton còn thực hiện nhiều tác vụ khác ngoài việc forward video.
Galène: lựa chọn gọn nhẹ
Galène là một SFU nhỏ gọn được viết bằng Go. Phần mềm biên dịch thành một binary static duy nhất, tích hợp sẵn web client và có TURN server, nên không cần duy trì XMPP server, Java runtime hoặc Rails application. Nếu yêu cầu của bạn chỉ là một cuộc gọi ổn định với 10 người trên một máy có cấu hình vừa phải, hãy thử Galène trước khi kết luận rằng bạn cần thêm phần cứng.
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 groupsGói golang-go trên Ubuntu 24.04 là Go 1.22. Nếu go build báo module cần phiên bản Go mới hơn, hãy cài toolchain hiện tại từ go.dev thay vì cố dùng gói của distribution.
Group là cách Galène gọi một room, và mỗi group là một file JSON:
echo '{"users": {"vimes": {"password":"sybil", "permissions":"op"}}}' > groups/night-watch.json
./galene &Mở https://your.server:8443/group/night-watch/ và đăng nhập bằng vimes. Thông tin đăng nhập này lấy trực tiếp từ README của project, vì vậy hãy đổi chúng trước khi cổng được truy cập từ nơi khác. Với deployment thực tế, project có tài liệu về 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.targetCác cổng gồm TCP 8443 cho web interface, TCP và UDP 1194 cho TURN server tích hợp sẵn, cùng một dải cổng UDP cao dành cho media. Hãy cố định dải cổng đó để bạn có thể viết một firewall rule cho nó:
./galene -udp-range 40000-40100Tùy chọn -turn là tùy chọn quan trọng trên VPS. -turn ':1194' lắng nghe trên tất cả địa chỉ IPv4 public. -turn '203.0.113.1:1194' cho Galène biết địa chỉ mà client thực sự nhìn thấy. Bạn cần tùy chọn này khi địa chỉ của máy là private. -turn '' tắt server tích hợp sẵn để bạn trỏ đến một server bên ngoài thông qua data/ice-servers.json. Giá trị mặc định là auto. Giá trị này hoạt động giống :1194 khi không có ice-servers.json.
Bạn có thể đặt nginx phía trước web interface bằng cách cấu hình proxyURL trong data/config.json, rồi proxy location /ws với các header nâng cấp WebSocket. Cần hiểu rõ phạm vi của cấu hình này: client vẫn mở các luồng UDP trực tiếp và các kết nối TCP trực tiếp đến cổng TURN, nên reverse proxy chỉ xử lý page và signalling. Media không đi qua reverse proxy.
Tài liệu Galène cho biết phần mềm cần tài nguyên server rất vừa phải nhưng không đưa ra con số cụ thể, vì vậy đừng chờ một con số cố định. Các phép tính bandwidth ở trên vẫn áp dụng đầy đủ. Phần bạn tiết kiệm được là memory và các thành phần không cần thiết ngoài SFU.
Owncast: một đến nhiều, băng thông tăng tuyến tính
Nhiều yêu cầu về “hội nghị video” thực chất là một người trình bày cho khán giả, còn khán giả nhập nội dung trong chat. Nếu nhu cầu của bạn là như vậy, SFU là công cụ không phù hợp và bài toán chi phí thay đổi hoàn toàn. Owncast nhận stream RTMP từ OBS hoặc encoder tương tự, rồi phân phối HLS qua HTTPS thông thường. Băng thông trên mỗi viewer tăng tuyến tính thay vì theo cấp số nhân, và vì output là các HTTP segment thông thường, bạn có thể đưa chúng qua object storage hoặc CDN để không phải tiếp tục trả chi phí cho origin.
curl -sL https://owncast.online/install.sh -o install-owncast.sh
less install-owncast.sh
bash install-owncast.shTài liệu của dự án yêu cầu không chạy công cụ này bằng root và phải kiểm tra mọi remote script trước khi thực thi. Vì vậy, bước download được tách riêng ở trên. Installer tải release hiện tại và binary ffmpeg nếu máy chưa có. Chạy ./owncast từ install directory, rồi mở admin panel tại /admin trên port 8080. Login mặc định là user admin, còn stream key mặc định abc123 được dùng làm password. Hãy đổi password này trước khi trỏ domain vào server.
Thiết kế HLS dẫn đến 2 hệ quả. Viewer bị trễ vài giây hoặc vài phút so với live vì HLS phân phối toàn bộ segment, nên không thể trò chuyện hai chiều theo thời gian thực. Ngoài ra, đường truyền không sử dụng UDP hoặc TURN ở bất kỳ vị trí nào. Vì vậy, Owncast vẫn đến được những network mà cuộc gọi WebRTC hoàn toàn không thể kết nối.
Owncast cũng là tool duy nhất ở đây chủ động thực hiện transcoding. Mỗi output quality bạn bật sẽ tạo thêm một lần encode bằng ffmpeg cho stream đầu vào, chạy trong suốt thời gian broadcast. Trên một VPS nhỏ, chỉ nên cung cấp 1 hoặc 2 quality. Nếu cung cấp 5 quality, CPU sẽ bị sử dụng hết trong khi network vẫn nhàn rỗi.
Element Call trên Matrix server đang chạy
Nếu bạn đã vận hành Matrix, video chỉ là một phần bổ sung thay vì một sản phẩm thứ hai cần quản lý. Tuy nhiên, đây vẫn là nhiều hơn một package. Element Call cần 2 thành phần phía sau homeserver. Thành phần đầu tiên là LiveKit SFU, dùng để chuyển tiếp media. Thành phần thứ hai là MatrixRTC authorisation service, element-hq/lk-jwt-service, cung cấp cho client URL WebSocket của LiveKit và một JWT đã ký (JSON web token) để kết nối. Service này dùng Matrix federation API, nên cần có TLS reverse proxy phía trước và một hostname mà federation có thể truy cập.
Các port được LiveKit tài liệu hóa:
- TCP 7880 cho API và WebSocket của client, phía sau proxy thực hiện TLS termination
- TCP 7881 cho ICE over TCP, dùng khi client không thể đi ra ngoài qua UDP
- UDP 50000 đến 60000 cho media; mỗi participant trong một room dùng 2 port
- UDP 3478 và TCP 5349 nếu bật embedded TURN server; port 5349 phải chuyển sang 443 trừ khi có load balancer đứng phía trước
Việc mỗi participant dùng 2 port nghe có vẻ đáng lo nhưng thực tế không phải vậy. Dải 10,000 port đủ cho hàng nghìn participant, và uplink của bạn sẽ hết băng thông từ lâu trước khi dải port này được dùng hết. Dù vậy, hãy mở toàn bộ dải port. Nếu chỉ mở một phần, kết nối sẽ fail với một số người nhưng vẫn hoạt động với những người khác. Đây là loại lỗi khó debug nhất. Phần homeserver là một công việc riêng, được trình bày trong vận hành Synapse homeserver trên VPS.
Một người không thể kết nối bao giờ? TURN và các mạng chặn UDP
Trước tiên là một số thuật ngữ, mỗi thuật ngữ chỉ dùng một lần. ICE (interactive connectivity establishment) là quy trình mà 2 endpoint WebRTC dùng để tìm một đường truyền hoạt động giữa chúng. STUN (session traversal utilities for NAT) là một service nhỏ cho client biết địa chỉ public của chính nó khi nhìn từ bên ngoài. TURN (traversal using relays around NAT) là một relay: khi không có đường truyền trực tiếp, cả 2 phía gửi media đến TURN server và server chuyển tiếp dữ liệu.
Bạn cần TURN cho những participant mà bạn không kiểm soát được network. Một participant có thể đang ở corporate network hoặc campus network chặn hoàn toàn UDP outbound. Participant khác có thể đứng sau carrier-grade NAT, nơi cấp một source port khác cho từng đích. Trường hợp này gọi là symmetric NAT và khiến địa chỉ mà STUN báo lại trở nên vô dụng.
Triệu chứng khá cụ thể. Hầu hết mọi người join và mọi thứ hoạt động bình thường. Một người thấy danh sách participant, thấy chat, nhưng chỉ thấy tile màu đen và spinner. Browser của họ đã thu thập candidates, nhưng không cặp nào hoạt động và ICE kết thúc ở trạng thái failed. Trong Chrome, chrome://webrtc-internals mở trong lúc thử kết nối sẽ hiển thị các candidate pair và lỗi đó. Hãy yêu cầu người này thử lại bằng điện thoại dùng mobile data. Nếu kết nối hoạt động khi đó, network của họ là nguyên nhân và TURN là cách khắc phục.
TURN qua TCP trên 443 hoặc 5349 là fallback hoạt động gần như ở mọi nơi, vì network chặn TLS trên 443 cũng đã chặn web. Package của Jitsi cài đặt và cấu hình coturn cho bạn. Đây là lý do các firewall rule được tài liệu hóa của Jitsi có UDP 3478 và TCP 5349. Galène tích hợp sẵn TURN trên 1194. LiveKit có TURN server tích hợp, bạn chỉ cần bật trong config. Nếu tự chạy 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-peersCác thiết lập đó nằm trong /etc/turnserver.conf. Trên Debian và Ubuntu, package khởi động coturn ngay khi cài đặt, với phiên bản mặc định của file đó. Vì vậy, enable --now ở trên sẽ thấy coturn đã chạy và không thay đổi gì. Các thiết lập của bạn có hiệu lực khi chạy sudo systemctl restart coturn. Mọi lần chỉnh sửa file sau đó cũng cần restart tương tự. Các hướng dẫn cũ còn yêu cầu đặt TURNSERVER_ENABLED=1 trong /etc/default/coturn. Chỉ init script cũ mới đọc tùy chọn đó. systemd unit mà các package hiện tại chạy không đọc tùy chọn này. Vì vậy, dòng đó không thay đổi gì, và coturn chưa được restart vẫn đang dùng file mặc định.
Bây giờ là chi phí thường không được ghi rõ. Một relay chuyển tiếp toàn bộ media của mỗi participant được relay theo cả 2 chiều. Khi coturn dùng chung máy với SFU, phần lớn traffic đi qua loopback và tiêu tốn CPU thay vì uplink. TLS listener cũng mã hóa từng packet thêm một lần, bên cạnh DTLS mà media đã sử dụng. Khi chuyển TURN sang máy riêng, máy đó cần bandwidth plan có dung lượng được tính theo cách tương tự bandwidth plan của SFU. TURN qua TCP biến media real-time thành một reliable stream. Vì vậy, packet bị mất sẽ được retransmit thay vì bỏ qua. Participant được relay trên một link không ổn định sẽ tích lũy delay thay vì chỉ gặp một glitch ngắn. Relay là fallback giúp kết nối được, nhưng chất lượng sẽ kém hơn đường truyền trực tiếp.
Khi nào SFU transcode và chi phí là bao nhiêu?
SFU chuyển tiếp packet và không bao giờ decode video. Vì vậy, 4 core vẫn có thể phục vụ một room mà trên lý thuyết có vẻ vượt quá khả năng. Có 2 tính năng phá vỡ đặc điểm này. Cả hai đều thường khiến người bật chúng chỉ bằng một checkbox bất ngờ.
Tính năng đầu tiên là recording. Jitsi ghi hình bằng Jibri. Tài liệu của Jibri mô tả chính xác cách nó hoạt động: Jibri khởi chạy một instance Chrome được render trong virtual framebuffer, sau đó capture và encode output bằng ffmpeg. Đây là một trình duyệt hoàn chỉnh render toàn bộ meeting, kèm theo một video encoder, chạy liên tục trong suốt thời lượng cuộc gọi. Tài liệu cũng nêu rõ rằng một Jibri chỉ hỗ trợ 1 recording tại một thời điểm. Jibri được thiết kế để chạy trên một máy hoặc virtual machine riêng, không có ứng dụng nào khác sử dụng display hoặc audio device. Recording cần một server thứ hai, không phải chỉ bật một checkbox.
Tính năng thứ hai là telephone dial-in. Việc nối một đường điện thoại vào conference yêu cầu chuyển đổi Opus ở 48 kHz sang định dạng mà mạng điện thoại chấp nhận, thường là G.711 ở 8 kHz, theo cả hai chiều và liên tục trong suốt cuộc gọi. Audio transcoding rẻ hơn nhiều so với video transcoding, nhưng nó chạy cho từng call leg và không bao giờ tạm dừng. Vì vậy, chi phí tăng theo số caller. Nếu cần một số dial-in, VoIP server tự host là component thực hiện công việc này. Component đó nên chạy trên một máy riêng, cũng vì lý do giống Jibri.
Bạn thực sự cần máy chủ lớn đến mức nào?
Với 2 người, gần như không cần tài nguyên đáng kể. Jitsi mặc định bật chế độ peer to peer khi có đúng 2 người tham gia. Ở chế độ này, conference không gửi dữ liệu qua videobridge mà dùng kết nối trực tiếp. Khi người thứ 3 tham gia, Jitsi chuyển lại sang bridge. Vì vậy, VPS 1 GB chạy Jitsi phù hợp cho cuộc gọi 1-1 nhưng không phù hợp cho cuộc gọi 4 người. Đây là lý do câu “tôi test thì chạy” xuất hiện rất thường xuyên.
Với tối đa khoảng 10 người bật camera, 67.2 Mbps ở 8 người tham gia vẫn nằm trong khả năng duy trì của uplink trên VPS thông thường. 2 vCPU và 4 GB có thể chạy Jitsi hoặc Galène ở quy mô này, miễn là bạn không recording. Hãy theo dõi bộ đếm transfer thay vì biểu đồ CPU.
Với 30 người, trường hợp xấu nhất là 1,044 Mbps liên tục, và 20 giờ ở mức đó tương đương 9.4 TB. Đây là quy mô mà bạn cần tính chi phí bandwidth trước khi tính chi phí máy chủ. Bật last-N để bridge chỉ forward những speaker gần đây, đặt camera-off làm mặc định cho attendee, và đặt SFU ở nơi có transfer allowance đủ đáp ứng phép tính này.
Lớn hơn mức đó, chỉ dùng 1 VPS là không phù hợp. Hoặc sự kiện thực chất là broadcast, khi đó Owncast kết hợp với CDN chỉ tốn một phần chi phí này; hoặc bạn cần nhiều videobridge phía sau một lớp signalling duy nhất. Đây là một dự án khác với hệ thống ban đầu của bạn.
Còn một điểm về routing. Hầu hết team cần chat nhiều giờ trong ngày hơn nhiều so với video. Chat cũng rẻ và dễ duy trì hơn. Dựng một alternative cho Slack tự host để phục vụ lưu lượng hằng ngày, rồi chỉ dùng conferencing server cho các cuộc gọi đã lên lịch, là phương án có thể duy trì với ngân sách VPS nhỏ.
FAQ
Vì sao mọi người có thể tham gia cuộc họp Jitsi nhưng không nghe hoặc thấy nhau?
Chat và danh sách người tham gia đi qua kênh signalling trên TCP 443, còn audio và video dùng UDP 10000 đến videobridge. Nếu danh sách người tham gia hiển thị đầy đủ nhưng mọi ô video đều màu đen, đường truyền media bị lỗi trong khi đường truyền signalling vẫn hoạt động. Hãy kiểm tra UDP 10000 trên cả hai firewall: firewall trên máy chủ và network firewall riêng trong control panel của nhà cung cấp. Sau đó kiểm tra bridge đã biết địa chỉ public của nó chưa: trên virtual machine có địa chỉ private và địa chỉ public được mapping, hãy thêm mapping tĩnh trong ice4j.harvest.mapping của /etc/jitsi/videobridge/jvb.conf rồi restart jitsi-videobridge2. Chạy sudo tcpdump -ni any udp port 10000 trong lúc có người tham gia sẽ cho biết lỗi nằm ở đâu, vì hoàn toàn không có packet nào nghĩa là block xảy ra ở upstream, trước hệ điều hành.
Một cuộc gọi video 30 người dùng bao nhiêu bandwidth?
Trong trường hợp xấu nhất, khi mọi người đều bật camera và SFU chuyển tiếp một layer chất lượng đầy đủ cho tất cả người tham gia, khoảng 1,044 Mbps rời khỏi server, tương đương 469.8 GB mỗi giờ. Đây là phép tính từ N lần (N trừ 1) stream ở mức 1.2 Mbps mỗi stream, không phải số đo từ hệ thống của bạn. Simulcast và thiết lập last-N làm giảm đáng kể mức sử dụng trong điều kiện bình thường, vì phần lớn người tham gia không xuất hiện trên màn hình tại cùng một thời điểm. Dù vậy, hãy sizing gần với trường hợp xấu nhất, vì trường hợp xấu nhất là lúc họp toàn bộ và mọi người cùng bật camera.
Tôi có thể chạy Jitsi Meet trên VPS 1 GB không?
Jitsi sẽ cài được và cuộc gọi 2 người sẽ hoạt động, một phần vì Jitsi dùng chế độ peer to peer khi có đúng 2 người tham gia nên bỏ qua videobridge hoàn toàn. Đây không phải server phù hợp cho cuộc gọi nhóm. Prosody, videobridge và Java runtime đều cần memory; handbook của dự án khuyến nghị 8 GB cho một deployment nghiêm túc, và phép tính bandwidth sẽ trở thành giới hạn trước memory. Nếu bạn chỉ có máy 1 GB, Galène phù hợp với cấu hình này hơn Jitsi.
VPS có public IP thì tôi còn cần TURN server không?
Có. Vấn đề mà TURN giải quyết nằm ở phía bên kia của cuộc gọi. Người tham gia trong corporate network chặn UDP outbound, hoặc ở sau carrier-grade NAT cấp một source port khác nhau cho từng đích đến, không thể tạo đường truyền media trực tiếp dù server của bạn có public address. TURN qua TCP trên 443 hoặc 5349 cung cấp cho họ một relay có hình thức giống web traffic thông thường đối với firewall của họ. Jitsi package install mặc định thiết lập coturn cho mục đích này, vì vậy các firewall rule được tài liệu hóa của Jitsi mở UDP 3478 và TCP 5349.
Vì sao BigBlueButton cần nhiều hardware hơn Jitsi Meet đến vậy?
Vì BigBlueButton làm nhiều việc hơn việc chuyển tiếp video. Yêu cầu production được công bố là 16 GB RAM và 8 core, trong khi handbook của Jitsi yêu cầu 8 GB và 4 core. BigBlueButton chạy full audio conferencing stack, shared whiteboard và presentation layer, pipeline recording và post-processing, cùng web front end có user account, tất cả trên cùng một máy. BigBlueButton cũng có yêu cầu cụ thể về platform: tính đến tháng 8 năm 2026, phiên bản được hỗ trợ để cài đặt là version 3.0 trên Ubuntu 22.04. Cả hai bộ số liệu đều lấy từ tài liệu riêng của từng dự án và chỉ là điểm bắt đầu, không phải số đo workload của bạn.