1. 程式人生 > >Java通過WebSocket WebRTC實現視訊通話例項

Java通過WebSocket WebRTC實現視訊通話例項

package org.rtc.servlet;

import java.io.IOException;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.rtc.room.WebRTCRoomManager;

@WebServlet(urlPatterns = {"/room"})
public class WebRTCRoomServlet extends HttpServlet {

  private static final long serialVersionUID = 1L;
  
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    this.doPost(request, response);
  }

  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String r = request.getParameter("r");
    if(StringUtils.isEmpty(r)){
      //如果房間為空,則生成一個新的房間號
      r = String.valueOf(System.currentTimeMillis());
      response.sendRedirect("room?r=" + r);
    }else{
      Integer initiator = 1;
      String user = UUID.randomUUID().toString().replace("-", "");//生成一個使用者ID串
      if(!WebRTCRoomManager.haveUser(r)){//第一次進入可能是沒有人的,所以就要等待連線,如果有人進入了帶這個房間好的頁面就會發起視訊通話的連線
        initiator = 0;//如果房間沒有人則不傳送連線的請求
      }
      WebRTCRoomManager.addUser(r, user);//向房間中新增一個使用者
      String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() +  request.getContextPath() +"/";
      String roomLink = basePath + "room?r=" + r;
      String roomKey = r;//設定一些變數
      request.setAttribute("initiator", initiator);
      request.setAttribute("roomLink", roomLink);
      request.setAttribute("roomKey", roomKey);
      request.setAttribute("user", user);
      request.getRequestDispatcher("index.jsp").forward(request, response);
    }
  }
}

這個是進入房間前的處理,然而客戶端是怎麼發起視訊通話的呢?
function initialize() {
      console.log("Initializing; room=${roomKey}.");
      card = document.getElementById("card");
      localVideo = document.getElementById("localVideo");
      miniVideo = document.getElementById("miniVideo");
      remoteVideo = document.getElementById("remoteVideo");
      resetStatus();
      openChannel();
      getUserMedia();
    }
    
    function getUserMedia() {
      try {
        navigator.webkitGetUserMedia({
          'audio' : true,
          'video' : true
        }, onUserMediaSuccess, onUserMediaError);
        console.log("Requested access to local media with new syntax.");
      } catch (e) {
        try {
          navigator.webkitGetUserMedia("video,audio",
              onUserMediaSuccess, onUserMediaError);
          console
              .log("Requested access to local media with old syntax.");
        } catch (e) {
          alert("webkitGetUserMedia() failed. Is the MediaStream flag enabled in about:flags?");
          console.log("webkitGetUserMedia failed with exception: "
              + e.message);
        }
      }
    }
    
    function onUserMediaSuccess(stream) {
      console.log("User has granted access to local media.");
      var url = webkitURL.createObjectURL(stream);
      localVideo.style.opacity = 1;
      localVideo.src = url;
      localStream = stream;
      // Caller creates PeerConnection.
      if (initiator)
        maybeStart();
    }
    
    function maybeStart() {
      if (!started && localStream && channelReady) {
        setStatus("Connecting...");
        console.log("Creating PeerConnection.");
        createPeerConnection();
        console.log("Adding local stream.");
        pc.addStream(localStream);
        started = true;
        // Caller initiates offer to peer.
        if (initiator)
          doCall();
      }
    }

    function doCall() {
      console.log("Sending offer to peer.");
      if (isRTCPeerConnection) {
        pc.createOffer(setLocalAndSendMessage, null, mediaConstraints);
      } else {
        var offer = pc.createOffer(mediaConstraints);
        pc.setLocalDescription(pc.SDP_OFFER, offer);
        sendMessage({
          type : 'offer',
          sdp : offer.toSdp()
        });
        pc.startIce();
      }
    }

    function setLocalAndSendMessage(sessionDescription) {
      pc.setLocalDescription(sessionDescription);
      sendMessage(sessionDescription);
    }

    function sendMessage(message) {
      var msgString = JSON.stringify(message);
      console.log('發出資訊 : ' + msgString);
      path = 'message?r=${roomKey}' + '&u=${user}';
      var xhr = new XMLHttpRequest();
      xhr.open('POST', path, true);
      xhr.send(msgString);
    }

頁面載入完之後會呼叫initialize方法,initialize方法中呼叫了getUserMedia方法,這個方法是通過本地攝像頭獲取視訊的方法,在成功獲取視訊之後傳送連線請求,並在客戶端建立連線管道,最後通過sendMessage向另外一個客戶端傳送連線的請求,引數為當前通話的房間號和當前登陸人。