GRVYDEV / Project-Lightspeed

A self contained OBS -> FTL -> WebRTC live streaming server. Comprised of 3 parts once configured anyone can achieve sub-second OBS to the browser livestreaming
MIT License
3.64k stars 138 forks source link

How to implement for the simple web app - project frontend #82

Open TrietPham96 opened 1 year ago

TrietPham96 commented 1 year ago

I had setup and run all successfully. However i'm a newbie with React, there are some difficulties for me to modified the player or layout on my side. Is there the simple approach or solution? such as implementation for project html + vanillaJS boiperlate. Thank you!!!~

malantp commented 1 year ago

I would love that too, the embedded React frontend is nice but not very customizable. I'd like to make my own one in the simplest way possible. Thanks :)

TrietPham96 commented 1 year ago

I migration handle Socket and WebRTC from React code, it's work OK. Hope to help someone

<!DOCTYPE html>
<html>

<head>
  <title>Viewer</title>
  <meta charset="UTF-8" />
</head>

<body>
  <video playsinline autoplay muted></video>
  <button id="enable-audio">Enable audio</button>
  <script type="text/javascript">
    const socket = new WebSocket("ws://192.168.1.10:8080/websocket");
    const video = document.querySelector("video");
    const enableAudioButton = document.querySelector("#enable-audio");

    enableAudioButton.addEventListener("click", enableAudio)

    function enableAudio() {
      console.log("Enabling audio")
      video.muted = false;
    }

    const appReducer = (state, action) => {
      switch (action.type) {
        case "track": {
          state.stream.addTrack(action.track);
          return { ...state, stream: state.stream };
        }
        case "info": {
          return { ...state, viewers: action.viewers };
        }

        default: {
          return { ...state };
        }
      }
    };

    const initialState = {
      stream: new MediaStream(),
      viewers: null,
    };

    const pc = new RTCPeerConnection();

    pc.ontrack = (event) => {
      video.srcObject = event.streams[0];
    };

    pc.onicecandidate = (e) => {
      const { candidate } = e;
      if (candidate) {
        console.log("Candidate success");
        socket.send(
          JSON.stringify({
            event: "candidate",
            data: e.candidate,
          })
        );
      }
    };

    if (socket) {
      socket.onmessage = async (event) => {
        const msg = JSON.parse(event.data);

        if (!msg) {
          console.log("Failed to parse msg");
          return;
        }

        const offerCandidate = msg.data;

        if (!offerCandidate) {
          console.log("Failed to parse offer msg data");
          return;
        }

        switch (msg.event) {
          case "offer":
            console.log("Offer");
            pc.setRemoteDescription(offerCandidate);

            try {
              const answer = await pc.createAnswer();
              pc.setLocalDescription(answer);
              socket.send(
                JSON.stringify({
                  event: "answer",
                  data: answer,
                })
              );
            } catch (e) {
              console.error(e.message);
            }

            return;
          case "candidate":
            console.log("Candidate");
            pc.addIceCandidate(offerCandidate);
            return;
        }
      };
    }
  </script>
</body>

</html>
malantp commented 1 year ago

That's awesome! Is very simple and it work just fine, just what I needed, thank you! 💯