Skip to content

Commit

Permalink
add VIDEO (op 12) handler
Browse files Browse the repository at this point in the history
  • Loading branch information
RuslanUC committed Apr 7, 2024
1 parent 98295ed commit 062993f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 5 deletions.
3 changes: 3 additions & 0 deletions yepcord/voice_gateway/default_sdp.py

Large diffs are not rendered by default.

36 changes: 31 additions & 5 deletions yepcord/voice_gateway/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
from os import urandom
from time import time
from typing import Optional
from uuid import uuid4

from quart import Websocket
from semanticsdp import SDPInfo, Setup
from semanticsdp import SDPInfo, Setup, Direction, StreamInfo, TrackInfo

from yepcord.yepcord.enums import VoiceGatewayOp
from .default_sdp import DEFAULT_SDP
from .default_sdp import DEFAULT_SDP, DEFAULT_SDP_DS
from .events import Event, ReadyEvent, SpeakingEvent, UdpSessionDescriptionEvent, RtcSessionDescriptionEvent
from .go_rpc import GoRpc
from .schemas import SelectProtocol
Expand All @@ -29,7 +30,7 @@ def __init__(self, ws: Websocket, gw: Gateway):
self.rtx_ssrc = 0
self.mode: Optional[str] = None
self.key: Optional[bytes] = None
self.sdp = SDPInfo.from_dict(DEFAULT_SDP)
self.sdp = SDPInfo.from_dict(DEFAULT_SDP_DS)

self._gw = gw

Expand Down Expand Up @@ -84,8 +85,7 @@ async def handle_HEARTBEAT(self, data: dict):

@require_auth(4003)
async def handle_SELECT_PROTOCOL(self, data: dict):
rpc = self._gw.rpc(self.guild_id)
if rpc is None:
if (rpc := self._gw.rpc(self.guild_id)) is None:
return

try:
Expand Down Expand Up @@ -133,6 +133,32 @@ async def handle_SPEAKING(self, data: dict):
return await self.ws.close(4014)
await self.esend(SpeakingEvent(self.ssrc, self.user_id, data["speaking"]))

@require_auth
async def handle_VIDEO(self, data: dict):
if (rpc := self._gw.rpc(self.guild_id)) is None:
return

if (audio_ssrc := data.get("audio_ssrc", 0)) < 1:
return await self.send({"op": VoiceGatewayOp.MEDIA_SINK_WANTS, "d": {"any": "100"}}) # ?

track_id = str(uuid4())
self.sdp.version += 1
self.sdp.medias[0].direction = Direction.SENDRECV
self.sdp.streams["-"] = StreamInfo(
id="-",
tracks={track_id: TrackInfo(
media="audio",
id=track_id,
media_id="0",
ssrcs=[audio_ssrc]
)}
)

sdp = "v=0\r\n" + str(self.sdp) + "\r\n"
await rpc.renegotiate(self.channel_id, self.session_id, sdp)

await self.send({"op": VoiceGatewayOp.MEDIA_SINK_WANTS, "d": {"any": "100"}})

async def handle_VOICE_BACKEND_VERSION(self, data: dict) -> None:
await self.send({"op": VoiceGatewayOp.VOICE_BACKEND_VERSION, "d": {"voice": "0.11.0", "rtc_worker": "0.4.11"}})

Expand Down
31 changes: 31 additions & 0 deletions yepcord/voice_gateway/go_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ def __init__(self, rpc_addr: str):
self._address = f"http://{rpc_addr}/rpc"

async def create_endpoint(self, channel_id: int) -> Optional[int]:
"""
Sends request to pion webrtc server to create new webrtc endpoint.
:param channel_id: Id of channel/guild to associate created endpoint with
:return: Endpoint port answer on success or None on error
"""
async with AsyncClient() as cl:
resp = await cl.post(self._address, json={
"id": 0, "method": "Rpc.CreateApi", "params": [{"channel_id": str(channel_id)}]
Expand All @@ -18,6 +23,13 @@ async def create_endpoint(self, channel_id: int) -> Optional[int]:
print(j["error"])

async def create_peer_connection(self, channel_id: int, session_id: int, offer: str) -> Optional[str]:
"""
Sends request to pion webrtc server to create new peerConnection.
:param channel_id: Id of channel/guild user associated with
:param session_id: Id of voice session
:param offer: Sdp offer
:return: Sdp answer on success or None on error
"""
async with AsyncClient() as cl:
resp = await cl.post(self._address, json={
"id": 0, "method": "Rpc.NewPeerConnection", "params": [
Expand All @@ -28,3 +40,22 @@ async def create_peer_connection(self, channel_id: int, session_id: int, offer:
if j["error"] is None:
return j["result"]
print(j["error"])

async def renegotiate(self, channel_id: int, session_id: int, offer: str) -> Optional[str]:
"""
Sends re-negotiate request to pion webrtc server.
:param channel_id: Id of channel/guild user associated with
:param session_id: Id of voice session
:param offer: Sdp offer
:return: Sdp answer on success or None on error
"""
async with AsyncClient() as cl:
resp = await cl.post(self._address, json={
"id": 0, "method": "Rpc.ReNegotiate", "params": [
{"channel_id": str(channel_id), "session_id": str(session_id), "offer": offer}
]
})
j = resp.json()
if j["error"] is None:
return j["result"]
print(j["error"])

0 comments on commit 062993f

Please sign in to comment.