Konubinix' opinionated web of thoughts

Webrtc to Go2rtc

Fleeting

clk android poc re
ssh "${PHONE_NAME}" termux-open "'http://localhost:9717/go2rtc?dst=browser_cam&media=camera+microphone'"
vlc rtsp://home:9910/browser_cam
git clone https://github.com/AlexxIT/go2rtc
cd go2rtc
go mod tidy
CGO_ENABLED=0 go run .

Hosting the following content thanks to my python runtime on android.

Then, to read the content

vlc rtsp://home:9910/browser_cam

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>go2rtc - WebRTC</title>
    <style>
      body {
          background-color: black;
          margin: 0;
          padding: 0;
      }

      html, body, video {
          height: 100%;
          width: 100%;
      }
    </style>
  </head>
  <body>
    <video id="video" autoplay controls playsinline muted></video>
    <script>
      async function PeerConnection(media) {
          const pc = new RTCPeerConnection({
              iceServers: [{urls: 'stun:stun.l.google.com:19302'}]
          });

          const localTracks = [];

          if (true) {
              const tracks = await getMediaTracks('user', {
                  video: {
                      facingMode: {exact: "environment"},
                  },
                  audio: true,
              });
              tracks.forEach(track => {
                  pc.addTransceiver(track, {direction: 'sendonly'});
                  if (track.kind === 'video') localTracks.push(track);
              });
          }

          if (media.indexOf('display') >= 0) {
              const tracks = await getMediaTracks('display', {
                  video: true,
                  audio: media.indexOf('speaker') >= 0,
              });
              tracks.forEach(track => {
                  pc.addTransceiver(track, {direction: 'sendonly'});
                  if (track.kind === 'video') localTracks.push(track);
              });
          }

          if (/video|audio/.test(media)) {
              const tracks = ['video', 'audio']
                    .filter(kind => media.indexOf(kind) >= 0)
                    .map(kind => pc.addTransceiver(kind, {direction: 'recvonly'}).receiver.track);
              localTracks.push(...tracks);
          }

          document.getElementById('video').srcObject = new MediaStream(localTracks);

          return pc;
      }

      async function getMediaTracks(media, constraints) {
          try {
              const stream = media === 'user'
                    ? await navigator.mediaDevices.getUserMedia(constraints)
                    : await navigator.mediaDevices.getDisplayMedia(constraints);
              return stream.getTracks();
          } catch (e) {
              console.warn(e);
              return [];
          }
      }

      function getCompleteOffer(pc, timeout) {
          return new Promise((resolve, reject) => {
              pc.addEventListener('icegatheringstatechange', () => {
                  if (pc.iceGatheringState === 'complete') resolve(pc.localDescription.sdp);
              });

              pc.createOffer().then(offer => pc.setLocalDescription(offer));

              setTimeout(() => resolve(pc.localDescription.sdp), timeout || 3000);
          });
      }

      async function connect(media) {
          const pc = await PeerConnection(media);
          const url = new URL('http://home/go2rtc/api/webrtc' + location.search, location.href);
          const r = await fetch(url, {method: 'POST', body: await getCompleteOffer(pc)});
          await pc.setRemoteDescription({type: 'answer', sdp: await r.text()});
      }

      const media = new URLSearchParams(location.search).get('media');
      connect(media || 'video+audio');
    </script>
  </body>
</html>