Files
ai-video-fullstack/backend/services/webrtc_ice.py
2026-08-05 14:05:22 +08:00

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