Voice و Video Chat با WebRTC
یک سرویس تماس صوتی و تصویری گروهی میسازید: signaling server، عبور از NAT با STUN و TURN و یک SFU که با Pion نوشته میشود و جریانهای رسانه را بین شرکتکنندهها پخش میکند.
در این صفحه
هدف
در پایان این پروژه یک سرویس تماس دارید که:
- تماس دونفره را مستقیم بین دو مرورگر برقرار میکند.
- تماس گروهی را از راه یک SFU که خودتان نوشتهاید پیش میبرد.
- پشت NAT و فایروالهای سختگیر هم وصل میشود.
- کیفیت تصویر را با پهنای باند هر شرکتکننده تنظیم میکند.
- با metricهای واقعی رسانه مثل packet loss، jitter و bitrate پایش میشود.
این پروژه سختترین پروژهٔ دوره است، چون همزمان با سه لایه سروکار دارید: پروتکل signaling که خودتان طراحی میکنید، مذاکرهٔ WebRTC و بستههای رسانه روی UDP.
چه چیزی میسازید
یک برنامهٔ تماس مبتنی بر اتاق: کاربر با یک پیوند وارد اتاق میشود، میکروفون و دوربینش را روشن میکند و بقیه را میبیند و میشنود.
اجزای تحویلی
سه مفهوم پایه
پیش از معماری، باید سه واژه را دقیق بدانید:
- signaling (پیامرسانی برقراری تماس): دو طرف پیش از تماس باید دربارهٔ codec، نشانیها و کلیدها توافق کنند. WebRTC نمیگوید این پیامها چطور جابهجا شوند. این بخش را شما با WebSocket میسازید.
- ICE: روشی برای پیدا کردن مسیری که دو طرف واقعاً بتوانند از آن بسته بفرستند. STUN نشانی عمومی شما را میگوید و TURN وقتی مسیر مستقیم ممکن نیست، بستهها را رله میکند.
- SFU (Selective Forwarding Unit): سروری که رسانهٔ هر شرکتکننده را میگیرد و بدون رمزگشایی تصویر، برای بقیه میفرستد.
چرا SFU
در این پروژه گام اول را با اتصال مستقیم دونفره میسازید تا مذاکره را بفهمید و سپس به SFU میروید.
معماری
- signaling و رسانه جدا هستند. signaling یک سرویس WebSocket معمولی است و SFU با UDP کار میکند. نیاز این دو به مقیاس و منابع فرق دارد.
- هر شرکتکننده یک
PeerConnectionبا SFU دارد. trackهای خودش را از همان اتصال میفرستد و trackهای بقیه را از همان میگیرد. - SFU بستههای RTP را رمزگشایی نمیکند. فقط header را میخواند، مسیر را انتخاب میکند و بسته را جلو میفرستد. برای همین با CPU کم کار میکند.
برقراری یک تماس
مقایسه با دنیای Python
پیشنیازها
- همهٔ فاز ۳، بهویژه
context، الگوهای لغو وsync. - از فاز ۴:
net/http، احراز هویت با token و graceful shutdown. - از فاز ۵: metric، profiling و Docker.
- از فاز ۶: درسهای WebSocket، UDP و بستهٔ
net، مبانی WebRTC و Pion. - پروژهٔ ۹ پیشنهاد میشود، چون مدیریت اتصال و اتاق را آنجا تمرین کردهاید.
گامهای پروژه
signaling و تماس دونفره
سرور signaling با اتاق، تبادل offer و answer و ICE candidate. دو مرورگر مستقیم به هم وصل میشوند.
معیار پذیرش: دو مرورگر در یک شبکه صدا و تصویر هم را دارند و ترتیب پیامهای signaling با تست پوشش داده شده است.
عبور از NAT
افزودن STUN و TURN با coturn، بررسی وضعیتهای ICE و صدور اعتبارنامهٔ موقت TURN با HMAC.
معیار پذیرش: تماس وقتی مسیر مستقیم UDP بسته است، از راه TURN برقرار میشود. اعتبارنامهٔ منقضیشده رد میشود.
نخستین SFU
سرور Pion که track هر شرکتکننده را میگیرد و بستههای RTP را برای بقیهٔ اتاق میفرستد.
معیار پذیرش: سه مرورگر در یک اتاق هم را میبینند و هر مرورگر فقط یک اتصال رسانه دارد.
ورود و خروج در میانهٔ تماس
renegotiation، افزودن و حذف track، قطع و وصل صدا و درخواست keyframe با RTCP.
معیار پذیرش: کسی که وسط تماس وارد میشود، در کمتر از یک ثانیه تصویر بقیه را میبیند. خروج یک نفر هیچ goroutine یا track رهاشدهای باقی نمیگذارد.
کیفیت تطبیقی
simulcast، انتخاب لایهٔ کیفیت برای هر گیرنده بر پایهٔ برآورد پهنای باند و تشخیص گویندهٔ فعال.
معیار پذیرش: با محدود کردن پهنای باند یک گیرنده، فقط کیفیت همان گیرنده پایین میآید و صدا قطع نمیشود.
دسترسی و امنیت
token دسترسی با مجوزهای جدا برای ارسال و دریافت، محدودیت نرخ روی signaling و سقف تعداد track.
معیار پذیرش: بدون token معتبر هیچ رسانهای جابهجا نمیشود و شرکتکنندهٔ فقطشنونده نمیتواند track بفرستد.
پایش، آزمون بار و انتشار
metric برای packet loss، jitter و bitrate، کلاینت مصنوعی با Pion برای آزمون بار و انتشار با Docker و بازهٔ پورت UDP.
معیار پذیرش: یک اتاق ۲۵ نفره و ۲۰ اتاق همزمان چهارنفره روی یک ماشین پایدار میمانند و مصرف CPU و حافظه در گزارش پروژه ثبت میشود.
پروتکل signaling
پیامها JSON هستند و روی WebSocket جابهجا میشوند:
تصمیمهای مهندسی که باید از آنها دفاع کنید
- جداسازی signaling از SFU: دو سرویس جدا یا یک پروسه؟ هزینهٔ هماهنگی در برابر مقیاسپذیری مستقل.
- یک
PeerConnectionیا دو: ارسال و دریافت روی یک اتصال باشد یا جدا؟ اثر آن بر renegotiation چیست؟ - TURN: همیشه روشن باشد یا فقط در صورت نیاز؟ هزینهٔ پهنای باند رله را چه کسی میدهد؟
- مقیاس افقی: یک اتاق روی یک SFU میماند. اتاق بزرگتر از ظرفیت یک سرور را چطور بین چند SFU پخش میکنید؟
- حافظه: برای هر بستهٔ RTP حافظهٔ تازه میگیرید یا از
sync.Poolاستفاده میکنید؟ این را با benchmark نشان میدهید.
اشتباههای رایج
نتیجهٔ نهایی
- سرور signaling و SFU با تست واحد، تست یکپارچه و
-raceسبز - کلاینت مرورگر برای تماس گروهی
- compose کامل همراه با coturn
- کلاینت مصنوعی و گزارش آزمون بار با عدد واقعی
- داشبورد metric رسانه
- یادداشت تصمیمهای مهندسی