59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
"""WebRTC ICE server config: STUN + optional TURN for cross-network voice preview."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
import hashlib
|
|
import hmac
|
|
import time
|
|
|
|
import settings
|
|
|
|
|
|
def _turn_credentials() -> tuple[str, str] | None:
|
|
"""Return (username, credential) for TURN, or None when TURN is not configured."""
|
|
if not settings.TURN_URLS:
|
|
return None
|
|
if settings.TURN_SECRET:
|
|
expiry = int(time.time()) + settings.TURN_CREDENTIAL_TTL
|
|
username = f"{expiry}:ai-video"
|
|
credential = base64.b64encode(
|
|
hmac.new(
|
|
settings.TURN_SECRET.encode("utf-8"),
|
|
username.encode("utf-8"),
|
|
hashlib.sha1,
|
|
).digest()
|
|
).decode("utf-8")
|
|
return username, credential
|
|
if settings.TURN_USERNAME and settings.TURN_PASSWORD:
|
|
return settings.TURN_USERNAME, settings.TURN_PASSWORD
|
|
return None
|
|
|
|
|
|
def client_ice_servers() -> list[dict]:
|
|
"""ICE servers for browser RTCPeerConnection (JSON-serializable)."""
|
|
servers: list[dict] = [{"urls": settings.STUN_URL}]
|
|
creds = _turn_credentials()
|
|
if not creds:
|
|
return servers
|
|
username, credential = creds
|
|
for url in settings.TURN_URLS:
|
|
servers.append({"urls": url, "username": username, "credential": credential})
|
|
return servers
|
|
|
|
|
|
def aiortc_ice_servers() -> list:
|
|
"""ICE servers for backend SmallWebRTCConnection / aiortc."""
|
|
from aiortc import RTCIceServer
|
|
|
|
servers = [RTCIceServer(urls=settings.STUN_URL)]
|
|
creds = _turn_credentials()
|
|
if not creds:
|
|
return servers
|
|
username, credential = creds
|
|
for url in settings.TURN_URLS:
|
|
servers.append(
|
|
RTCIceServer(urls=url, username=username, credential=credential)
|
|
)
|
|
return servers
|