Mercurial > libervia-web
diff libervia/web/pages/calls/_browser/webrtc.py @ 1616:6bfeb9f0fb84
browser (calls): conferences implementation:
- Handle A/V conferences calls creation/joining by entering a conference room JID in the
search box.
- Group call box has been improved and is used both for group calls (small number of
participants) and A/V conferences (larger number of participants).
- Fullscreen button for group call is working.
- Avatar/user nickname are shown in group call on peer user, as an overlay on video
stream.
- Use `user` metadata when present to display the right user avatar/name when receiving a
stream from SFU (i.e. A/V conference).
- Peer user have a new 3 dots menu with a `pin` item to (un)pin it (i.e. display it on
full container with on top).
- Updated webrtc to handle unidirectional streams correctly and to adapt to A/V conference
specification.
rel 448
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 07 Aug 2024 00:01:57 +0200 |
parents | 4a9679369856 |
children |
line wrap: on
line diff
--- a/libervia/web/pages/calls/_browser/webrtc.py Tue Aug 06 23:56:18 2024 +0200 +++ b/libervia/web/pages/calls/_browser/webrtc.py Wed Aug 07 00:01:57 2024 +0200 @@ -648,12 +648,19 @@ window.pc = self._peer_connection return peer_connection - async def _get_user_media(self, audio: bool = True, video: bool = True) -> None: + async def _get_user_media( + self, + audio: bool = True, + video: bool = True, + direction: str = "sendrecv" + ) -> None: """ Gets user media (camera and microphone). @param audio: True if an audio flux is required. @param video: True if a video flux is required. + @param direction: The direction of the stream ('sendonly', 'recvonly', 'sendrecv', + or 'inactive') """ media_constraints = {"audio": audio, "video": video} if self.local_stream is None: @@ -668,8 +675,12 @@ if self.local_video_elt is not None: self.local_video_elt.srcObject = self.local_stream - for track in self.local_stream.getTracks(): - self._peer_connection.addTrack(track) + if direction != "recvonly": + for track in self.local_stream.getTracks(): + sender = self._peer_connection.addTransceiver(track, { + 'direction': direction, + 'streams': [self.local_stream] + }) async def _replace_user_video( self, @@ -936,7 +947,7 @@ self.remote_stream.addTrack(event.track) def on_negotiation_needed(self, event) -> None: - log.debug(f"on_negotiation_needed {event=}") + log.debug("on_negotiation_needed") # TODO def _on_data_channel(self, event) -> None: @@ -947,7 +958,13 @@ data_channel = event.channel self.file_receiver = FileReceiver(self.sid, data_channel, self.extra_data) - async def answer_call(self, sid: str, offer_sdp: str, profile: str): + async def answer_call( + self, + sid: str, + offer_sdp: str, + profile: str, + conference: bool = False + ): """We respond to the call""" log.debug("answering call") if sid != self.sid: @@ -962,7 +979,9 @@ if self.file_only: self._peer_connection.bind("datachannel", self._on_data_channel) else: - await self._get_user_media() + await self._get_user_media( + direction="recvonly" if conference else "sendrecv" + ) # Gather local ICE candidates local_ice_data = await self._gather_ice_candidates(False) @@ -998,7 +1017,8 @@ async def prepare_call( self, audio: bool = True, - video: bool = True + video: bool = True, + direction: str = "sendrecv" ) -> dict: """Prepare a call. @@ -1009,17 +1029,21 @@ @return: Call Data """ await self._create_peer_connection() - await self._get_user_media(audio, video) + await self._get_user_media(audio, video, direction) return await self._get_call_data() async def make_call( - self, callee_jid: jid.JID, audio: bool = True, video: bool = True + self, + callee_jid: jid.JID, + audio: bool = True, + video: bool = True, + direction: str = "sendrecv" ) -> None: """ @param audio: True if an audio flux is required @param video: True if a video flux is required """ - call_data = await self.prepare_call(audio, video) + call_data = await self.prepare_call(audio, video, direction) log.info(f"calling {callee_jid!r}") self.sid = await bridge.call_start(str(callee_jid), json.dumps(call_data)) log.debug(f"Call SID: {self.sid}")