What is the problem with my code(bandwidth limitation)?

61 Views Asked by At

I'm now making a broadcasting web using socket.io and webRTC. I can successly broadcast the video stream from the broadcaster to the viewers. However, I want to limit the bandwidth of the viewers/broadcasters so that if more viewers/broadcaster join the server, the quality of the video can be reduced to allow more users. It seems that I cannot change the videoWidth and videoHeight as they are read-only so I cannot directly change the resolution of the video. So I wonder if I can setBitrate to limit the performance of the video.

server.js

const express = require("express");
const app = express();

let broadcaster;
const port = 4000;

const http = require("http");
const server = http.createServer(app);

const io = require("socket.io")(server);
app.use(express.static(__dirname + "/public"));

io.sockets.on("error", e => console.log(e));
io.sockets.on("connection", socket => {
  socket.on("broadcaster", () => {
    broadcaster = socket.id;
    socket.broadcast.emit("broadcaster");
  });
  socket.on("watcher", () => {
    socket.to(broadcaster).emit("watcher", socket.id);
  });
  socket.on("offer", (id, message) => {
    socket.to(id).emit("offer", socket.id, message);
  });
  socket.on("answer", (id, message) => {
    socket.to(id).emit("answer", socket.id, message);
  });
  socket.on("candidate", (id, message) => {
    socket.to(id).emit("candidate", socket.id, message);
  });
  socket.on("disconnect", () => {

    if (socket.id === broadcaster) {
      
      socket.broadcast.emit("disconnectServer");
    }
    
    socket.broadcast.emit("disconnectPeer", socket.id);
  });
});
server.listen(port, () => console.log(`Server is running on port ${port}`));

broadcast.js

const peerConnections = {};
const config = {
  iceServers: [
    {
      "urls": "stun:stun.l.google.com:19302"
    }
  ],
  sdpSemantics: "plan-b"
};

function setBitrate(sdp, bitrate) {
  return sdp.replace(/a=mid:(audio|video)\r\n/g, `a=mid:$1\r\nb=AS:${bitrate}\r\n`);
}



const socket = io.connect(window.location.origin);
const video = document.querySelector("video");


// Media contrains
function getStream() {
  if (window.stream) {
    window.stream.getTracks().forEach(track =>{
      track.stop();
    });
  }
  const constraints = {
    video: true,
    audio: true,
    width: {exact:320},
    height: {exact:240},
    aspectRatio: 16/9,
    frameRate: {exact: 30},
    videoBitrate: 100000
    
  };

  

  
  navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
      const videoTrack = stream.getVideoTracks()[0];
      const capabilities = videoTrack.getCapabilities();
      console.log(capabilities.width.max); // maximum supported width
      console.log(capabilities.height.max); // maximum supported height
    })
    .catch(error => {
      // handle the error
    });
  video.addEventListener("loadedmetadata", function(){
    console.log("VideoWidth: " + video.videoWidth + " VideoHeight: " + video.videoHeight);
  })


  return navigator.mediaDevices
    .getUserMedia(constraints)
    .then(gotStream)
    .catch(handleError);
}




function gotStream(stream){ 
  window.stream = stream;
  video.srcObject = stream;
  socket.emit("broadcaster");
}



function handleError(error) {
  console.error("Error: ", error);
}


function setdefaultscreen(){
  video.srcObject = null;
  video.style.backgroundColor = "black";
}

socket.on("watcher", id => {
  console.log("viewerConnect!!");
  const peerConnection = new RTCPeerConnection(config);
  peerConnections[id] = peerConnection;

  let stream = video.srcObject;
  stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
    
  peerConnection.onicecandidate = event => {
    if (event.candidate) {
      socket.emit("candidate", id, event.candidate);
    }
  };

  peerConnection
    .createOffer()
    .then(sdp => {
      sdp.sdp = setBitrate(sdp.sdp, 5);
      return peerConnection.setLocalDescription(sdp)})
    .then(() => {
      socket.emit("offer", id, peerConnection.localDescription);
    });
});

socket.on("answer", (id, description) => {
  peerConnections[id].setRemoteDescription(description);
});

socket.on("candidate", (id, candidate) => {
  peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate));
});

socket.on("disconnect" ,() =>{
  socket.emit("disconnect");
  console.log("disconnect from server");
  if (peerConnection) {
    peerConnection.close();
  }
  setdefaultscreen();
})

socket.on("disconnectPeer", id => {
  console.log("disconnect peer from client");
  peerConnections[id].close();
  delete peerConnections[id];
});


window.onunload = window.onbeforeunload = () => {
  socket.close();
};


getStream();

viewer.js

let peerConnection;
const config = {
  iceServers: [
      { 
        "urls": "stun:stun.l.google.com:19302",
      },
      // { 
      //   "urls": "turn:TURN_IP?transport=tcp",
      //   "username": "TURN_USERNAME",
      //   "credential": "TURN_CREDENTIALS"
      // }
  ],
  sdpSemantics: "plan-b",
};


function setBitrate(sdp, bitrate) {
  return sdp.replace(/a=mid:(audio|video)\r\n/g, `a=mid:$1\r\nb=AS:${bitrate}\r\n`);
}

const socket = io.connect(window.location.origin);
const video = document.querySelector("video");

socket.on("offer", (id, description) => {
  peerConnection = new RTCPeerConnection(config);
  peerConnection
    .setRemoteDescription(description)
    .then(() => peerConnection.createAnswer())
    .then(sdp => {
      sdp.sdp = setBitrate(sdp.sdp, 5);
      return peerConnection.setLocalDescription(sdp)}
      )
    .then(() => {
      socket.emit("answer", id, peerConnection.localDescription);
    });
  peerConnection.ontrack = event => {
    video.srcObject = event.streams[0];
  };
  peerConnection.onicecandidate = event => {
    if (event.candidate) {
      socket.emit("candidate", id, event.candidate);
    }
  };
});


socket.on("candidate", (id, candidate) => {
  peerConnection
    .addIceCandidate(new RTCIceCandidate(candidate))
    .catch(e => console.error(e));
});

socket.on("connect", () => {
  socket.emit("watcher");
});

socket.on("broadcaster", () => {
  
  socket.emit("watcher");
});

function setdefaultscreen(){
  video.srcObject = null;
  video.style.backgroundColor = "black";
}

socket.on("disconnectServer", () => {
  console.log("disconnect from server");
  setdefaultscreen();
});

window.onunload = window.onbeforeunload = () => {
  socket.close();
  peerConnection.close();
  setdefaultscreen();
  
  
};

now I setBitrate to 5 and the video should be hardly playable. But I found that no matter what value I set the video is still playable and its quality doesn't change. I use Google Chrome to open the web. Is the problem related to the browser?

0

There are 0 best solutions below