]>
Commit | Line | Data |
---|---|---|
e2da0c51 RBR |
1 | const internals = { |
2 | peers: {}, | |
3 | ||
4 | createAudioElement(source) { | |
b9a2baf2 RBR |
5 | const audioElement = document.createElement("audio"); |
6 | audioElement.setAttribute("class", "junction-call-audio"); | |
7 | audioElement.autoplay = "autoplay"; | |
06b7617a | 8 | audioElement.srcObject = source; |
d38261f1 | 9 | |
b9a2baf2 | 10 | document.querySelector("body").appendChild(audioElement); |
e2da0c51 RBR |
11 | |
12 | return audioElement; | |
b9a2baf2 | 13 | }, |
e2da0c51 RBR |
14 | }; |
15 | ||
bab26a4d RBR |
16 | export function addPeer({ |
17 | peerId, | |
18 | shouldCreateOffer, | |
19 | mediaStream, | |
20 | onOffer, | |
21 | socket, | |
22 | }) { | |
06b7617a RBR |
23 | const peerConnection = new RTCPeerConnection( |
24 | { iceServers: internals.kIceServers }, | |
25 | { optional: [{ DtlsSrtpKeyAgreement: true }] }, | |
26 | ); | |
e2da0c51 | 27 | |
06b7617a RBR |
28 | internals.peers[peerId] = peerConnection; |
29 | mediaStream.getTracks().forEach((track) => { | |
30 | peerConnection.addTrack(track, mediaStream); | |
31 | }); | |
e2da0c51 | 32 | |
06b7617a RBR |
33 | peerConnection.onicecandidate = (event) => { |
34 | if (event.candidate) { | |
35 | socket.emit("relayICECandidate", { | |
36 | peerId: peerId, | |
37 | candidate: event.candidate, | |
38 | }); | |
39 | } | |
40 | }; | |
e2da0c51 | 41 | |
06b7617a RBR |
42 | const remoteStream = new MediaStream(); |
43 | peerConnection.ontrack = (event) => { | |
44 | remoteStream.addTrack(event.track); | |
45 | const remoteAudioElement = new Audio(); | |
46 | remoteAudioElement.srcObject = remoteStream; | |
47 | remoteAudioElement.play(); | |
48 | }; | |
49 | ||
50 | peerConnection.onnegotiationneeded = async () => { | |
3f2e36ea RBR |
51 | if (shouldCreateOffer) { |
52 | console.debug("Creating RTC offer to ", peerId); | |
53 | const offer = await peerConnection.createOffer(); | |
54 | await peerConnection.setLocalDescription(offer); | |
06b7617a | 55 | |
3f2e36ea RBR |
56 | onOffer({ peerId, offer }); |
57 | } | |
06b7617a RBR |
58 | }; |
59 | ||
60 | console.info(`There are now ${countPeers()} participants`); | |
61 | } | |
62 | ||
63 | export function removePeer({ peerId }) { | |
64 | delete internals.peers[peerId]; | |
65 | console.info(`There are now ${countPeers()} participants`); | |
66 | } | |
67 | ||
68 | export async function answerPeerOffer({ peerId, offer }) { | |
3f2e36ea | 69 | console.info(`Answering peer ${peerId}`); |
06b7617a RBR |
70 | const peerConnection = internals.peers[peerId]; |
71 | ||
72 | const remoteDescription = new RTCSessionDescription(offer); | |
73 | await peerConnection.setRemoteDescription(remoteDescription); | |
74 | ||
75 | const answer = await peerConnection.createAnswer(); | |
76 | await peerConnection.setLocalDescription(answer); | |
77 | ||
78 | return { peerId, answer }; | |
79 | } | |
80 | ||
81 | export async function processPeerAnswer({ peerId, answer }) { | |
3f2e36ea | 82 | console.info(`Processing answer for peer ${peerId}`); |
06b7617a RBR |
83 | const peerConnection = internals.peers[peerId]; |
84 | const remoteDescription = new RTCSessionDescription(answer); | |
85 | await peerConnection.setRemoteDescription(remoteDescription); | |
86 | } | |
87 | ||
88 | export async function addIceCandidate({ peerId, candidate }) { | |
3f2e36ea | 89 | console.info(`Adding ICE candidate for peer ${peerId}`); |
06b7617a | 90 | const peerConnection = internals.peers[peerId]; |
3f2e36ea | 91 | console.info(peerConnection.signalingState); |
06b7617a RBR |
92 | const iceCandidate = new RTCIceCandidate(candidate); |
93 | await peerConnection.addIceCandidate(iceCandidate); | |
94 | } | |
95 | ||
96 | export function countPeers() { | |
97 | return Object.keys(internals.peers).length; | |
98 | } | |
99 | ||
100 | export function resetPeers() { | |
101 | internals.peers = {}; | |
102 | document | |
103 | .querySelectorAll(".junction-call-audio") | |
104 | .forEach((audioElement) => audioElement.remove()); | |
105 | } |