مجله ایرانیکاسرورآموزش سرور، هاست، وردپرس و شبکه
آموزشی

چرا WebRTC صدا ندارد؟ رفع مشکل ICE، TURN، DTLS و RTP

اگر تماس WebRTC زنگ می‌خورد، پاسخ داده می‌شود و حتی تایمر تماس شروع می‌شود اما صدایی شنیده نمی‌شود، معمولاً مشکل دیگر در SIP Registration نیست؛ باید مسیر Media را بررسی کنید. در WebRTC، برقراری…

چرا WebRTC صدا ندارد؟ رفع مشکل ICE، TURN، DTLS و RTP
خلاصه سریع این آموزش

اگر تماس WebRTC زنگ می‌خورد، پاسخ داده می‌شود و حتی تایمر تماس شروع می‌شود اما صدایی شنیده نمی‌شود، معمولاً مشکل دیگر در SIP Registration نیست؛ باید مسیر Media را بررسی…

۲۲ دقیقه مطالعه ۰ دیدگاه ۲۵ مهر ۱۴۰۵ آخرین به‌روزرسانی
اگر تماس WebRTC زنگ می‌خورد، پاسخ داده می‌شود و حتی تایمر تماس شروع می‌شود اما صدایی شنیده نمی‌شود، معمولاً مشکل دیگر در SIP Registration نیست؛ باید مسیر Media را بررسی کنید. در WebRTC، برقراری تماس و عبور صدا دو مرحله جدا هستند و سالم‌بودن WSS یا SIP به این معنی نیست که ICE، DTLS-SRTP و RTP هم درست کار می‌کنند.مشکل WebRTC no audio معمولاً در یکی از این بخش‌ها قرار دارد: ICE Candidate اشتباه، NAT یا Firewall، در دسترس نبودن TURN، شکست DTLS Handshake، بسته‌بودن RTP Portها، Codec نامناسب یا حتی پخش‌نشدن Audio داخل خود مرورگر.در این مقاله از حدس‌زدن عبور می‌کنیم و تماس را مرحله‌به‌مرحله بررسی می‌کنیم. ابتدا مشخص می‌کنیم آیا Browser واقعاً Audio Track دارد، بعد ICE Candidate و Selected Candidate Pair را پیدا می‌کنیم، TURN را آزمایش می‌کنیم، DTLS را از RTP جدا می‌کنیم و در نهایت با Asterisk و Packet Capture مشخص می‌کنیم صدا دقیقاً در کدام نقطه متوقف شده است.

نکته مهم: اگر تماس اصلاً Register نمی‌شود یا INVITE به مقصد نمی‌رسد، هنوز وارد مرحله عیب‌یابی Media نشده‌اید. این راهنما برای شرایطی است که Signaling حداقل تا حد زیادی سالم است و مشکل اصلی «نبود صدا»، «صدای یک‌طرفه» یا «قطع Media بعد از برقراری تماس» است.

فهرست مطالب

اول مشخص کنیم «صدا ندارد» دقیقاً یعنی چه

سه وضعیت ظاهراً مشابه، علت‌های متفاوتی دارند.

نشانه احتمال بیشتر
هیچ‌کدام از طرفین صدا ندارند ICE، DTLS، RTP Firewall یا Media Negotiation
فقط یک طرف صدا دارد NAT، SDP، Candidate Pair یا Routing یک‌طرفه
Packet دریافت می‌شود ولی چیزی شنیده نمی‌شود Codec، Audio Element، Output Device، Mute یا Autoplay مرورگر
ICE روی Checking می‌ماند Connectivity و STUN/TURN
ICE Connected است ولی Media نمی‌آید DTLS-SRTP، RTP Routing یا Codec

مسیر واقعی یک تماس WebRTC را بشناسید

در یک تماس مرورگری روی Asterisk، دو مسیر مستقل داریم.

Signaling:

Browser
   |
   | WSS / SIP
   v
Asterisk

Media:

Browser
   |
ICE Candidate Selection
   |
DTLS Handshake
   |
SRTP
   |
Asterisk

بنابراین ممکن است:

REGISTER = موفق

INVITE = موفق

200 OK = موفق

ACK = موفق

ولی:

ICE یا DTLS شکست بخورد و هیچ صدایی نداشته باشید.

روش تشخیص استاندارد مشکل WebRTC no audio

این ترتیب را حفظ کنید:

مرحله ۱: آیا Browser Microphone Track دارد؟

مرحله ۲: آیا ICE Candidate جمع‌آوری شده است؟

مرحله ۳: کدام Candidate Pair انتخاب شده؟

مرحله ۴: آیا ICE به Connected یا Completed رسیده؟

مرحله ۵: آیا DTLS Handshake موفق شده؟

مرحله ۶: آیا SRTP Packet ارسال می‌شود؟

مرحله ۷: آیا Asterisk RTP دریافت و ارسال می‌کند؟

مرحله ۸: آیا Browser Packet دریافت می‌کند ولی Audio را پخش نمی‌کند؟

مرحله ۱: قبل از ICE، Microphone مرورگر را بررسی کنید

اگر Browser اصلاً Audio Track تولید نکرده باشد، بررسی TURN و RTP هیچ کمکی نمی‌کند.

در DevTools Console می‌توانید ساده‌ترین تست را اجرا کنید:

navigator.mediaDevices
  .getUserMedia({
    audio: true,
    video: false
  })
  .then(stream => {
    console.log(stream.getAudioTracks());
  })
  .catch(err => {
    console.error(err.name, err.message);
  });

اگر Audio Track دارید، به مرحله ICE بروید.

اگر ندارید، موارد زیر را بررسی کنید:

🔹 Permission میکروفن Browser روی Block نباشد.

🔹 Web App با HTTPS اجرا شود.

🔹 دستگاه ورودی مناسب انتخاب شده باشد.

🔹 برنامه دیگری Microphone را انحصاری نگرفته باشد.

مرحله ۲: ICE Candidateها را بررسی کنید

ICE قبل از برقراری Media چند مسیر احتمالی برای ارتباط پیدا می‌کند.

Candidateهای مهم WebRTC چهار نوع هستند:

نوع معنی در عیب‌یابی چه می‌گوید؟
host آدرس مستقیم Interface برای LAN یا مسیر مستقیم مناسب است
srflx Server Reflexive Public Mapping کشف‌شده از طریق STUN
prflx Peer Reflexive Mapping کشف‌شده حین Connectivity Check
relay TURN Relay Media از TURN Server عبور می‌کند

نمونه Candidate از نوع host

a=candidate:4234997325 1 udp 2043278322 192.0.2.172 44323 typ host

بخش آخر:

typ host

نوع Candidate را مشخص می‌کند.

اگر فقط host Candidate دارید چه؟

اگر Browser و Asterisk در دو شبکه متفاوت یا پشت NAT باشند، Candidate محلی به‌تنهایی اغلب کافی نیست.

مثلاً Browser می‌گوید:

192.168.1.42:53188

اما Asterisk اینترنتی طبیعتاً نمی‌تواند مستقیماً به این آدرس خصوصی Route کند.

در چنین شرایطی باید حداقل Candidate مناسب STUN یا TURN وجود داشته باشد.

srflx یعنی STUN کار کرده است؟

وجود Candidate از نوع `srflx` معمولاً نشان می‌دهد ICE Agent توانسته Public Mapping مربوط به NAT را کشف کند.

مثلاً:

typ srflx
address: 198.51.100.24
relatedAddress: 192.168.1.42

اما وجود `srflx` به معنی تضمین ارتباط نیست.

ممکن است NAT اجازه برگشت Packet از Peer را ندهد و Connectivity Check شکست بخورد.

relay مهم‌ترین Candidate برای تشخیص TURN است

اگر Candidate از نوع:

typ relay

می‌بینید، TURN Server توانسته Relay Candidate ایجاد کند.

این Candidate زمانی بسیار مهم است که Direct Connectivity از طریق host یا srflx ممکن نباشد.

نبود relay Candidate همیشه مشکل نیست

اگر Direct Candidate کار می‌کند، WebRTC ممکن است اصلاً به TURN نیاز نداشته باشد.

بنابراین قانون درست این نیست:

«relay نداریم پس WebRTC خراب است.»

قانون درست این است:

«اگر Direct Candidate شکست می‌خورد، آیا یک relay Candidate سالم برای مسیر جایگزین داریم؟»

مرحله ۳: Selected Candidate Pair را پیدا کنید

صرف وجود Candidate کافی نیست.

ICE در نهایت یک جفت Candidate را انتخاب می‌کند.

مثلاً:

Local:
relay / UDP

Remote:
host / UDP

State:
succeeded

این اطلاعات بسیار مهم‌تر از فهرست تمام Candidateهاست.

کجا Candidate Pair را ببینیم؟

در مرورگرهای Chromium می‌توانید از WebRTC Internals یا ابزارهای Developer مربوط به PeerConnection استفاده کنید.

در برنامه خودتان نیز `getStats()` اطلاعات دقیقی می‌دهد.

نمونه ساده getStats

const stats = await peerConnection.getStats();

stats.forEach(report => {
  if (
    report.type === "candidate-pair" ||
    report.type === "inbound-rtp" ||
    report.type === "outbound-rtp"
  ) {
    console.log(report);
  }
});

چه چیزهایی را در Stats نگاه کنیم؟

برای Media ورودی:

🔹 packetsReceived

🔹 bytesReceived

🔹 packetsLost

🔹 jitter

برای خروجی:

🔹 packetsSent

🔹 bytesSent

اگر bytesSent بالا می‌رود ولی bytesReceived صفر است

این یکی از واضح‌ترین نشانه‌های Media یک‌طرفه است.

یعنی Browser صدا می‌فرستد، اما Media برگشتی به Browser نمی‌رسد.

تمرکز روی:

🔹 NAT سمت Asterisk

🔹 Firewall

🔹 SDP Address

🔹 Remote Candidate

🔹 RTP Routing

قرار می‌گیرد.

اگر bytesReceived بالا می‌رود ولی کاربر صدایی نمی‌شنود

شبکه احتمالاً کار می‌کند.

حالا Browser Playback را بررسی کنید:

🔹 آیا Remote Stream به Audio Element وصل شده؟

🔹 آیا Audio Element روی mute نیست؟

🔹 آیا Output Device درست انتخاب شده؟

🔹 آیا Browser به دلیل Autoplay Policy، `play()` را متوقف کرده است؟

یک خطای برنامه‌نویسی رایج

ممکن است Track از شبکه رسیده باشد ولی هیچ Media Elementی آن را پخش نکند.

ساختار ساده:

peerConnection.ontrack = event => {
  const remoteAudio = document.getElementById("remoteAudio");

  remoteAudio.srcObject = event.streams[0];

  remoteAudio.play().catch(error => {
    console.error("Audio playback blocked:", error);
  });
};

مرحله ۴: وضعیت ICE را بررسی کنید

مقادیر مهم `iceConnectionState` عبارت‌اند از:

🔹 new

🔹 checking

🔹 connected

🔹 completed

🔹 disconnected

🔹 failed

🔹 closed

اگر روی checking گیر کرده است

Candidateها جمع شده‌اند اما هیچ Candidate Pair موفقی پیدا نشده است.

علت‌های رایج:

🔹 UDP بین دو طرف Block شده است.

🔹 NAT اجازه ارتباط مستقیم نمی‌دهد.

🔹 STUN Candidate قابل‌استفاده نیست.

🔹 TURN Relay ندارید.

🔹 TURN Authentication شکست خورده است.

اگر ICE روی failed می‌رود

ICE Connectivity Checkها شکست خورده‌اند.

در این حالت قبل از بررسی Codec و Dialplan، مشکل Connectivity را برطرف کنید.

Codec باعث نمی‌شود ICE State به failed برود.

اگر ICE connected است ولی هنوز صدا ندارید

این مرحله بسیار مهم است.

وقتی ICE Connected شده، حداقل یک مسیر Network بین دو طرف پیدا شده است.

حالا باید به ترتیب بررسی کنید:

DTLS → SRTP → Codec → Browser Playback

TURN چه زمانی مشکل را حل می‌کند؟

TURN زمانی وارد کار می‌شود که ارتباط مستقیم میان Browser و مقصد ممکن یا پایدار نباشد.

به‌جای:

Browser ↔ Asterisk

مسیر تبدیل می‌شود به:

Browser
   |
 TURN Relay
   |
Asterisk

سناریویی که TURN اهمیت زیادی پیدا می‌کند

فرض کنید WebRTC برای کاربران اینترنت خانگی کار می‌کند اما کاربران یک شرکت خاص هیچ صدایی ندارند.

این الگو می‌تواند نشان دهد:

🔹 Firewall سازمان UDP را محدود کرده است.

🔹 NAT سخت‌گیرانه است.

🔹 Direct ICE Candidate شکست می‌خورد.

اگر TURN روی مسیر سازگار در دسترس باشد، `relay` Candidate می‌تواند اتصال را برقرار کند.

چطور مطمئن شویم TURN واقعاً استفاده می‌شود؟

بهترین پاسخ:

Selected Candidate Pair را ببینید.

اگر Candidate انتخاب‌شده:

type = relay

باشد، Media از TURN استفاده می‌کند.

روش تست مهم: فقط TURN را اجباری کنید

برای عیب‌یابی موقت می‌توانید در Browser فقط Relay Candidate را اجازه دهید:

const configuration = {
  iceServers: [
    {
      urls: "turn:turn.example.com:3478",
      username: "TEMP_USER",
      credential: "TEMP_PASSWORD"
    }
  ],
  iceTransportPolicy: "relay"
};

const pc = new RTCPeerConnection(configuration);

این تنظیم برای تست بسیار ارزشمند است.

اگر تماس در حالت `relay` کاملاً صدا دارد ولی در حالت عادی ندارد، مشکل احتمالاً در Direct ICE/NAT Path است.

relay را دائماً Force کنیم؟

نه لزوماً.

TURN تمام Media را از سرور عبور می‌دهد و در نتیجه:

🔹 Bandwidth سرور افزایش پیدا می‌کند.

🔹 یک Hop جدید به تماس اضافه می‌شود.

🔹 Latency ممکن است افزایش یابد.

در بیشتر سیستم‌ها TURN باید مسیر جایگزین قابل‌اعتماد باشد، مگر اینکه طراحی امنیتی شما عمداً Media Relay اجباری بخواهد.

Coturn برای TURN Server

یکی از رایج‌ترین گزینه‌های متن‌باز برای STUN/TURN، پروژه Coturn است.

TURN Server باید Authentication داشته باشد و Anonymous Relay برای سرویس عمومی انتخاب امنی نیست.

برای WebRTC می‌توان از Long-Term Credential یا Credentialهای زمان‌دار استفاده کرد.

TURN Credential را داخل JavaScript دائمی Hardcode نکنید

اگر Web App عمومی است، هر کاربر می‌تواند Source را ببیند.

یک Password دائمی TURN داخل JavaScript عملاً Secret نیست.

برای سرویس واقعی بهتر است Credential زمان‌دار از Backend صادر شود.

پورت‌های TURN

Coturn به‌صورت رایج Listenerهایی مثل:

3478
5349

دارد، اما Relay Media Portها نیز باید در Firewall مطابق `min-port` و `max-port` واقعی سرور باز باشند.

این نکته یکی از علت‌های کلاسیک «TURN وصل می‌شود ولی Media عبور نمی‌کند» است.

TURN Server پشت NAT است؟

اگر خود Coturn پشت NAT قرار دارد، Public/External IP باید به‌درستی تنظیم شود.

در غیر این صورت Relay Candidate ممکن است آدرسی تبلیغ کند که Browser یا Asterisk نمی‌توانند به آن دسترسی داشته باشند.

یک مقاله مرتبط در ایرانیکاسرور

اگر هنوز TURN Server ندارید: در مقاله راه‌اندازی Coturn روی VPS ایران می‌توانید نمونه عملی ساخت TURN Server را ببینید. برای WebRTC تلفنی نیز همان مفاهیم Public IP، Authentication، Relay Port و Firewall اهمیت دارند.

مرحله ۵: DTLS را بررسی کنید

بعد از پیدا شدن مسیر ICE، WebRTC باید Media Encryption را آماده کند.

در معماری معمول Browser و Asterisk، این مرحله با:

DTLS-SRTP

انجام می‌شود.

DTLS چه کاری می‌کند؟

DTLS روی مسیر Datagram اجرا می‌شود و در WebRTC برای مذاکره کلیدهای SRTP استفاده می‌شود.

خود Audio بعداً به شکل SRTP منتقل می‌شود.

پس:

ICE = مسیر شبکه

DTLS = مذاکره امنیت Media

SRTP = صدای رمزنگاری‌شده

در SDP دنبال چه چیزی بگردیم؟

وجود Fingerprint:

a=fingerprint:sha-256 ...

و Setup Role:

a=setup:actpass

از نشانه‌های مهم DTLS هستند.

Asterisk WebRTC و DTLS

در PJSIP، اگر Endpoint شما:

webrtc=yes

داشته باشد، Asterisk تنظیمات اصلی WebRTC مانند:

use_avpf=yes
media_encryption=dtls
dtls_verify=fingerprint
dtls_setup=actpass
ice_support=yes
media_use_received_transport=yes
rtcp_mux=yes

را فعال می‌کند.

اگر ICE Connected است ولی DTLS شکست می‌خورد

علت‌های محتمل:

🔹 Endpoint WebRTC به‌درستی تعریف نشده است.

🔹 Fingerprint بین SDP دو طرف سازگار نیست.

🔹 DTLS Certificate/Private Key قابل استفاده نیست.

🔹 SDP توسط SBC/Proxy نامناسب تغییر کرده است.

🔹 Packetهای DTLS روی مسیر Media Drop می‌شوند.

WSS Certificate را با DTLS Certificate اشتباه نگیرید

این خطا بسیار رایج است.

Certificate مربوط به:

wss://pbx.example.com:8089/ws

برای Signaling است.

DTLS Media نیز Certificate/Fingerprint خودش را دارد.

ممکن است WSS کاملاً سالم باشد و DTLS Media شکست بخورد.

مرحله ۶: RTP را روی Asterisk ببینید

اگر Asterisk دارید، ابتدا SIP Logger:

pjsip set logger on

و سپس RTP Debug:

rtp set debug on

را فقط هنگام تست کوتاه فعال کنید؛ روی سرور پرترافیک Output آن می‌تواند بسیار زیاد شود.

چه نتیجه‌ای مهم است؟

سه حالت داریم.

حالت اول: Asterisk هیچ Media Packet دریافت نمی‌کند

مشکل احتمالاً قبل از Asterisk است:

🔹 ICE Pair

🔹 TURN

🔹 NAT

🔹 Firewall

🔹 Candidate Address

حالت دوم: Asterisk Packet دریافت می‌کند ولی برنمی‌گرداند

بررسی کنید:

🔹 Media Destination

🔹 Codec Negotiation

🔹 Bridge State

🔹 Route خروجی

حالت سوم: Asterisk هم Send و هم Receive دارد

اگر Browser هنوز بی‌صداست، روی:

🔹 Selected Candidate Pair

🔹 Browser getStats

🔹 Remote Track

🔹 Audio Playback

تمرکز کنید.

Packet Capture روی Server

برای Range نمونه RTP Asterisk:

tcpdump -ni any udp portrange 10000-20000

اگر در `rtp.conf` Range دیگری دارید، همان مقدار واقعی را استفاده کنید.

Capture کامل‌تر برای یک Client خاص

tcpdump -ni any host 198.51.100.25 -w /tmp/webrtc-media.pcap

IP مثال است.

فایل را بعداً در Wireshark بررسی کنید.

در WebRTC Packet Capture همیشه RTP خوانا نیست

Media مرورگر معمولاً SRTP است.

بنابراین در Wireshark ممکن است Packetها را ببینید ولی Payload صوت مستقیماً Decode نشود.

برای تشخیص اولیه همین سؤال مهم است:

آیا Packet دوطرفه عبور می‌کند یا خیر؟

مرحله ۷: NAT روی Asterisk را بررسی کنید

اگر Asterisk خودش پشت NAT است، Network Configuration باید Public Address را درست Advertise کند.

در PJSIP Transport معمولاً مواردی مانند:

external_signaling_address=
external_media_address=
local_net=

با توجه به Topology شبکه اهمیت دارند.

مقدار دقیق را از شبکه خودتان بگیرید؛ Public IP یا CIDR نمونه اینترنت را Copy نکنید.

علامت کلاسیک NAT اشتباه

اگر در SDP سمت اینترنت هنوز چیزی شبیه:

c=IN IP4 10.10.0.15

می‌بینید و Client اینترنتی قرار است Media مستقیم بفرستد، Topology را دوباره بررسی کنید.

WebRTC با ICE همیشه فقط از c= خط SDP پیروی نمی‌کند

این نکته مهم است.

در WebRTC، ICE Candidateها تعیین‌کننده اصلی Connectivity هستند.

پس فقط خط:

c=IN IP4 ...

را نبینید؛ Candidateها و Selected Pair را هم بررسی کنید.

مرحله ۸: Firewall را بر اساس Packet بررسی کنید

برای رفع سریع مشکل، کل Firewall را خاموش نکنید.

اول مشخص کنید:

Packet باید از کجا وارد شود؟

روی چه Portی؟

به کدام مقصد؟

بعد فقط Rule لازم را اصلاح کنید.

Firewallهای درگیر ممکن است چندتا باشند

🔹 Firewall خود Server

🔹 Cloud Firewall یا Security Group

🔹 Router/NAT Gateway

🔹 Firewall سازمان کاربر

🔹 Firewall TURN Server

یک اشتباه رایج TURN

Port 3478 باز است.

Browser حتی می‌تواند Allocate Request انجام دهد.

اما Relay UDP Port Range روی Firewall بسته است.

نتیجه:

TURN ظاهراً Online است ولی Media عبور نمی‌کند.

مرحله ۹: Codec را بعد از Network بررسی کنید

اگر ICE و DTLS سالم هستند و Packet وجود دارد، Codec اهمیت پیدا می‌کند.

WebRTC معمولاً با Opus بسیار خوب کار می‌کند.

مثلاً Endpoint Asterisk:

disallow=all
allow=opus,ulaw,alaw

اگر هیچ Codec مشترکی وجود نداشته باشد

معمولاً Call Setup یا SDP Negotiation به مشکل می‌خورد و ممکن است Responseهایی مثل 488 ببینید.

اما اگر تماس برقرار است و Packet وجود دارد، Codec Negotiation و Decoder/Playback را همچنان بررسی کنید.

چرا مشکل فقط در تماس Browser به SIP Trunk دیده می‌شود؟

ممکن است Browser با:

Opus + DTLS-SRTP

و Carrier با:

PCMA + RTP

کار کند.

در نتیجه Asterisk یا Media Proxy باید بین دو Media Profile تطبیق ایجاد کند.

اگر RTPengine دارید چه؟

وقتی RTPengine بین WebRTC و Asterisk یا SIP Trunk قرار دارد، Media Troubleshooting یک Layer دیگر پیدا می‌کند.

مسیر:

Browser
   |
ICE / DTLS-SRTP
   |
RTPengine
   |
RTP/SRTP
   |
Asterisk

است.

باید هر Leg جداگانه بررسی شود.

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

SDP هم روی Asterisk و هم روی RTPengine با Policyهای متناقض Rewrite می‌شود.

در چنین حالتی Media Address یا ICE Candidate ممکن است غیرمنتظره شود.

از ابتدا مشخص کنید مالک Media NAT و SDP Rewrite کدام Layer است.

اگر تماس پس از ۳۰ ثانیه قطع می‌شود

این الزاماً همان مشکل «no audio» نیست.

قطع نزدیک ۳۰ ثانیه معمولاً شما را دوباره به Signaling و ACK/Transaction هدایت می‌کند.

پس دو مشکل را یکی نکنید:

تماس برقرار و بی‌صدا

با:

تماس بعد از مدت ثابت قطع می‌شود

مسیر عیب‌یابی یکسانی ندارند.

اگر فقط صدای ورودی نداریم

از Browser شروع کنید.

در `getStats()` ببینید:

inbound-rtp → packetsReceived

آیا افزایش پیدا می‌کند؟

اگر صفر است، Media به Browser نمی‌رسد.

اگر افزایش دارد، Playback را بررسی کنید.

اگر فقط صدای خروجی نداریم

بررسی کنید:

🔹 Local Audio Track وجود دارد.

🔹 Track روی enabled است.

🔹 Sender به PeerConnection اضافه شده است.

🔹 outbound-rtp packetsSent افزایش پیدا می‌کند.

نمونه بررسی Track محلی

const senders = peerConnection.getSenders();

senders.forEach(sender => {
  if (sender.track) {
    console.log(
      sender.track.kind,
      sender.track.enabled,
      sender.track.readyState
    );
  }
});

readyState روی ended است؟

اگر Microphone Track پایان یافته باشد، PeerConnection می‌تواند هنوز برقرار باشد ولی Audio جدیدی ارسال نشود.

این موضوع مخصوصاً بعد از تغییر Audio Device یا Reconnect کردن Headset قابل بررسی است.

یک Decision Tree سریع

تماس بی‌صداست.

آیا ICE Connected است؟

🔹 خیر → Candidate، STUN، TURN، NAT و Firewall.

🔹 بله → DTLS را بررسی کنید.

آیا DTLS موفق است؟

🔹 خیر → Fingerprint، Certificate، SDP و Media Path.

🔹 بله → RTP/SRTP Packet را بررسی کنید.

Packet به Browser می‌رسد؟

🔹 خیر → Routing، Firewall، NAT، TURN.

🔹 بله → Codec، Remote Track، Audio Element و Output Device.

سناریوی ۱: روی Wi-Fi خانه کار می‌کند ولی روی اینترنت موبایل نه

احتمال زیاد باید ICE Path دو شبکه را مقایسه کنید.

روی Mobile ممکن است CGNAT متفاوتی وجود داشته باشد.

Selected Candidate Pair را روی هر دو اتصال ثبت کنید.

اگر Wi-Fi از `srflx` و Mobile فقط با `relay` کار می‌کند، TURN برای این کاربران ضروری است.

سناریوی ۲: داخل شرکت کار نمی‌کند ولی بیرون شرکت سالم است

موارد احتمالی:

🔹 Corporate Firewall

🔹 UDP Restriction

🔹 TLS Inspection

🔹 Proxy Policy

TURN روی Transport مناسب می‌تواند مسیر جایگزین ایجاد کند.

سناریوی ۳: TURN Candidate ساخته نمی‌شود

بررسی کنید:

🔹 TURN Hostname Resolve می‌شود؟

🔹 Credential معتبر است؟

🔹 Listener Port در دسترس است؟

🔹 Realm و Authentication درست است؟

🔹 Browser Console خطای ICE Candidate نشان می‌دهد؟

روی TURN Server Portها را ببینید

ss -lntup | grep -E '3478|5349'

سناریوی ۴: relay Candidate داریم ولی باز هم صدا نیست

وجود Candidate به معنی کامل‌شدن مسیر نیست.

بررسی کنید:

آیا همان relay Candidate در Selected Pair استفاده شده است؟

اگر بله:

🔹 Relay Port Range باز است؟

🔹 TURN Server به Asterisk دسترسی دارد؟

🔹 Public/External IP درست Advertise شده؟

🔹 DTLS بعد از ICE موفق شده؟

سناریوی ۵: ICE Completed ولی Packet Loss صددرصد است

Connectivity Check موفق شده ولی مسیر Media واقعی ممکن است مشکل داشته باشد.

Capture دو سمت را مقایسه کنید.

فقط به State مرورگر اعتماد نکنید.

سناریوی ۶: صدا چند ثانیه می‌آید و بعد قطع می‌شود

این الگو می‌تواند به:

🔹 NAT Mapping Timeout

🔹 Firewall State

🔹 ICE Restart

🔹 Network Handover

مربوط باشد.

Timeline مرورگر و Server Packet Capture را کنار هم بگذارید.

سناریوی ۷: کاربر صدا می‌شنود ولی Asterisk چیزی دریافت نمی‌کند

اگر صدای دریافتی Browser از سمت دیگری می‌آید ولی Media خروجی Browser به Asterisk نمی‌رسد، Local Track و outbound-rtp را بررسی کنید.

ممکن است مشکل اصلاً شبکه نباشد و Microphone Track ارسال نشده باشد.

از `connectionState` هم استفاده کنید

`RTCPeerConnection.connectionState` وضعیت کلی Peer Connection را نشان می‌دهد.

مقادیر مهم:

🔹 connecting

🔹 connected

🔹 disconnected

🔹 failed

اما برای تشخیص Media بهتر است در کنار آن:

`iceConnectionState` و Statistics واقعی RTP

را هم ببینید.

Logging ساده سمت Browser

peerConnection.addEventListener(
  "iceconnectionstatechange",
  () => {
    console.log(
      "ICE:",
      peerConnection.iceConnectionState
    );
  }
);

peerConnection.addEventListener(
  "connectionstatechange",
  () => {
    console.log(
      "Connection:",
      peerConnection.connectionState
    );
  }
);

برای Production چه چیزی Log کنیم؟

بدون ذخیره اطلاعات حساس، برای هر تماس ثبت کنید:

🔹 Call ID

🔹 ICE State

🔹 Selected Candidate Type

🔹 استفاده یا عدم استفاده از TURN

🔹 Codec انتخاب‌شده

🔹 packetsSent/Received

🔹 packetsLost

🔹 jitter

این اطلاعات برای پیدا کردن الگوهای مشکل بین ISPها بسیار ارزشمند است.

در Log، IP خصوصی کاربران را بی‌دلیل نگه ندارید

ICE Diagnostics می‌تواند اطلاعات شبکه کاربر را آشکار کند.

Retention، Masking و دسترسی به Log را مطابق نیاز واقعی و سیاست حریم خصوصی طراحی کنید.

WebRTC no audio در معماری Asterisk + Kamailio + RTPengine

اگر معماری شما چندلایه است، مسیر را به Legهای کوچک تقسیم کنید.

Browser
   |
WebRTC Media
   |
RTPengine
   |
RTP/SRTP
   |
Asterisk
   |
Carrier

نپرسید:

«چرا صدا نداریم؟»

بپرسید:

در کدام Leg اولین بار Packet ناپدید می‌شود؟

ترتیب Capture در معماری چندلایه

۱. Browser getStats

۲. RTPengine Interface سمت Browser

۳. RTPengine Interface سمت Asterisk

۴. Asterisk RTP Debug

۵. Carrier Leg

اولین جایی که Packet ورودی دارد ولی خروجی ندارد، محدوده مشکل را کوچک می‌کند.

چک‌لیست نهایی WebRTC بدون صدا

🔹 Microphone Permission فعال است.

🔹 Audio Track محلی ساخته شده است.

🔹 ICE Gathering کامل می‌شود.

🔹 Candidateهای منطقی وجود دارند.

🔹 در صورت نیاز relay Candidate داریم.

🔹 Selected Candidate Pair موفق است.

🔹 ICE Connected/Completed است.

🔹 DTLS Fingerprint وجود دارد.

🔹 DTLS Handshake موفق است.

🔹 RTP/SRTP Portهای لازم باز هستند.

🔹 Asterisk Packet دریافت و ارسال می‌کند.

🔹 Codec مشترک وجود دارد.

🔹 Browser Remote Track دریافت می‌کند.

🔹 Audio Element Muted نیست.

🔹 Output Device درست است.

پرسش‌های رایج

چرا تماس WebRTC برقرار می‌شود اما صدا ندارد؟

چون Signaling و Media مسیرهای جدا دارند. ممکن است SIP و WSS کاملاً سالم باشند اما ICE، DTLS-SRTP، NAT، TURN، RTP Firewall یا پخش Audio مرورگر مشکل داشته باشد.

از کجا بفهمیم مشکل ICE است؟

اگر `iceConnectionState` روی `checking` بماند یا به `failed` برسد، ابتدا Candidateها، STUN، TURN، NAT و Firewall را بررسی کنید.

تفاوت host و srflx و relay چیست؟

host آدرس مستقیم Interface است، srflx معمولاً Public Mapping کشف‌شده از طریق STUN است و relay آدرسی است که TURN Server برای عبور Media در اختیار Connection قرار می‌دهد.

از کجا بفهمیم تماس واقعاً از TURN استفاده می‌کند؟

Selected Candidate Pair را بررسی کنید. اگر Candidate انتخاب‌شده از نوع `relay` باشد، Media از TURN عبور می‌کند.

اگر relay Candidate نداریم یعنی TURN خراب است؟

اگر TURN در RTCConfiguration تعریف شده ولی هیچ relay Candidate ایجاد نمی‌شود، Credential، DNS، Listener Port، Firewall و تنظیمات TURN را بررسی کنید. اما اگر TURN اصلاً تعریف نشده یا Direct ICE موفق است، نبود relay الزاماً خطا نیست.

ICE Connected است ولی هنوز صدا نداریم؛ قدم بعد چیست؟

DTLS Handshake، SRTP Packetها، Codec و Browser Playback را بررسی کنید. ICE Connected فقط نشان می‌دهد یک مسیر ارتباطی پیدا شده است.

چرا صدا فقط یک‌طرفه است؟

معمولاً یکی از جهت‌های RTP/SRTP به‌دلیل NAT، Firewall، Candidate اشتباه یا Routing ناقص عبور نمی‌کند. bytesSent و bytesReceived در WebRTC Stats کمک زیادی می‌کنند.

آیا TURN مشکل همه NATها را حل می‌کند؟

TURN یک مسیر Relay بسیار مفید است، اما خود TURN نیز باید Public Reachability، Authentication، Relay Port Range و Routing درست داشته باشد.

DTLS چه ارتباطی با صدا دارد؟

در WebRTC، DTLS معمولاً برای مذاکره کلیدهای SRTP استفاده می‌شود. اگر ICE سالم باشد ولی DTLS Handshake شکست بخورد، Media رمزنگاری‌شده قابل راه‌اندازی نیست.

اگر Asterisk RTP دریافت می‌کند ولی Browser صدا ندارد چه؟

ببینید Asterisk RTP برگشتی ارسال می‌کند یا نه. اگر Browser نیز bytesReceived دارد، مشکل احتمالاً در Remote Track، Audio Element، Output Device یا Playback Policy مرورگر است.

آیا برای WebRTC حتماً TURN لازم است؟

خیر. در شبکه‌هایی که Direct ICE با host یا srflx Candidate موفق می‌شود، TURN استفاده نمی‌شود. TURN برای شبکه‌هایی که مسیر مستقیم ندارند بسیار مهم است.

جمع‌بندی

وقتی WebRTC تماس را برقرار می‌کند اما صدا ندارید، عیب‌یابی را از SIP شروع نکنید و همه تنظیمات را هم‌زمان تغییر ندهید.

ابتدا مطمئن شوید مرورگر Audio Track دارد. سپس Candidateها را ببینید و مشخص کنید ICE کدام مسیر را انتخاب کرده است. اگر Direct Connection ممکن نیست، وجود و استفاده واقعی از Candidate نوع `relay` نشان می‌دهد TURN وارد مسیر شده است.

اگر ICE به Connected یا Completed می‌رسد، Connectivity اولیه برقرار است و باید DTLS-SRTP را بررسی کنید. بعد از موفقیت DTLS، سؤال اصلی این است که آیا RTP/SRTP Packet واقعاً دوطرفه حرکت می‌کند یا خیر.

در Asterisk از `pjsip set logger on` و `rtp set debug on` برای تست کنترل‌شده استفاده کنید و در Browser نیز `getStats()`، ICE State و Selected Candidate Pair را بررسی کنید.

اگر Packet به Browser می‌رسد ولی کاربر همچنان چیزی نمی‌شنود، دیگر TURN و Firewall مظنون اصلی نیستند؛ Remote Track، Audio Element، Mute، Output Device، Codec و Autoplay را بررسی کنید.

بهترین ترتیب عیب‌یابی این است:

Microphone → ICE Candidates → Selected Pair → TURN → DTLS → SRTP → RTP Stats → Browser Playback

با این ترتیب، مشکل «WebRTC no audio» از یک مسئله مبهم به چند مرحله قابل‌اندازه‌گیری تبدیل می‌شود.

منابع و مستندات
ICE Candidate، TURN، DTLS-SRTP، Asterisk WebRTC و ابزارهای عیب‌یابی این مقاله بر اساس مستندات رسمی و منابع به‌روز تا ۱۷ اکتبر ۲۰۲۶ بررسی شده‌اند.
Asterisk WebRTC
مرجع WSS، Endpoint WebRTC، webrtc=yes، DTLS، ICE، RTCP-MUX و تنظیمات رسمی PJSIP برای مرورگر
Asterisk ICE
مرجع ICE در Asterisk و تنظیمات STUN/TURN در لایه RTP
ICE Candidate
مرجع چهار نوع Candidate یعنی host، srflx، prflx و relay و معنی هرکدام در ICE
ICE Connectivity
مرجع Candidate Pair Selection، Candidateهای UDP/TCP و نحوه انتخاب مسیر WebRTC
Peer Connection
مرجع iceConnectionState، connectionState، Gathering State و APIهای اصلی PeerConnection برای Diagnostics
TURN
مرجع نقش TURN به‌عنوان Relay وقتی ارتباط مستقیم میان Peerها امکان‌پذیر نیست
Coturn
مرجع رسمی پروژه Coturn، STUN/TURN Relay، نصب و سرویس‌دهی Media پشت NAT
TURN Security
مرجع Long-Term Credential، TURN REST API، Credentialهای زمان‌دار، Listenerها و Relay Server
زیرساخت پیشنهادی ایرانیکاسرور برای رفع مشکل WebRTC

WebRTC روی بعضی اینترنت‌ها صدا ندارد؟ یک TURN Server مستقل با IP ثابت آزمایش کنید

اگر Web Phone شما روی یک شبکه کار می‌کند اما روی اینترنت موبایل، CGNAT یا شبکه‌های سازمانی بی‌صدا می‌شود، قبل از تغییر Asterisk یک TURN Server مستقل راه‌اندازی کنید و تماس را با `iceTransportPolicy: “relay”` آزمایش کنید. این تست خیلی سریع مشخص می‌کند مشکل از مسیر مستقیم NAT است یا باید جای دیگری دنبال علت بگردید.

برای کاربران داخل ایران، قرارگرفتن TURN و Media Node روی یک VPS ایران با IP ثابت می‌تواند مسیر کوتاه‌تری ایجاد کند. برای کاربران بین‌المللی نیز بهتر است Location سرور به کاربران نزدیک باشد تا Relay باعث Latency اضافی نشود.

مشاوره Asterisk، Coturn، ICE و WebRTC: 021-91302467

اشتراک‌گذاری مقاله
گفت‌وگو درباره آموزش

دیدگاه‌ها (۰)

هنوز دیدگاهی ثبت نشده است.

دیدگاه یا سؤال خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *