پرش به محتوای اصلی

پروژهٔ ۱۰

Voice و Video Chat با WebRTC

یک سرویس تماس صوتی و تصویری گروهی می‌سازید: signaling server، عبور از NAT با STUN و TURN و یک SFU که با Pion نوشته می‌شود و جریان‌های رسانه را بین شرکت‌کننده‌ها پخش می‌کند.

Seniorزمان پیشنهادی: ۴۰ ساعتزمان مطالعه: ۱۰ دقیقه
در این صفحه

هدف

در پایان این پروژه یک سرویس تماس دارید که:

  • تماس دونفره را مستقیم بین دو مرورگر برقرار می‌کند.
  • تماس گروهی را از راه یک SFU که خودتان نوشته‌اید پیش می‌برد.
  • پشت NAT و فایروال‌های سخت‌گیر هم وصل می‌شود.
  • کیفیت تصویر را با پهنای باند هر شرکت‌کننده تنظیم می‌کند.
  • با metric‌های واقعی رسانه مثل packet loss، jitter و bitrate پایش می‌شود.

این پروژه سخت‌ترین پروژهٔ دوره است، چون هم‌زمان با سه لایه سروکار دارید: پروتکل signaling که خودتان طراحی می‌کنید، مذاکرهٔ WebRTC و بسته‌های رسانه روی UDP.

چه چیزی می‌سازید

یک برنامهٔ تماس مبتنی بر اتاق: کاربر با یک پیوند وارد اتاق می‌شود، میکروفون و دوربینش را روشن می‌کند و بقیه را می‌بیند و می‌شنود.

اجزای تحویلی

جزءتوضیح
cmd/signalingسرور signaling روی WebSocket: اتاق، عضویت و تبادل SDP
cmd/sfuسرور رسانه با Pion: دریافت و پخش track‌ها
internal/roomوضعیت اتاق و شرکت‌کننده‌ها
internal/mediaمسیردهی RTP، مدیریت RTCP و انتخاب لایهٔ کیفیت
internal/authtoken دسترسی به اتاق و اعتبارنامهٔ موقت TURN
web/کلاینت مرورگر با TypeScript
deploy/Dockerfile، compose همراه با coturn و داشبورد metric

سه مفهوم پایه

پیش از معماری، باید سه واژه را دقیق بدانید:

  • signaling (پیام‌رسانی برقراری تماس): دو طرف پیش از تماس باید دربارهٔ codec، نشانی‌ها و کلیدها توافق کنند. WebRTC نمی‌گوید این پیام‌ها چطور جابه‌جا شوند. این بخش را شما با WebSocket می‌سازید.
  • ICE: روشی برای پیدا کردن مسیری که دو طرف واقعاً بتوانند از آن بسته بفرستند. STUN نشانی عمومی شما را می‌گوید و TURN وقتی مسیر مستقیم ممکن نیست، بسته‌ها را رله می‌کند.
  • SFU (Selective Forwarding Unit): سروری که رسانهٔ هر شرکت‌کننده را می‌گیرد و بدون رمزگشایی تصویر، برای بقیه می‌فرستد.

چرا SFU

در حال رسم نمودار…
معیارMeshSFUMCU
بار upload هر کاربریک جریان برای هر نفریک جریانیک جریان
بار CPU سرورصفرکم، فقط مسیردهیزیاد، رمزگشایی و ترکیب
سقف عملی شرکت‌کنندهحدود ۴ نفرده‌ها نفرزیاد
کنترل کیفیت برای هر گیرندهنداردداردندارد

در این پروژه گام اول را با اتصال مستقیم دونفره می‌سازید تا مذاکره را بفهمید و سپس به SFU می‌روید.

معماری

در حال رسم نمودار…
  • signaling و رسانه جدا هستند. signaling یک سرویس WebSocket معمولی است و SFU با UDP کار می‌کند. نیاز این دو به مقیاس و منابع فرق دارد.
  • هر شرکت‌کننده یک PeerConnection با SFU دارد. track‌های خودش را از همان اتصال می‌فرستد و track‌های بقیه را از همان می‌گیرد.
  • SFU بسته‌های RTP را رمزگشایی نمی‌کند. فقط header را می‌خواند، مسیر را انتخاب می‌کند و بسته را جلو می‌فرستد. برای همین با CPU کم کار می‌کند.

برقراری یک تماس

در حال رسم نمودار…

مقایسه با دنیای Python

موضوعGoPython
کتابخانهٔ WebRTCPion، کاملاً با Go و بدون وابستگی Caiortc روی asyncio
مسیردهی بستهیک goroutine برای هر tracktask روی یک event loop
استفاده از چند هستهخودکارمحدود به GIL، نیاز به چند پروسه
هزینهٔ هر بستهتخصیص حافظهٔ قابل‌کنترل با sync.Poolساخت شیء برای هر بسته
کاربرد رایج در productionسرور رسانهنمونه‌سازی و پردازش سمت کلاینت
ساخت سرور رسانه در Go و Python

پیش‌نیازها

  • همهٔ فاز ۳، به‌ویژه context، الگوهای لغو و sync.
  • از فاز ۴: net/http، احراز هویت با token و graceful shutdown.
  • از فاز ۵: metric، profiling و Docker.
  • از فاز ۶: درس‌های WebSocket، UDP و بستهٔ net، مبانی WebRTC و Pion.
  • پروژهٔ ۹ پیشنهاد می‌شود، چون مدیریت اتصال و اتاق را آنجا تمرین کرده‌اید.

گام‌های پروژه

  1. signaling و تماس دونفره

    سرور signaling با اتاق، تبادل offer و answer و ICE candidate. دو مرورگر مستقیم به هم وصل می‌شوند.

    معیار پذیرش: دو مرورگر در یک شبکه صدا و تصویر هم را دارند و ترتیب پیام‌های signaling با تست پوشش داده شده است.

  2. عبور از NAT

    افزودن STUN و TURN با coturn، بررسی وضعیت‌های ICE و صدور اعتبارنامهٔ موقت TURN با HMAC.

    معیار پذیرش: تماس وقتی مسیر مستقیم UDP بسته است، از راه TURN برقرار می‌شود. اعتبارنامهٔ منقضی‌شده رد می‌شود.

  3. نخستین SFU

    سرور Pion که track هر شرکت‌کننده را می‌گیرد و بسته‌های RTP را برای بقیهٔ اتاق می‌فرستد.

    معیار پذیرش: سه مرورگر در یک اتاق هم را می‌بینند و هر مرورگر فقط یک اتصال رسانه دارد.

  4. ورود و خروج در میانهٔ تماس

    renegotiation، افزودن و حذف track، قطع و وصل صدا و درخواست keyframe با RTCP.

    معیار پذیرش: کسی که وسط تماس وارد می‌شود، در کمتر از یک ثانیه تصویر بقیه را می‌بیند. خروج یک نفر هیچ goroutine یا track رهاشده‌ای باقی نمی‌گذارد.

  5. کیفیت تطبیقی

    simulcast، انتخاب لایهٔ کیفیت برای هر گیرنده بر پایهٔ برآورد پهنای باند و تشخیص گویندهٔ فعال.

    معیار پذیرش: با محدود کردن پهنای باند یک گیرنده، فقط کیفیت همان گیرنده پایین می‌آید و صدا قطع نمی‌شود.

  6. دسترسی و امنیت

    token دسترسی با مجوزهای جدا برای ارسال و دریافت، محدودیت نرخ روی signaling و سقف تعداد track.

    معیار پذیرش: بدون token معتبر هیچ رسانه‌ای جابه‌جا نمی‌شود و شرکت‌کنندهٔ فقط‌شنونده نمی‌تواند track بفرستد.

  7. پایش، آزمون بار و انتشار

    metric برای packet loss، jitter و bitrate، کلاینت مصنوعی با Pion برای آزمون بار و انتشار با Docker و بازهٔ پورت UDP.

    معیار پذیرش: یک اتاق ۲۵ نفره و ۲۰ اتاق هم‌زمان چهارنفره روی یک ماشین پایدار می‌مانند و مصرف CPU و حافظه در گزارش پروژه ثبت می‌شود.

پروتکل signaling

پیام‌ها JSON هستند و روی WebSocket جابه‌جا می‌شوند:

JSON
{
  "type": "offer",
  "room": "team-standup",
  "payload": { "sdp": "v=0 ..." }
}
پیامجهتکاربرد
joinکلاینت به سرورورود به اتاق با token
offer و answerدوطرفهتوافق دربارهٔ رسانه با SDP
candidateدوطرفهنشانی‌های پیشنهادی ICE
participantسرور به کلاینتورود، خروج و تغییر وضعیت دیگران
muteکلاینت به سرورقطع و وصل صدا یا تصویر
errorسرور به کلاینتکد و شرح خطا

تصمیم‌های مهندسی که باید از آن‌ها دفاع کنید

  • جداسازی signaling از SFU: دو سرویس جدا یا یک پروسه؟ هزینهٔ هماهنگی در برابر مقیاس‌پذیری مستقل.
  • یک PeerConnection یا دو: ارسال و دریافت روی یک اتصال باشد یا جدا؟ اثر آن بر renegotiation چیست؟
  • TURN: همیشه روشن باشد یا فقط در صورت نیاز؟ هزینهٔ پهنای باند رله را چه کسی می‌دهد؟
  • مقیاس افقی: یک اتاق روی یک SFU می‌ماند. اتاق بزرگ‌تر از ظرفیت یک سرور را چطور بین چند SFU پخش می‌کنید؟
  • حافظه: برای هر بستهٔ RTP حافظهٔ تازه می‌گیرید یا از sync.Pool استفاده می‌کنید؟ این را با benchmark نشان می‌دهید.

اشتباه‌های رایج

نتیجهٔ نهایی

  • سرور signaling و SFU با تست واحد، تست یکپارچه و -race سبز
  • کلاینت مرورگر برای تماس گروهی
  • compose کامل همراه با coturn
  • کلاینت مصنوعی و گزارش آزمون بار با عدد واقعی
  • داشبورد metric رسانه
  • یادداشت تصمیم‌های مهندسی

ویرایش این صفحه در GitHub