SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-09-28

راهنمای میزبانی ویدیو کنفرانس روی VPS و محاسبه پهنای باند

برای میزبانی Jitsi یا BigBlueButton روی VPS باید پهنای باند را با توان دوم شرکت‌کنندگان محاسبه کنید. این مطلب تفاوت مصرف RAM و چالش‌های NAT در SFU را بررسی می‌کند.

میزبانی سرویس کنفرانس ویدیویی روی VPS با چالش پهنای باند مواجه است

میزبانی شخصی سرویس‌های کنفرانس ویدیویی روی سرورهای کوچک به یک دلیل شکست می‌خورد و این دلیل تقریباً هرگز مربوط به مراحل نصب نیست. بخش اصلی سرور که تمام ابزارهای مدرن از آن استفاده می‌کنند، SFU (واحد انتخاب‌گر ارسال) است. این واحد یک استریم ویدیویی از هر شرکت‌کننده دریافت کرده و یک کپی از آن را برای تمام شرکت‌کنندگان دیگر ارسال می‌کند؛ بنابراین ترافیک خروجی از سرور با توان دوم تعداد افراد افزایش می‌یابد. یک VPS با 1 GB یا 2 GB رم روی یک uplink اشتراکی، نرم‌افزار را به‌خوبی اجرا می‌کند، اما توانایی پشتیبانی از جلسات گروهی بزرگی که در ذهن دارید را نخواهد داشت.

بنابراین کار را به این ترتیب انجام دهید: ابتدا تعداد افراد را بشمارید، میزان مگابیت مورد نیاز را محاسبه کنید و سپس سرور مناسب را انتخاب کنید. نصب نرم‌افزار تنها 20 دقیقه کپی و پیست کردن است، اما این uplink است که تعیین می‌کند آیا صدای شما به دیگران می‌رسد یا خیر.

چرا پهنای باند با توان دوم تعداد شرکت‌کنندگان رشد می‌کند؟

با مدل mesh شروع می‌کنیم. در این مدل، هر مرورگر تصویر دوربین را انکود کرده و یک نسخه را مستقیماً برای هر مرورگر دیگر می‌فرستد و هیچ سرور واسطی ویدیو را پردازش نمی‌کند. یک تماس دو نفره در مدل mesh تنها به یک سرور signalling نیاز دارد و به همین دلیل است که میزبانی تماس‌های یک‌به‌یک تقریباً رایگان است. مدل mesh در حدود چهار یا پنج نفر از کار می‌افتد، زیرا لپ‌تاپی که از اینترنت خانگی استفاده می‌کند، باید همزمان چهار یا پنج نسخه مجزا از ویدیوی خود را آپلود کند.

یک SFU متفاوت عمل می‌کند. هر مرورگر یک نسخه را به سرور آپلود می‌کند. سرور هدرهای RTP (پروتکل انتقال بلادرنگ) را می‌خواند و آن بسته‌ها را بدون دیکود کردن ویدیو، برای سایر شرکت‌کنندگان ارسال می‌کند. تمام ترفند کار همین است و به همین دلیل است که SFU فشار کمی به CPU وارد می‌کند اما پهنای باند شبکه زیادی مصرف می‌کند.

ساختار قدیمی‌تر، MCU (واحد کنترل چندنقطه‌ای) است. این واحد تمام استریم‌های ورودی را دیکود کرده، آن‌ها را در یک تصویر واحد ترکیب می‌کند و سپس آن تصویر را دوباره انکود می‌کند. پهنای باند خروجی در این حالت بسیار ناچیز است، اما هزینه CPU بسیار سنگین است. امروزه تقریباً هیچ‌چیز از MCU برای ویدیو استفاده نمی‌کند و هیچ‌کدام از ابزارهای این راهنما نیز از آن استفاده نمی‌کنند.

حال محاسبات مربوط به SFU را بررسی می‌کنیم. فرض کنید هر نفر ویدیو را با نرخ 1.2 Mbps ارسال می‌کند و هیچ‌کس دوربین خود را خاموش نکرده است. سرور N ضرب‌در 1.2 Mbps دریافت می‌کند که خطی و بی‌خطر است. سرور N ضرب‌در (N منهای 1) ضرب‌در 1.2 Mbps ارسال می‌کند، زیرا هر یک از N نفر باید N منهای 1 استریم دیگر را دریافت کنند. آن عدد دوم همان چیزی است که پروژه‌ها را با شکست مواجه می‌کند.

ChartSFU outbound traffic, arithmetic model at 1.2 Mbps per sender
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
  }
]

این ردیف‌ها محاسبات ریاضی هستند، نه اندازه‌گیری یک سرور خاص. ستون ماهانه فرض را بر 20 ساعت تماس در ماه گذاشته است. ابتدا ردیف آخر را بخوانید. پنجاه نفر با دوربین روشن به 2,940 Mbps ترافیک خروجی پایدار از یک ماشین واحد نیاز دارند. سی نفر به 1,044 Mbps نیاز دارند. چهار نفر به 14.4 Mbps نیاز دارند که هر VPS بدون هیچ مشکلی از پس آن برمی‌آید. بین ردیف چهار نفره و سی نفره، تعداد افراد 7.5 برابر می‌شود در حالی که ترافیک خروجی بیش از 70 برابر رشد می‌کند.

پیاده‌سازی‌های واقعی کمتر از این اعداد هستند و دانستن دلیل آن اهمیت دارد. Jitsi و LiveKit هر دو از simulcast استفاده می‌کنند: فرستنده چندین لایه کیفیتی را همزمان منتشر می‌کند و SFU لایه پایین‌تر را برای کسانی که در صفحه نیستند ارسال می‌کند. Jitsi همچنین تنظیماتی به نام last-N دارد که ویدیو را فقط برای آخرین سخنرانان ارسال می‌کند. هر دو روش ترافیک زیادی را صرفه‌جویی می‌کنند. هیچ‌کدام شکل منحنی رشد را تغییر نمی‌دهند و هر دو به محض اینکه همه دوربین خود را روشن کنند و تصویر یکدیگر را پین کنند، کارایی خود را از دست می‌دهند.

صفحهٔ مشخصات یک طرح، عبارت "1 Gbps port" را ذکر می‌کند. این سرعت کارت شبکه مجازی است، نه تعهدی برای گام بعدی شبکه (next hop). این لینک با سایر مستأجران روی همان میزبان فیزیکی مشترک است؛ بنابراین، نرخ انتقال داده پایدار در ساعات شلوغی کمتر از سرعت پورت خواهد بود و یک تماس کنفرانسی دقیقاً یک بارِ کاری پایدار محسوب می‌شود. اکثر طرح‌ها همچنین دارای یک سقف انتقال داده ماهانه هستند که پس از عبور از آن، سرعت شما محدود (throttle) شده یا مشمول هزینه اضافی می‌شوید.

آن سقف انتقال داده، همان جایی است که هزینه‌های غیرمنتظره در صورت‌حساب ظاهر می‌شوند. بیست ساعت تماس 30 نفره در یک ماه، مقدار 9.4 ترابایت داده را با نرخ 469.8 گیگابایت در ساعت از سرور خارج می‌کند. بیست ساعت تماس 50 نفره، 26.5 ترابایت داده جابه‌جا می‌کند. پیش از بررسی میزان RAM، سقف انتقال داده را چک کنید؛ اگر صفحهٔ طرح در این مورد مبهم است، همان ابهام پاسخ شماست. خواندن صحیح پیشنهادهای VPS ارزان برای این نوع بار کاری، بیش از هر کار دیگری اهمیت دارد.

Jitsi Meet: گزینه پیش‌فرض و نیازمندی‌های آن

Jitsi Meet گزینه‌ای است که اکثر افراد باید کار خود را با آن شروع کنند. این سرویس از مخزن Debian متعلق به خود پروژه نصب می‌شود، در حین نصب nginx و گواهی را پیکربندی می‌کند و videobridge (JVB) آن تنها از یک پورت UDP استفاده می‌کند که باعث می‌شود قوانین فایروال مختصر باقی بمانند. این سرویس به 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

نصب‌کننده از شما یک hostname می‌خواهد و سپس گزینه‌ای برای انتخاب گواهی ارائه می‌دهد. گزینه Let's Encrypt را انتخاب کنید و یک نام دامنه به آن بدهید که از قبل به آدرس عمومی این سرور اشاره می‌کند. گواهی از طریق چالش HTTP صادر می‌شود، بنابراین اگر نام دامنه به جای دیگری اشاره کند، این مرحله با شکست مواجه خواهد شد.

سپس پورت‌ها را باز کنید. این‌ها پورت‌هایی هستند که در کتابچه راهنما مستند شده‌اند؛ ابتدا SSH را باز کنید تا ufw enable باعث قفل شدن دسترسی شما نشود:

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 enable

پورت‌های TCP 80 و 443 برای سرویس‌دهی به برنامه وب و تمدید گواهی استفاده می‌شوند. پورت UDP 10000 تمام ترافیک صوتی و تصویری را منتقل می‌کند و همان پورتی است که معمولاً فراموش می‌شود. پورت‌های UDP 3478 و TCP 5349 متعلق به سرور coturn هستند که بسته Jitsi در کنار bridge نصب می‌کند؛ این مسیر جایگزین برای کسانی است که شبکه آن‌ها ترافیک UDP را مسدود کرده است.

sudo systemctl status jitsi-videobridge2
sudo ss -ulnp | grep 10000

دستور اول باید وضعیت سرویس را به عنوان active گزارش دهد. دستور دوم باید نشان دهد که bridge روی پورت UDP 10000 در حال گوش دادن است. اگر خروجی خالی بود، یعنی bridge شروع به کار نکرده است و /var/log/jitsi/jvb.log دلیل آن را بیان خواهد کرد.

برای تعیین ابعاد سرور، کتابچه راهنمای Jitsi نقطه شروع پیشنهادی خود را منتشر کرده و BigBlueButton نیز مقادیر بسیار بزرگ‌تری را پیشنهاد می‌دهد:

ChartSizing each project publishes for one production server
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 گیگابایت رم و 4 هسته پردازنده اختصاصی پیشنهاد می‌دهد و اشاره می‌کند که پهنای باند 1,000 مگابیت بر ثانیه اغلب کافی است؛ همچنین ذکر شده که تنظیمات کوچک‌تر روی 4 یا 2 گیگابایت رم نیز اجرا می‌شوند. یک نکته در آن صفحه ارزش به خاطر سپردن دارد: Prosody، سرور XMPP که مدیریت سیگنالینگ را بر عهده دارد، تنها می‌تواند از یک هسته استفاده کند. هسته‌های اضافی به bridge کمک می‌کنند اما تأثیری بر سیگنالینگ ندارند.

چرا همه به تماس ملحق می‌شوند اما کسی ویدیو را نمی‌بیند؟

این یک خطای استاندارد در Jitsi روی VPS است. لیست شرکت‌کنندگان پر می‌شود، چت کار می‌کند، اما تمام کادرهای ویدیو سیاه باقی می‌مانند. videobridge آدرس‌هایی را که روی رابط‌های شبکه خود پیدا می‌کند، تبلیغ می‌کند. در سرویس‌دهنده‌ای که یک آدرس خصوصی به ماشین مجازی اختصاص می‌دهد و یک آدرس عمومی را روی آن نگاشت (map) می‌کند، تنها آدرسی که JVB پیدا می‌کند همان آدرس خصوصی است؛ بنابراین هر کلاینت سعی می‌کند مدیا را به مقصدی مانند 10.0.0.5 بفرستد و بسته‌ها به هیچ‌جا نمی‌رسند.

هر دو آدرس را به bridge معرفی کنید. یک نگاشت ایستا (static mapping) به /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 انجام می‌دادند. آن روش‌ها همچنان کار می‌کنند، اما در نصب‌های جدید باید از بلوک نگاشت بالا استفاده کنید.

دلیل دیگر، فایروالی است که پیکربندی نکرده‌اید. اکثر سرویس‌دهنده‌ها یک فایروال شبکه در پنل مدیریت دارند که از ufw روی سیستم‌عامل مجزا است و پورت UDP 10000 باید در هر دو باز باشد. برای اینکه بفهمید کدام لایه بسته‌ها را مسدود می‌کند، در حالی که شخصی از خارج به تماس ملحق می‌شود، sudo tcpdump -ni any udp port 10000 را روی سرور اجرا کنید. اگر هیچ بسته‌ای دریافت نشد، یعنی چیزی به ماشین نمی‌رسد و مسدودسازی در لایه‌ای بالاتر از سیستم‌عامل انجام شده است. اگر بسته‌ها می‌رسند اما کادرها سیاه باقی می‌مانند، یعنی bridge با آدرسی پاسخ می‌دهد که کلاینت به آن دسترسی ندارد؛ پس مشکل از نگاشت است. اگر در مورد خود ufw مطمئن نیستید، قوانین ufw که یک VPS واقعاً به آن نیاز دارد ترتیب قوانینی را که معمولاً باعث ایجاد مشکل می‌شوند، توضیح می‌دهد.

BigBlueButton: سنگین، دارای ساختار مشخص و نیازمند کل سرور

BigBlueButton برای آموزش طراحی شده است. این سرویس دارای تخته‌سفید، اتاق‌های گروهی، نظرسنجی و بخش ارائه است و خط‌لوله ضبط آن یک قابلیت اصلی محسوب می‌شود، نه یک افزونه. این گزینه با اختلاف زیاد سنگین‌ترین گزینه در این لیست است و بسته‌ای نیست که بتوانید به یک سرور موجود اضافه کنید.

از اوت 2026، مسیر پشتیبانی‌شده، BigBlueButton 3.0 روی Ubuntu 22.04 است که با فلگ نسخه jammy-300 انتخاب می‌شود. نیازمندی‌های تولیدی اعلام‌شده توسط پروژه عبارتند از 16 گیگابایت حافظه با فعال بودن swap، 8 هسته CPU با عملکرد تک‌رشته‌ای بالا، 250 مگابیت بر ثانیه پهنای باند متقارن و 500 گیگابایت دیسک در صورت نگهداری ضبط‌ها (50 گیگابایت در صورت غیرفعال کردن آن‌ها). پورت‌های مورد نیاز 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 شما را بازنویسی می‌کند، استک رسانه و صوتی اختصاصی خود را نصب می‌کند، نسخه‌های بسته را پین می‌کند و نام میزبان (hostname) را تصاحب می‌کند. این یک نقص نیست، بلکه بخشی از طراحی است: BigBlueButton انتظار دارد مالک کل ماشین باشد. فلگ -w فایروال را پیکربندی می‌کند، -s نام میزبان است، -e آدرسی است که Let's Encrypt ثبت می‌کند و -g رابط کاربری Greenlight را اضافه می‌کند. اگر همان سرور وظیفه TLS termination برای سایر سرویس‌ها را نیز بر عهده دارد، یا BigBlueButton را به جای دیگری منتقل کنید یا پیش از آنکه اسکریپت پیکربندی را تغییر دهد، مطمئن شوید که عملکرد پیکربندی reverse proxy در nginx خود را درک کرده‌اید.

دو ردیف موجود در آن جدول را با دقت مقایسه کنید. BigBlueButton دو برابر حافظه و دو برابر هسته‌های پیشنهادی Jitsi را درخواست می‌کند، در حالی که یک‌چهارم پهنای باند را نیاز دارد. این دو عدد به روش یکسانی اندازه‌گیری نشده‌اند و فرض‌های متفاوتی برای اندازه اتاق‌ها دارند، بنابراین هر کدام را به عنوان نقطه شروع پروژه مربوط به خودش در نظر بگیرید، نه یک مقایسه مستقیم. شکاف CPU واقعی است و ناشی از تمام کارهایی است که BigBlueButton علاوه بر انتقال ویدیو انجام می‌دهد.

Galène: گزینه سبک

Galène یک SFU فشرده است که با زبان Go نوشته شده است. این برنامه به یک فایل اجرایی واحد و ایستا (static binary) کامپایل می‌شود، کلاینت وب اختصاصی خود را دارد و شامل یک سرور TURN است؛ بنابراین نیازی به سرور XMPP، محیط اجرای Java یا اپلیکیشن Rails برای نگهداری نیست. اگر نیاز شما یک تماس ده نفره قابل‌اطمینان روی یک سرور معمولی است، پیش از آنکه نتیجه بگیرید به سخت‌افزار قوی‌تری نیاز دارید، این گزینه را امتحان کنید.

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 groups

بسته golang-go در Ubuntu 24.04 شامل Go 1.22 است. اگر go build گزارش داد که ماژول به نسخه جدیدتری از Go نیاز دارد، به‌جای درگیری با بسته توزیع، یک toolchain به‌روز را از go.dev نصب کنید.

در ادبیات Galène، یک گروه (group) همان اتاق است و هر گروه در قالب یک فایل JSON تعریف می‌شود:

echo '{"users": {"vimes": {"password":"sybil", "permissions":"op"}}}' > groups/night-watch.json
./galene &

فایل https://your.server:8443/group/night-watch/ را باز کرده و با نام کاربری vimes وارد شوید. این اعتبارنامه‌ها مستقیماً از فایل README پروژه آمده‌اند، بنابراین پیش از آنکه پورت از هر جای دیگری در دسترس قرار گیرد، آن‌ها را تغییر دهید. برای یک استقرار واقعی، پروژه یک unit برای systemd ارائه می‌دهد:

[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

پورت‌های مورد نیاز عبارتند از TCP 8443 برای رابط وب، TCP و UDP 1194 برای سرور داخلی TURN، و بازه‌ای از پورت‌های UDP بالا برای رسانه. این بازه را محدود کنید تا بتوانید یک قانون فایروال واحد برای آن بنویسید:

./galene -udp-range 40000-40100

گزینه -turn در VPS اهمیت زیادی دارد. -turn ':1194' روی تمام آدرس‌های IPv4 عمومی گوش می‌دهد. -turn '203.0.113.1:1194' آدرسی را که کلاینت‌ها واقعاً می‌بینند به Galène اعلام می‌کند؛ این همان چیزی است که وقتی آدرس خودِ ماشین خصوصی (private) است، به آن نیاز دارید. -turn '' سرور داخلی را غیرفعال می‌کند تا بتوانید از طریق data/ice-servers.json به یک سرور خارجی اشاره کنید. مقدار پیش‌فرض auto است که در صورت عدم وجود ice-servers.json، مانند :1194 عمل می‌کند.

شما می‌توانید با تنظیم proxyURL در data/config.json و پروکسی کردن مسیر /ws با هدرهای ارتقای WebSocket، از nginx در مقابل رابط وب استفاده کنید. توجه داشته باشید که این کار چه چیزی را پوشش می‌دهد: کلاینت‌ها همچنان جریان‌های مستقیم UDP و اتصالات مستقیم TCP به پورت TURN برقرار می‌کنند، بنابراین reverse proxy فقط صفحه و سیگنالینگ را مدیریت می‌کند. ترافیک رسانه هرگز از آن عبور نمی‌کند.

مستندات Galène بیان می‌کند که این برنامه به منابع سرور بسیار کمی نیاز دارد و عدد خاصی را منتشر نمی‌کند، پس انتظار عدد مشخصی نداشته باشید. محاسبات پهنای باند که پیش‌تر ذکر شد، همچنان به‌طور کامل معتبر است. آنچه در اینجا صرفه‌جویی می‌کنید، حافظه و پیچیدگی‌های نگهداری تمام اجزایی است که بخشی از SFU نیستند.

Owncast: یک به چند، جایی که پهنای باند خطی باقی می‌ماند

بسیاری از نیازهای «کنفرانس ویدیویی» در واقع یک نفر است که برای مخاطبانی که در چت تایپ می‌کنند، ارائه می‌دهد. اگر نیاز شما این است، SFU ابزار اشتباهی است و صرفهٔ اقتصادی کاملاً تغییر می‌کند. Owncast یک استریم RTMP را از OBS یا یک انکودر مشابه دریافت کرده و آن را از طریق HTTPS معمولی به صورت HLS ارائه می‌دهد. پهنای باند به ازای هر بیننده به جای حالت درجه دوم، خطی است و چون خروجی شامل سگمنت‌های HTTP ساده است، می‌توانید آن را به پشت یک object storage یا CDN منتقل کنید و دیگر هزینه‌ای برای آن در مبدأ نپردازید.

curl -sL https://owncast.online/install.sh -o install-owncast.sh
less install-owncast.sh
bash install-owncast.sh

مستندات پروژه توصیه می‌کند که این برنامه را به عنوان root اجرا نکنید و هر اسکریپت راه دور را پیش از اجرا بررسی کنید؛ به همین دلیل دانلود در مرحلهٔ جداگانه‌ای در بالا انجام شد. نصب‌کننده، نسخهٔ فعلی و یک باینری ffmpeg را در صورتی که از قبل نداشته باشید، دریافت می‌کند. دستور ./owncast را از دایرکتوری نصب اجرا کنید و پنل مدیریت را در /admin روی پورت 8080 باز کنید. نام کاربری پیش‌فرض admin و رمز عبور پیش‌فرض همان stream key یعنی abc123 است. پیش از آنکه دامنه‌ای را به سرور متصل کنید، آن را تغییر دهید.

دو نتیجه از طراحی HLS حاصل می‌شود. بینندگان چند ثانیه یا چند دقیقه از پخش زنده عقب‌تر هستند، زیرا HLS سگمنت‌های کامل را ارسال می‌کند، بنابراین هیچ گفتگوی رفت و برگشتی وجود ندارد. همچنین هیچ UDP و هیچ TURN در مسیر وجود ندارد، بنابراین به شبکه‌هایی می‌رسد که یک تماس WebRTC اصلاً نمی‌تواند در آن‌ها متصل شود.

Owncast همچنین تنها ابزار در این لیست است که عمداً transcoding انجام می‌دهد. هر کیفیت خروجی که فعال می‌کنید، یک انکود ffmpeg دیگر از استریم ورودی است که به اندازهٔ طول پخش اجرا می‌شود. روی یک VPS کوچک، یک یا دو کیفیت ارائه دهید. پنج کیفیت، CPU را اشباع می‌کند در حالی که شبکه بیکار می‌ماند.

راه‌اندازی Element Call روی سرور Matrix فعلی

اگر در حال حاضر Matrix را اجرا می‌کنید، قابلیت ویدیو یک افزودنی محسوب می‌شود و نه محصولی دوم برای مدیریت. با این حال، این قابلیت بیش از یک بسته نرم‌افزاری است. Element Call در پشت homeserver شما به دو مورد نیاز دارد. اولی یک LiveKit SFU است که وظیفه انتقال رسانه را بر عهده دارد. دومی سرویس احراز هویت MatrixRTC با نام element-hq/lk-jwt-service است که URL مربوط به WebSocket سرویس LiveKit و یک JWT (JSON web token) امضاشده را برای اتصال در اختیار کلاینت قرار می‌دهد. این سرویس از API فدراسیون Matrix استفاده می‌کند، بنابراین به یک reverse proxy با قابلیت TLS در مقابل خود و نامی که از طریق فدراسیون قابل دسترس باشد، نیاز دارد.

پورت‌های مستندشده برای LiveKit عبارتند از:

  • پورت TCP 7880 برای API و WebSocket کلاینت، در پشت پروکسی که TLS را خاتمه می‌دهد
  • پورت TCP 7881 برای ICE روی TCP، که زمانی استفاده می‌شود که کلاینت نتواند از طریق UDP ارتباط برقرار کند
  • پورت‌های UDP 50000 تا 60000 برای رسانه، که در آن هر شرکت‌کننده در یک اتاق از دو پورت استفاده می‌کند
  • پورت‌های UDP 3478 و TCP 5349 در صورتی که سرور TURN داخلی را فعال کنید؛ پورت 5349 باید به 443 منتقل شود، مگر اینکه یک load balancer در مقابل آن قرار داشته باشد

استفاده از دو پورت برای هر شرکت‌کننده ممکن است نگران‌کننده به نظر برسد، اما این‌طور نیست. بازه 10000 پورتی، هزاران شرکت‌کننده را پوشش می‌دهد و پهنای باند آپلینک شما بسیار زودتر از اتمام این بازه به پایان می‌رسد. در هر صورت، کل بازه را باز کنید، زیرا باز بودن ناقص این بازه باعث می‌شود اتصال برای برخی کاربران برقرار و برای برخی دیگر قطع شود؛ این بدترین نوع خطا برای عیب‌یابی است. بخش مربوط به homeserver در این سناریو، وظیفه‌ای مجزا است که در اجرای یک homeserver از نوع Synapse روی VPS به آن پرداخته شده است.

چرا یک نفر هرگز نمی‌تواند متصل شود؟ TURN و شبکه‌هایی که UDP را مسدود می‌کنند

ابتدا چند واژه که هر کدام یک‌بار استفاده می‌شوند: ICE (مخفف interactive connectivity establishment) فرآیندی است که دو نقطه پایانی WebRTC برای یافتن یک مسیر کاری بین خود استفاده می‌کنند. STUN (مخفف session traversal utilities for NAT) سرویس کوچکی است که به کلاینت می‌گوید آدرس عمومی‌اش از بیرون چگونه دیده می‌شود. TURN (مخفف traversal using relays around NAT) یک رله است: زمانی که مسیر مستقیمی وجود ندارد، هر دو طرف رسانه خود را به سرور TURN می‌فرستند و آن سرور عملیات ارسال را انجام می‌دهد.

شما برای شرکت‌کنندگانی که شبکه‌هایشان برای شما قابل مشاهده نیست، به TURN نیاز دارید. یکی از آن‌ها ممکن است در شبکه شرکتی یا دانشگاهی باشد که در آن خروجی UDP به‌طور کامل مسدود شده است. دیگری پشت یک NAT در سطح اپراتور (Carrier-grade NAT) قرار دارد که برای هر مقصد یک پورت مبدأ متفاوت اختصاص می‌دهد؛ این وضعیت symmetric NAT نامیده می‌شود و باعث می‌شود آدرسی که STUN گزارش کرده، بی‌فایده باشد.

نشانه این مشکل خاص است. اکثر افراد متصل می‌شوند و همه چیز کار می‌کند. یک نفر لیست شرکت‌کنندگان و چت را می‌بیند، اما یک کادر سیاه و یک آیکون بارگذاری (spinner) مشاهده می‌کند. مرورگر آن‌ها کاندیداها را جمع‌آوری کرده، اما هیچ‌کدام از جفت‌ها کار نکرده و ICE در وضعیت شکست (failed) پایان یافته است. در Chrome، باز کردن chrome://webrtc-internals در حین تلاش برای اتصال، جفت‌های کاندیدا و آن شکست را نشان می‌دهد. از آن شخص بخواهید با استفاده از اینترنت موبایل دوباره تلاش کند. اگر در آنجا کار کرد، شبکه آن‌ها علت مشکل است و TURN راه حل آن است.

استفاده از TURN روی پروتکل TCP و پورت 443 یا 5349، راهکار جایگزینی است که تقریباً در همه جا کار می‌کند، زیرا شبکه‌ای که TLS روی پورت 443 را مسدود کند، در واقع وب را مسدود کرده است. بسته Jitsi نرم‌افزار coturn را برای شما نصب و پیکربندی می‌کند، و دقیقاً به همین دلیل است که قوانین فایروال مستند آن شامل UDP 3478 و TCP 5349 است. Galène دارای TURN داخلی روی پورت 1194 است. LiveKit یک سرور TURN تعبیه شده دارد که در تنظیمات آن را فعال می‌کنید. اگر خودتان coturn را اجرا می‌کنید:

sudo apt install -y coturn
sudo systemctl enable --now coturn
listening-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 دارد. راهنماهای قدیمی‌تر به شما می‌گویند که TURNSERVER_ENABLED=1 را در /etc/default/coturn تنظیم کنید. فقط اسکریپت init قدیمی آن سوئیچ را می‌خواند. واحد systemd که بسته‌های فعلی اجرا می‌کنند این کار را نمی‌کند، بنابراین آن خط هیچ تغییری ایجاد نمی‌کند و coturn که هرگز restart نشده، همچنان از فایل پیش‌فرض استفاده می‌کند.

حالا هزینه‌ای که کسی درباره آن نمی‌نویسد: یک رله، تمام رسانه هر شرکت‌کننده رله‌شده را در هر دو جهت حمل می‌کند. وقتی coturn با SFU روی یک سرور مشترک است، بیشتر این ترافیک از طریق loopback عبور می‌کند و به‌جای پهنای باند خروجی، CPU شما را درگیر می‌کند، و listener مربوط به TLS هر بسته را برای بار دوم روی DTLS که رسانه از قبل حمل می‌کند، رمزگذاری می‌کند. وقتی TURN را به ماشین اختصاصی خودش منتقل می‌کنید، آن ماشین به برنامه پهنای باند خاص خود نیاز دارد که مشابه SFU اندازه‌گیری شده باشد. همچنین، TURN روی TCP رسانه بلادرنگ را به یک جریان قابل‌اطمینان تبدیل می‌کند، بنابراین یک بسته گم‌شده به‌جای نادیده گرفته شدن، دوباره ارسال می‌شود و شرکت‌کننده‌ای که از طریق رله و روی یک لینک با افت کیفیت متصل است، به‌جای یک اختلال کوتاه، دچار تأخیر انباشته می‌شود. رله یک راهکار جایگزین است که اتصال را برقرار می‌کند، اما با کیفیتی که مسیر مستقیم قطعاً بهتر از آن عمل می‌کرد.

SFU چه زمانی عملیات transcode را انجام می‌دهد و هزینه آن چقدر است؟

یک SFU بسته‌ها را فقط فوروارد می‌کند و هرگز ویدیو را decode نمی‌کند؛ به همین دلیل است که 4 هسته پردازشی می‌توانند اتاقی را مدیریت کنند که روی کاغذ غیرممکن به نظر می‌رسد. دو قابلیت این ویژگی را نقض می‌کنند و هر دو، کاربرانی را که با یک تیک ساده آن‌ها را فعال کرده‌اند، غافلگیر می‌کنند.

اولین مورد، ضبط (Recording) است. Jitsi با استفاده از Jibri ضبط را انجام می‌دهد و مستندات خود Jibri دقیقاً توضیح می‌دهد که چه کاری انجام می‌دهد: این ابزار یک نمونه از Chrome را در یک framebuffer مجازی رندر کرده و خروجی را با ffmpeg ضبط و encode می‌کند. این یعنی یک مرورگر کامل که تمام جلسه شما را رندر می‌کند، به علاوه یک انکودر ویدیویی که در تمام طول تماس به‌طور مداوم در حال اجراست. همان مستندات بیان می‌کنند که در هر لحظه فقط یک ضبط روی یک Jibri پشتیبانی می‌شود و Jibri باید روی یک ماشین یا ماشین مجازی جداگانه اجرا شود که هیچ برنامه دیگری از نمایشگر یا دستگاه‌های صوتی آن استفاده نمی‌کند. ضبط کردن، یک سرور دوم است، نه فقط یک تیک ساده.

دومین مورد، شماره‌گیری تلفنی (Telephone dial-in) است. پل زدن یک خط تلفن به داخل کنفرانس به معنای تبدیل Opus با نرخ 48 kHz به فرمتی است که شبکه تلفن می‌پذیرد (معمولاً G.711 با نرخ 8 kHz)؛ این کار در هر دو جهت و به‌طور مداوم برای کل مدت تماس انجام می‌شود. transcoding صوتی بسیار ارزان‌تر از transcoding ویدیویی است، اما برای هر شاخه از تماس اجرا می‌شود و هرگز متوقف نمی‌شود، بنابراین هزینه آن با تعداد تماس‌گیرندگان افزایش می‌یابد. اگر به یک شماره برای تماس تلفنی نیاز دارید، یک سرور VoIP خودمیزبان مؤلفه‌ای است که این کار را انجام می‌دهد و به همان دلیلی که برای Jibri ذکر شد، باید روی سخت‌افزار اختصاصی خود اجرا شود.

واقعاً به چه ابعادی از سرور نیاز دارید؟

برای دو نفر، تقریباً به هیچ منبع خاصی نیاز ندارید. Jitsi به‌صورت پیش‌فرض وقتی دقیقاً دو شرکت‌کننده حضور دارند، حالت peer to peer را فعال می‌کند؛ در این حالت، کنفرانس ارسال داده از طریق videobridge را متوقف کرده و از اتصال مستقیم استفاده می‌کند. پیوستن نفر سوم، وضعیت را دوباره به حالت bridge برمی‌گرداند. بنابراین، یک VPS با 1 گیگابایت رم برای تماس‌های دونفره عالی است، اما برای چهار نفر ضعیف عمل می‌کند؛ به همین دلیل است که گزارش «هنگام تست کار می‌کرد» بسیار رایج است.

برای حداکثر حدود ده نفر با دوربین روشن، 67.2 مگابیت بر ثانیه برای هشت شرکت‌کننده، در محدوده توانایی آپلینک یک VPS معمولی قرار دارد. دو هسته پردازنده مجازی و 4 گیگابایت رم برای اجرای Jitsi یا Galène در این مقیاس کافی است، به شرطی که در حال ضبط نباشید. به‌جای نمودار CPU، شمارنده انتقال داده (transfer counter) را زیر نظر بگیرید.

برای سی نفر، بدترین حالت 1,044 مگابیت بر ثانیه ترافیک پایدار است و بیست ساعت از آن معادل 9.4 ترابایت می‌شود. در این مقیاس، پیش از قیمت‌گذاری سرور، باید هزینه پهنای باند را محاسبه کنید. قابلیت last-N را فعال کنید تا bridge فقط تصویر سخنرانان اخیر را ارسال کند، حالت پیش‌فرض دوربین شرکت‌کنندگان را خاموش قرار دهید و SFU را در جایی میزبانی کنید که محدودیت انتقال داده‌اش با این محاسبات همخوانی داشته باشد.

فراتر از این تعداد، استفاده از یک VPS انتخاب اشتباهی است. یا رویداد شما در واقع یک پخش زنده (broadcast) است که در آن صورت Owncast به همراه یک CDN کسری از این هزینه را خواهد داشت، یا نیاز دارید که بیش از یک videobridge را پشت یک لایه signalling واحد قرار دهید که پروژه‌ای متفاوت از چیزی است که شروع کرده‌اید.

یک نکته نهایی درباره مسیریابی: اکثر تیم‌ها در ساعات بیشتری از روز به چت نیاز دارند تا ویدیو، و میزبانی چت ارزان است و نگهداری آن آسان است. راه‌اندازی یک جایگزین Slack خودمیزبان برای ترافیک روزمره و نگهداری یک سرور کنفرانس فقط برای تماس‌های برنامه‌ریزی‌شده، چیدمانی است که با بودجه محدود یک VPS سازگار است.

FAQ

چرا افراد می‌توانند به جلسه Jitsi من ملحق شوند اما یکدیگر را نمی‌بینند یا نمی‌شنوند؟

چت و لیست شرکت‌کنندگان از طریق کانال سیگنالینگ منتقل می‌شوند که از پروتکل TCP روی پورت 443 استفاده می‌کند، در حالی که صدا و تصویر از پروتکل UDP روی پورت 10000 برای ارتباط با videobridge استفاده می‌کنند. اگر لیست شرکت‌کنندگان پر شود اما تصویر همه سیاه بماند، مسیر رسانه (media path) قطع است در حالی که مسیر سیگنالینگ مشکلی ندارد. پورت UDP 10000 را در هر دو فایروال بررسی کنید: فایروال روی سرور و فایروال شبکه در پنل مدیریت ارائه‌دهنده سرویس. سپس بررسی کنید که bridge آدرس عمومی خود را می‌شناسد یا خیر؛ در ماشین‌های مجازی که دارای آدرس خصوصی هستند و یک آدرس عمومی به آن‌ها نگاشت شده، یک نگاشت ایستا (static mapping) در ice4j.harvest.mapping داخل فایل /etc/jitsi/videobridge/jvb.conf اضافه کنید و jitsi-videobridge2 را ری‌استارت کنید. اجرای دستور sudo tcpdump -ni any udp port 10000 هنگام ملحق شدن یک نفر به جلسه، مشخص می‌کند مشکل از کدام بخش است، زیرا اگر هیچ بسته‌ای دریافت نشود، یعنی مسدودسازی در لایه‌ای بالاتر از سیستم‌عامل رخ داده است.

یک تماس ویدیویی 30 نفره چقدر پهنای باند مصرف می‌کند؟

در بدترین حالت، یعنی زمانی که دوربین همه روشن است و SFU یک لایه با کیفیت کامل را برای همه ارسال می‌کند، حدود 1,044 مگابیت بر ثانیه از سرور خارج می‌شود که معادل 469.8 گیگابایت در ساعت است. این یک محاسبه ریاضی از N ضربدر (N منهای 1) استریم با نرخ 1.2 مگابیت بر ثانیه برای هر کدام است و نه یک اندازه‌گیری واقعی از تنظیمات شما. قابلیت Simulcast و تنظیم last-N در استفاده معمول، این مقدار را به‌شدت کاهش می‌دهند، زیرا در هر لحظه اکثر شرکت‌کنندگان در صفحه نمایش حضور ندارند. با این حال، ظرفیت سرور را برای حالتی نزدیک به بدترین وضعیت در نظر بگیرید، چرا که بدترین حالت زمانی است که همه شرکت‌کنندگان هم‌زمان دوربین خود را روشن می‌کنند.

آیا می‌توانم Jitsi Meet را روی یک VPS با 1 گیگابایت رم اجرا کنم؟

نصب می‌شود و تماس دو نفره کار خواهد کرد، بخشی به این دلیل که Jitsi برای دقیقاً دو شرکت‌کننده از حالت peer-to-peer استفاده می‌کند و videobridge را کاملاً دور می‌زند. این سرور برای تماس‌های گروهی مناسب نیست. Prosody، videobridge و Java runtime همگی به حافظه نیاز دارند؛ پیشنهاد خودِ راهنمای Jitsi برای یک استقرار جدی 8 گیگابایت رم است و محدودیت پهنای باند پیش از محدودیت حافظه خود را نشان خواهد داد. اگر تنها یک سرور 1 گیگابایتی در اختیار دارید، Galène گزینه مناسب‌تری نسبت به Jitsi برای این ابعاد است.

آیا اگر VPS من دارای IP عمومی است، همچنان به سرور TURN نیاز دارم؟

بله. مشکلی که TURN حل می‌کند در سمت دیگر تماس قرار دارد. شرکت‌کننده‌ای که در یک شبکه سازمانی با محدودیت خروجی UDP قرار دارد، یا پشت یک NAT در سطح اپراتور (carrier-grade NAT) است که برای هر مقصد یک پورت منبع متفاوت اختصاص می‌دهد، نمی‌تواند مسیر مستقیم رسانه ایجاد کند، فارغ از اینکه آدرس سرور شما چقدر عمومی باشد. TURN روی پروتکل TCP و پورت‌های 443 یا 5349 به آن‌ها یک رله (relay) می‌دهد که برای فایروال آن‌ها مانند ترافیک عادی وب به نظر می‌رسد. نصب بسته‌ای Jitsi به‌صورت پیش‌فرض coturn را برای این منظور تنظیم می‌کند، به همین دلیل است که قوانین فایروال مستند شده برای آن، پورت‌های UDP 3478 و TCP 5349 را باز می‌کنند.

چرا BigBlueButton نسبت به Jitsi Meet به سخت‌افزار بسیار بیشتری نیاز دارد؟

زیرا کارهای بسیار بیشتری از صرفاً ارسال ویدیو انجام می‌دهد. نیازمندی‌های تولیدی منتشر شده برای آن 16 گیگابایت رم و 8 هسته پردازنده است، در حالی که این مقادیر در راهنمای Jitsi برابر با 8 گیگابایت رم و 4 هسته است. BigBlueButton یک پشته کامل کنفرانس صوتی، تخته‌سفید اشتراکی و لایه ارائه، خط لوله ضبط و پردازش پس از آن، و یک رابط کاربری وب با حساب‌های کاربری را همگی روی یک ماشین اجرا می‌کند. این نرم‌افزار همچنین در مورد پلتفرم خود سخت‌گیر است: تا اوت 2026، نسخه پشتیبانی‌شده برای نصب، نسخه 3.0 روی Ubuntu 22.04 است. هر دو مجموعه ارقام از مستندات خودِ پروژه‌ها استخراج شده‌اند و نقاط شروع هستند، نه اندازه‌گیری دقیق از بار کاری شما.

#jitsi#webrtc#video-conferencing#self-hosting#bandwidth