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

ساخت تلفن تحت وب با SIP.js؛ راه‌اندازی تماس مرورگری با WSS، WebRTC، TURN و Push

SIP.js یک کتابخانه جاوااسکریپت/TypeScript برای ساخت تلفن نرم‌افزاری داخل مرورگر است. این کتابخانه SIP را از طریق WebSocket به PBX یا SIP Server می‌رساند و برای Media از WebRTC استفاده می‌کند. نتیجه می‌تواند یک…

ساخت تلفن تحت وب با SIP.js؛ راه‌اندازی تماس مرورگری با WSS، WebRTC، TURN و Push
خلاصه سریع این آموزش

SIP.js یک کتابخانه جاوااسکریپت/TypeScript برای ساخت تلفن نرم‌افزاری داخل مرورگر است. این کتابخانه SIP را از طریق WebSocket به PBX یا SIP Server می‌رساند و برای Media از WebRTC استفاده…

۱۴ دقیقه مطالعه ۰ دیدگاه ۲۸ مهر ۱۴۰۵ آخرین به‌روزرسانی

SIP.js یک کتابخانه جاوااسکریپت/TypeScript برای ساخت تلفن نرم‌افزاری داخل مرورگر است. این کتابخانه SIP را از طریق WebSocket به PBX یا SIP Server می‌رساند و برای Media از WebRTC استفاده می‌کند. نتیجه می‌تواند یک تلفن تحت وب باشد که داخل CRM، پنل پشتیبانی، سامانه فروش، داشبورد Call Center یا یک PWA اجرا شود و بدون نصب Softphone جداگانه تماس بگیرد.

اما ساخت یک Web Phone واقعی فقط با چند خط new SimpleUser() تمام نمی‌شود. در Production باید هم‌زمان چند لایه را درست طراحی کنید: WSS و Certificate، دسترسی Microphone، Autoplay، ICE/STUN/TURN، DTLS-SRTP، Reconnect، Registration، تغییر شبکه و محدودیت‌های Background/Push مرورگر.

تا ۲۰ اکتبر ۲۰۲۶، صفحه Release رسمی SIP.js نسخه 0.21.2 را به‌عنوان آخرین Release فهرست می‌کند. خانواده 0.21 همچنین SessionManager را برای سناریوهای چندتماسی اضافه کرده و نسخه 0.21.2 امکان SIP OPTIONS Ping در SessionManager را ارائه می‌کند.

خلاصه معماری: Browser با WSS به Asterisk/Kamailio/SBC وصل می‌شود، SIP Signaling روی WebSocket جابه‌جا می‌شود و صدای تماس از مسیر WebRTC یعنی ICE + DTLS-SRTP عبور می‌کند. WSS فقط Signaling است و به‌تنهایی مشکل NAT یا Media را حل نمی‌کند.

فهرست مطالب

SIP.js دقیقاً چه کاری انجام می‌دهد؟

SIP.js یک SIP User Agent برای محیط JavaScript است. پروژه رسمی آن قابلیت تماس صوتی/تصویری WebRTC، SIP over WebSocket، Hold، Transfer، DTMF، Messaging و Presence را فراهم می‌کند و با SIP Serverهای استاندارد مانند Asterisk و FreeSWITCH سازگار است.

برای توسعه سه سطح اصلی دارید:

سطح مناسب برای محدودیت/مزیت
SimpleUser یک تماس ساده در SPA شروع سریع؛ یک Session هم‌زمان
SessionManager Call Center و چند Session کنترل بیشتر، Reconnect/Retry بهتر
Full API محصول حرفه‌ای سفارشی انعطاف کامل و پیچیدگی بیشتر

اگر فقط یک تلفن تک‌خط می‌خواهید، SimpleUser بهترین نقطه شروع است. اگر چند تماس هم‌زمان، Queue، Holdهای متعدد یا State Management پیچیده دارید، SessionManager منطقی‌تر است.

معماری یک تلفن تحت وب با SIP.js

Browser / SIP.js
      |
      | WSS (SIP signaling)
      v
Asterisk / SBC / SIP Proxy
      |
      +------ SIP Trunk ------ Provider
      |
      +------ RTP/WebRTC Media Path

Browser Media:
getUserMedia()
      |
      v
RTCPeerConnection
      |
 ICE / STUN / TURN
      |
 DTLS-SRTP
      |
      v
PBX / Media Gateway

دو مسیر را از هم جدا ببینید:

🔹 Signaling: REGISTER، INVITE، BYE، REFER و بقیه پیام‌های SIP روی WSS.

🔹 Media: Audio/Video روی WebRTC با ICE و DTLS-SRTP.

به همین دلیل ممکن است SIP REGISTER کاملاً موفق باشد ولی تماس صدا نداشته باشد؛ در این حالت Signaling سالم است اما Media Path شکست خورده است.

WSS؛ اولین شرط یک Web Phone واقعی

صفحه شما در Production باید روی HTTPS اجرا شود و اتصال SIP نیز بهتر است با wss:// باشد. مرورگرها Mixed Content را محدود می‌کنند و طبق راهنمای MDN نباید از صفحه HTTPS یک WebSocket ناامن ws:// باز کنید.

نمونه URL:

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

در Asterisk، WebRTC معمولاً از HTTP/WebSocket داخلی استفاده می‌کند. مستند رسمی Asterisk مثال زیر را برای HTTPS/WSS ارائه می‌کند:

[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088

tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/keys/fullchain.pem
tlsprivatekey=/etc/asterisk/keys/privkey.pem

و Transport مربوط به PJSIP:

[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0

بعد از Reload، این دستور مفید است:

asterisk -rx "http show status"

باید URI مربوط به /ws و HTTPS Listener را ببینید.

Certificate: Self-signed Certificate در WebRTC Production دردسر زیادی ایجاد می‌کند. Asterisk نیز برای Browser Client استفاده از Certificate معتبر عمومی را توصیه می‌کند؛ چون Browser ممکن است اتصال WSS را بدون Dialog واضح رد کند.

تنظیم Endpoint WebRTC در Asterisk

در Asterisk گزینه webrtc=yes چند تنظیم مهم را هم‌زمان فعال می‌کند: rtcp_mux، use_avpf، ice_support و media_use_received_transport. همچنین Media Encryption روی DTLS قرار می‌گیرد و Fingerprint Verification فعال می‌شود.

نمونه ساده:

[web1001]
type=aor
max_contacts=3
remove_existing=yes

[web1001]
type=auth
auth_type=userpass
username=web1001
password=CHANGE_TO_A_LONG_RANDOM_PASSWORD

[web1001]
type=endpoint
aors=web1001
auth=web1001
webrtc=yes
context=from-webphone
disallow=all
allow=opus,ulaw

برای Production، Context این Endpoint را محدود طراحی کنید و Credential مستقل برای هر User داشته باشید. Password Trunk یا Credential مدیریتی را هرگز داخل Frontend قرار ندهید.

یک نمونه ساده SIP.js برای تماس صوتی

ابتدا نصب:

npm install sip.js

در HTML یک Audio Element برای صدای Remote قرار دهید:

<audio id="remoteAudio" playsinline></audio>

نمونه TypeScript/JavaScript:

import {{ Web }} from "sip.js";

const remoteAudio = document.getElementById("remoteAudio");

if (!(remoteAudio instanceof HTMLAudioElement)) {{
  throw new Error("remoteAudio element not found");
}}

const server = "wss://pbx.example.com:8089/ws";

const phone = new Web.SimpleUser(server, {{
  aor: "sip:web1001@example.com",

  media: {{
    constraints: {{
      audio: true,
      video: false
    }},
    remote: {{
      audio: remoteAudio
    }}
  }},

  reconnectionAttempts: 5,
  reconnectionDelay: 4,

  registererOptions: {{
    expires: 600
  }},

  userAgentOptions: {{
    authorizationUsername: "web1001",
    authorizationPassword: "USER_SPECIFIC_SECRET",
    displayName: "Web Phone 1001"
  }}
}});

phone.delegate = {{
  onServerConnect: () => {{
    console.log("WSS connected");
  }},

  onServerDisconnect: (error) => {{
    console.warn("WSS disconnected", error);
  }},

  onRegistered: () => {{
    console.log("SIP registered");
  }},

  onCallReceived: () => {{
    console.log("Incoming call");
  }},

  onCallHangup: () => {{
    console.log("Call ended");
  }}
}};

await phone.connect();
await phone.register();

برای تماس خروجی:

await phone.call("sip:1002@example.com");

برای پاسخ به تماس ورودی:

await phone.answer();

این مثال برای آموزش معماری است. در محصول واقعی State رابط کاربری، خطاها، Permission، Reconnect، Audio Playback و Call Lifecycle را جدا مدیریت کنید.

مشکل اول: Microphone Permission

WebRTC برای Microphone از navigator.mediaDevices.getUserMedia() استفاده می‌کند. طبق MDN این API فقط در Secure Context یعنی HTTPS یا localhost در دسترس است و User باید اجازه Microphone بدهد.

قبل از اولین تماس می‌توانید Permission را به شکل کنترل‌شده درخواست کنید:

async function checkMicrophone() {{
  try {{
    const stream = await navigator.mediaDevices.getUserMedia({{
      audio: true,
      video: false
    }});

    stream.getTracks().forEach(track => track.stop());

    return true;
  }} catch (error) {{
    console.error("Microphone permission failed", error);
    return false;
  }}
}}

اگر Web Phone داخل iframe است، ممکن است Permissions Policy هم لازم باشد:

<iframe
  src="https://phone.example.com"
  allow="microphone"
></iframe>

MDN توضیح می‌دهد اگر Microphone توسط Permissions Policy بسته شده باشد، getUserMedia() با NotAllowedError رد می‌شود.

مشکل دوم: تماس Answer شده ولی صدای Remote پخش نمی‌شود

حتی وقتی WebRTC MediaStream درست رسیده، Browser ممکن است پخش خودکار Audio را به‌دلیل Autoplay Policy متوقف کند. فراخوانی play() می‌تواند با NotAllowedError رد شود.

بنابراین همیشه Promise را کنترل کنید:

async function ensureRemoteAudioCanPlay() {{
  try {{
    await remoteAudio.play();
  }} catch (error) {{
    console.warn("Autoplay blocked", error);

    // Show a visible button:
    // "فعال‌کردن صدای تماس"
  }}
}}

بهترین UX این است که User قبل از استفاده از تلفن یک Interaction واضح مثل «فعال‌کردن تلفن» یا «شروع کار» داشته باشد. به Autoplay کورکورانه تکیه نکنید.

مشکل سوم: REGISTER موفق است ولی Media برقرار نمی‌شود

این مشکل معمولاً WSS نیست. SIP Signaling به PBX رسیده ولی ICE نتوانسته مسیر Media مناسبی بسازد.

مرورگر از RTCPeerConnection و ICE استفاده می‌کند. STUN به Client کمک می‌کند Candidate عمومی پیدا کند و TURN در شبکه‌هایی که مسیر مستقیم ممکن نیست Media را Relay می‌کند.

ساختار مفهومی:

Browser
   |
   +--> host candidate
   |
   +--> STUN -> srflx candidate
   |
   +--> TURN -> relay candidate
                 |
                 v
             Media Path

در WebRTC Production داشتن فقط STUN معمولاً کافی نیست. Corporate Firewall، CGNAT، Symmetric NAT و Mobile Network می‌توانند Candidate مستقیم را شکست دهند؛ TURN باید به‌عنوان Fallback وجود داشته باشد.

نمونه Configuration برای Peer Connection در سطح UserAgentOptions:

sessionDescriptionHandlerFactoryOptions: {{
  peerConnectionConfiguration: {{
    iceServers: [
      {{
        urls: "stun:stun.example.com:3478"
      }},
      {{
        urls: "turn:turn.example.com:3478",
        username: "short-lived-user",
        credential: "short-lived-secret"
      }},
      {{
        urls: "turns:turn.example.com:5349",
        username: "short-lived-user",
        credential: "short-lived-secret"
      }}
    ],
    iceTransportPolicy: "all"
  }}
}}

Credentialهای TURN را ترجیحاً Short-lived بسازید و Secret ثابت عمومی داخل Bundle Frontend قرار ندهید.

مطلب مرتبط: اگر برای WebRTC به Relay نیاز دارید، مقاله Coturn ایرانیکاسرور را هم ببینید.

راه‌اندازی Coturn روی VPS و ساخت TURN Server

ICE State را در UI واقعی نمایش دهید

به‌جای نمایش یک Status کلی «تماس برقرار است»، وضعیت ICE را هم مانیتور کنید:

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

Stateهای مهم شامل checking، connected، completed، disconnected و failed هستند. اگر SIP Call Established است ولی ICE روی failed رفته، مشکل را در NAT/TURN/Firewall دنبال کنید نه در Dialplan.

Reconnect؛ قطع اینترنت را بخشی از طراحی بدانید

در لپ‌تاپ و موبایل، تغییر Wi-Fi، Sleep/Wake، VPN و جابه‌جایی شبکه طبیعی است. یک Web Phone نباید با اولین Disconnect تا Refresh صفحه مرده بماند.

SIP.js برای SimpleUser و SessionManager گزینه‌های reconnectionAttempts و reconnectionDelay دارد. در API سطح پایین‌تر نیز مستند رسمی نمونه‌ای برای userAgent.reconnect()، Re-register و Event آنلاین Browser ارائه می‌کند.

برای UI:

window.addEventListener("online", () => {{
  console.log("Browser is online again");
}});

window.addEventListener("offline", () => {{
  console.log("Network unavailable");
}});

اما فقط به Event online اعتماد نکنید؛ آنلاین‌بودن Browser به معنی سالم‌بودن WSS یا Registrar نیست.

OPTIONS Ping در SessionManager

در Release 0.21.2، SIP.js گزینه OPTIONS Ping را به SessionManager اضافه کرده است. در API فعلی گزینه‌های optionsPingInterval و optionsPingRequestURI وجود دارند و برای تشخیص Availability مسیر SIP مفیدند.

این Ping جای WebSocket State یا Application Health Monitoring کامل را نمی‌گیرد؛ فقط یک Signal دیگر برای تشخیص زنده‌بودن مسیر است.

Background Tab با «برنامه بسته» فرق دارد

یکی از بزرگ‌ترین اشتباه‌ها در ساخت Web Phone این است که تصور کنیم اگر Tab در پس‌زمینه رفت، همیشه مثل یک Softphone Native زنده می‌ماند.

MDN توضیح می‌دهد Browserها Timerهای Tabهای Background را Throttle می‌کنند؛ WebSocket و WebRTC در بسیاری از حالت‌ها برای جلوگیری از Timeout از بخشی از این Throttling معاف‌اند. اما این به معنی تضمین ۲۴ ساعته نیست. سیستم‌عامل، Mobile Browser، Memory Pressure، Sleep و بسته‌شدن Tab می‌توانند Session را متوقف کنند.

نتیجه مهم: «Tab مخفی» ممکن است هنوز WebSocket فعال داشته باشد؛ ولی «Browser/App بسته» را نباید مثل SIP Phone همیشه Registered فرض کنید.

Push Notification برای تماس ورودی چه کمکی می‌کند؟

Push API می‌تواند حتی وقتی Web App در Foreground نیست، Service Worker را برای یک Push Event فعال کند و Notification نشان دهد. این قابلیت برای اعلام «تماس ورودی دارید» مفید است.

اما Service Worker یک Process دائمی نیست. طبق MDN، Service Worker می‌تواند وقتی Idle است Terminate شود و هنگام Event دوباره Start شود. بنابراین طراحی «یک SIP WebSocket دائمی داخل Service Worker» قابل اتکا نیست.

معماری منطقی برای PWA:

Incoming SIP call
      |
      v
Backend / PBX integration
      |
      v
Web Push Service
      |
      v
Service Worker wakes
      |
      v
Show incoming-call notification
      |
      v
User taps notification
      |
      v
Open / focus Web App
      |
      v
Reconnect WSS + Register
      |
      v
Continue app-specific call flow

این Workflow باید با Call Routing واقعی شما هماهنگ باشد. Push خودش SIP INVITE را به Browser تبدیل نمی‌کند و تضمین نمی‌کند Call Session بازمانده روی PBX تا زمان بازشدن App هنوز قابل Answer باشد.

چرا برای تماس ورودی Background باید Backend داشته باشیم؟

اگر Pure Browser Client بسته باشد، WSS آن هم وجود ندارد. در این وضعیت PBX باید بداند چطور Event تماس ورودی را به Backend شما بدهد تا Backend Push Notification بسازد، Timeout تماس را مدیریت کند یا Route جایگزین داشته باشد.

برای تجربه‌ای واقعاً شبیه تماس Native روی موبایل ــ مخصوصاً وقتی App کامل بسته است ــ معمولاً Wrapper/Native App با Push Integration مخصوص Platform قابل‌اتکاتر از Pure Web App است.

Session Recovery؛ Refresh صفحه تماس جاری را نجات نمی‌دهد

اگر User وسط تماس صفحه را Refresh کند، JavaScript Context و RTCPeerConnection قبلی از بین می‌روند. SIP.js نمی‌تواند به‌صورت عمومی یک Browser Session حذف‌شده را دوباره از همان نقطه ادامه دهد.

برای جلوگیری از UX بد:

🔹 هنگام تماس، Refresh/Navigation را در UI واضح کنید.

🔹 State تماس را در Backend هم نگه دارید.

🔹 در صورت Reload، سریع Reconnect/Register کنید.

🔹 برای Call Recovery از Flow اختصاصی PBX/Application استفاده کنید، نه انتظار از Browser State قدیمی.

امنیت Credential در SIP.js

اگر Browser مستقیماً REGISTER می‌کند، Credential همان User باید در Runtime Client موجود باشد. بنابراین:

🔹 Credential مدیریتی یا SIP Trunk را داخل Frontend قرار ندهید.

🔹 برای هر کاربر Account جدا داشته باشید.

🔹 دسترسی Dialplan همان Account را محدود کنید.

🔹 Password را داخل Repository یا Bundle هاردکد نکنید.

🔹 در صورت امکان Credential موقت یا Provisioning امن از Backend طراحی کنید.

🔹 WSS و HTTPS با Certificate معتبر اجباری باشند.

Obfuscate کردن JavaScript راه امنیتی نیست؛ User Browser به کدی که روی دستگاه خودش اجرا می‌شود دسترسی دارد.

Checklist قبل از Production

بخش وضعیت مطلوب
Frontend HTTPS معتبر
SIP Transport WSS با Certificate معتبر
PBX WebRTC Endpoint با DTLS-SRTP و ICE
Microphone Permission Flow واضح
Remote Audio Autoplay Error Handling
ICE STUN + TURN Production
Reconnect WSS Reconnect + Re-register
Network Change Online/offline + ICE State Monitoring
Background عدم اتکا به Tab برای Always-On
Incoming Push Backend + Service Worker + Notification
Credential User-specific، محدود و غیرهاردکد
Monitoring WSS، SIP Response، ICE و Call Metrics

معماری پیشنهادی برای یک Web Phone سازمانی

                    +------------------+
                    |  Web App Backend |
                    | auth / push / API|
                    +--------+---------+
                             |
                    Web Push / HTTPS
                             |
                             v
+---------+      WSS      +------+       SIP       +----------+
| Browser | ------------> | SBC  | --------------> | Asterisk |
| SIP.js  |               +------+                 +----------+
+----+----+                   |
     |                        |
     | WebRTC Media           |
     | ICE / DTLS-SRTP        |
     v                        v
 STUN/TURN  <-----------  Media Path
     |
     v
 coturn

این معماری بهتر از اتصال مستقیم همه Browserها به یک PBX خام است؛ چون لایه Backend برای Auth/Push و SBC برای Edge Control را جدا می‌کند. در پروژه کوچک می‌توانید بعضی اجزا را ساده‌تر کنید، اما مسئولیت هر بخش باید روشن باشد.

Web Phone خوب فقط UI زیبا نیست؛ WSS، TURN، Reconnect و Push باید از ابتدا طراحی شوند

می‌خواهید تلفن تحت وب SIP.js را روی Asterisk راه‌اندازی کنید؟

برای یک استقرار Production باید PBX، WSS، Certificate، STUN/TURN، Route تماس، Security و رفتار Background مشخص باشند. بعد می‌توان Frontend و زیرساخت را بدون وابستگی به تنظیم‌های موقت Browser پیاده‌سازی کرد.

ایرانیکاسرور می‌تواند برای تهیه VPS، راه‌اندازی Asterisk، WSS، TURN و معماری WebRTC کمک کند.

تماس با پشتیبانی ایرانیکاسرور: 021-91302467

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

SIP.js چیست؟

SIP.js یک کتابخانه JavaScript/TypeScript برای ساخت SIP User Agent در Web است. Signaling را از طریق WebSocket و Media را با WebRTC مدیریت می‌کند.

برای SIP.js حتماً WSS لازم است؟

در Production روی صفحه HTTPS عملاً باید WSS داشته باشید. Browserها Mixed Content را محدود می‌کنند و Certificate نامعتبر نیز می‌تواند اتصال را خراب کند.

چرا Microphone در SIP.js باز نمی‌شود؟

getUserMedia فقط در Secure Context کار می‌کند و User باید Permission بدهد. Permissions Policy یا iframe بدون اجازه Microphone نیز می‌تواند NotAllowedError ایجاد کند.

برای SIP.js فقط STUN کافی است؟

نه همیشه. در NAT و Firewallهای سخت، TURN باید به‌عنوان Relay Fallback وجود داشته باشد. WebRTC از ICE برای انتخاب مسیر مناسب استفاده می‌کند.

SIP.js بعد از قطع اینترنت خودکار Reconnect می‌شود؟

SimpleUser و SessionManager گزینه‌های Reconnection دارند، اما Application باید State، Re-registration و تغییر شبکه را هم مدیریت و مانیتور کند.

آیا Web Phone وقتی Browser بسته است تماس ورودی می‌گیرد؟

نباید روی WebSocket همیشه‌فعال در Browser بسته تکیه کنید. Web Push می‌تواند Service Worker را برای Notification بیدار کند، اما Service Worker Process دائمی SIP نیست و Call Flow باید با Backend/PBX هماهنگ شود.

چرا تماس وصل است ولی صدای Remote پخش نمی‌شود؟

ممکن است Browser Autoplay را Block کرده باشد. Promise مربوط به HTMLMediaElement.play() را کنترل کنید و در صورت NotAllowedError یک دکمه تعامل مستقیم برای فعال‌کردن صدا نشان دهید.

SimpleUser یا SessionManager کدام بهتر است؟

برای یک تماس ساده و یک Session هم‌زمان SimpleUser مناسب است. برای چند تماس هم‌زمان و مدیریت پیشرفته Sessionها، SessionManager گزینه مناسب‌تری است.

جمع‌بندی

برای ساخت تلفن نرم‌افزاری تحت وب با SIP.js ابتدا Signaling و Media را جدا ببینید: SIP روی WSS و Media روی WebRTC با ICE و DTLS-SRTP حرکت می‌کند.

بیشترین خطاهای Production از خود SIP.js نیستند؛ Certificate WSS، Permission Microphone، Autoplay، NAT/TURN و Reconnect معمولاً نقاط شکست اصلی‌اند.

اگر Web Phone باید تماس ورودی را حتی در Background یا بعد از بسته‌شدن App اعلام کند، Pure WebSocket کافی نیست. Push Notification و Backend باید در معماری حضور داشته باشند و محدودیت چرخه عمر Service Worker را در نظر بگیرید.

برای محصول ساده با یک تماس، SimpleUser شروع خوبی است؛ برای Call Center یا چند Session هم‌زمان، SessionManager یا Full API کنترل لازم را می‌دهد.

منابع و مستندات
نسخه SIP.js، WSS، WebRTC Endpoint، Microphone Permission، Autoplay، ICE/STUN/TURN، Reconnect و محدودیت‌های Background/Push این مقاله تا ۲۰ اکتبر ۲۰۲۶ با منابع رسمی بررسی شده‌اند.
SIP.js
مرجع معماری SIP over WebSocket، WebRTC، SimpleUser، SessionManager و API اصلی SIP.js.
SIP.js Releases
مرجع نسخه 0.21.2 و تغییرات 0.21.x از جمله SessionManager و OPTIONS Ping.
Asterisk WebRTC
مرجع HTTPS/WSS، پورت 8089، /ws، Transport WSS و Endpoint با webrtc=yes.
MDN Media
مرجع Secure Context، Permission Microphone و محدودیت‌های iframe/Permissions Policy.
MDN WebRTC
مرجع iceServers، STUN/TURN و Credentialهای TURN در RTCPeerConnection.
MDN Audio
مرجع Autoplay Policy و خطای NotAllowedError هنگام پخش خودکار Audio.
MDN Background
مرجع Push، Notification و محدودیت Background Work در Browser/PWA.
MDN Service Worker
مرجع Terminate شدن Service Worker هنگام Idle و راه‌اندازی مجدد آن هنگام Event.
اشتراک‌گذاری مقاله
گفت‌وگو درباره آموزش

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

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

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

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