WEBRTC--简单入门实例

         WebRTC 是一个支持网页浏览器进行实时语音对话或视频对话的技术 ,,最近工做须要研究了一下,写一个demo供你们参考,原理方面的东西你们能够百度一下,须要注意的是demo目前只支持火狐 由于谷歌目前必须是https 访问 才能够获取视频信息.系统环境为:tomcat8+jdk7javascript

      websocketcss

package com.li.web;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/video/{roomId}/{userId}")
public class VideoScoket {
	
    /**
     * 存放房间与用户
     */
    private static HashMap<String,Set<User>>  usersRoom = new HashMap<String,Set<User>>();
    
	/**
	 * 打开websocket
	 * @param session websocket的session
	 * @param uid 打开用户的UID
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam("roomId")String roomId, @PathParam("userId")String userId) {  
	                      Set<User> users = usersRoom.get(roomId);
	                      if(users== null ){
	                          users = new HashSet<User>();
	                      }
	                      if(users.size()>=2){
	                          sendMessage(session, "peopleMax");//目前只支持两我的之间的通信 ,因此不能超过两我的
	                      }else{
	                          User user = new User();
	                          user.setId(userId);
	                          user.setSession(session);
	                          users.add(user);
	                          usersRoom.put(roomId,users);
	                      }
	}

	/**
	 * websocket关闭
	 * @param session 关闭的session
	 * @param uid 关闭的用户标识
	 */
	@OnClose
	public void onClose(Session session, @PathParam("roomId")String roomId, @PathParam("userId")String userId) {
	   
	                    Set<User> users = usersRoom.get(roomId);
	                    if(users!=null){
	                        for (User user:users) {
	                            if(user.getId().equals(userId)){
	                                users.remove(user);
	                                return;
	                            }else if(!user.getId().equals(userId)){
                                    sendMessage(user.getSession(), "bye");//退出以后,发送给另外一我的信息,以便让他断开视频链接
                                    return;
                                }
	                        }
	                    }
	}

	/**
	 * 收到消息
	 * @param message 消息内容
	 * @param session 发送消息的session
	 * @param uid
	 */
	@OnMessage
	public void onMessage(String message,Session session, @PathParam("roomId")String roomId, @PathParam("userId")String userId) {
	                     Set<User> users = usersRoom.get(roomId);
	                     if(users!=null){
	                            User recipient = null;
	                            for (User user:users) {//查询当前会议中另外一个在线人
	                                if(!user.getId().equals(userId)){
	                                    recipient = user;
	                                }
	                            }
	                            if(message.startsWith("query-On-line")){//若是查询是否有人在线
	                                if(users.size()>1){
	                                    sendMessage(session,"query-On-line-Yes");
	                                }else{
	                                    sendMessage(session,"query-On-line-No");
	                                }
	                            }else if(recipient!=null){
	                                sendMessage(recipient.getSession(), message);
	                            }
	                      }
	}
/**
 * 给客户端发送消息
 * @param session
 * @param message
 */
	public void sendMessage(Session session,String message){
	    try {
	       if(session.isOpen()) {
	           session.getBasicRemote().sendText(new String(message));
	       }
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
}

Userhtml

package com.li.web;

import javax.websocket.Session;


public class User {

    private String id;
    
    private Session session;

    public String getId() {
    
        return id;
    }
    
    public void setId(String id) {
    
        this.id = id;
    }
    
    public Session getSession() {
    
        return session;
    }
    
    public void setSession(Session session) {
    
        this.session = session;
    }
}

meeting.jspjava

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
String scoketPasePath = "ws://"+request.getServerName()+":"+request.getServerPort()+path+"/video/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
     <meta charset="utf-8">
    <script src="<%=basePath%>jquery.min.js"></script>
    <script src="<%=basePath%>monitor.js"></script>

    <style type="text/css">
      .right{
          height: 80%;
          position:absolute;
          right: 40px;
          top:40px;
          width:180px;
      }
      .remoteAudio{
       margin-top: 20px;
       list-style:outside none none;
       height:150px;
       width: 180px;
       background-color: black;
       border: 1px red solid;
       text-align:center;
      }
      
      .name{
       position:absolute;
       z-index:99999;
       left:77px;
      }
      
    </style>
  </head>
  
  <body>
    <input type="text" id="roomId"/> <input type="button" value="进入房间" onclick="goRoom()"/>
    <script type="text/javascript">
    function goRoom(){
    	var $roomId = $("#roomId").val();
    	if($roomId==""){
    		alert("请输入房间号");
    	}else{
    		 monitor.initialize("<%=scoketPasePath%>", "localVideo","remoteAudio", $roomId);
    		 monitor.openChannel();
    	}
    }
   
    </script>
    
    <div>
       <video id="localVideo" autoplay="autoplay"></video>
    </div>
    <div>
         <video id="remoteAudio" autoplay="autoplay"></video>
    </div>
    
  </body>
</html>

monitor.jsjquery

var monitor ={
		initSucess:false,
		socket    :null,
		PeerConnection:null,
		pc:null,
		started:false,
		localStream:null,
		remoteVideo:null,
		localVideo:null,
		remoteStream:null,
		scoketPath:null,
		roomId:null,
		userId:null,
		socketSate:false,
		iceServer:{//打洞服务器地址配置
		    "iceServers": [{
		        "url": "stun:1.1.1.1"
		}]},
		log:function(msg){
		    if(console && console.log){
		        console.log(msg);
		    }
		},//初始化一些信息
		initialize:function(scoketPath,localVideoId,remoteVideoId,roomId){
			PeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
			monitor.remoteVideo = $("#"+remoteVideoId);
			monitor.localVideo = $("#"+localVideoId);
			monitor.scoketPath   = scoketPath;
			monitor.roomId = roomId;
			monitor.userId = new Date().getTime();
		},//打开webscoket
		openChannel:function(){
			monitor.socketSate=true;
			monitor.socket = new WebSocket(monitor.scoketPath+monitor.roomId+"/"+monitor.userId);
			monitor.socket.onopen = monitor.onopen;
			monitor.socket.onmessage = monitor.onChannelMessage;
			monitor.socket.onclose = monitor.onChannelClosed;
		},
		onopen:function(onopenCallBack){
			monitor.log("websocket打开");
			monitor.socketSate = true;
			monitor.getUserMedia();
		},
		onChannelClosed:function(){
			monitor.log("websocket关闭");
			monitor.socketSate=false;
			monitor.openChannel();
		},
		onChannelMessage:function(message){
			monitor.log("收到信息 : " + message.data);
			if(message.data=="query-On-line-Yes"){
				monitor.maybeStart();
			}else if(message.data=="peopleMax"){
				alert("人数已经超过限制");
			}else if(message.data=="bye"){
				monitor.onRemoteClose();
			}else if(message.data!="query-On-line-No"){
				monitor.processSignalingMessage(message.data);//创建视频链接
			}
		},
		getUserMedia:function(){
			monitor.log("获取用户媒体");
			navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
			navigator.getUserMedia({
				"audio" : true,
				"video" : true
			},monitor.onUserMediaSuccess, monitor.onUserMediaError);
		},
		onUserMediaSuccess:function(stream){
			monitor.log("获取媒体成功");
			monitor.localStream=stream;
			var url = window.URL.createObjectURL(stream);
			monitor.localVideo.attr("src",url);
			monitor.sendMessageByString("query-On-line");
		},
		onUserMediaError:function(){
			monitor.log("获取用户流失败!");
		},
		maybeStart:function(){
			if (!monitor.started) {
				monitor.createPeerConnection();
				monitor.pc.addStream(monitor.localStream);
				monitor.started = true;
				monitor.doCall();
			}
		},
		createPeerConnection:function(){
			monitor.pc = new PeerConnection(monitor.iceServer);
			monitor.pc.onicecandidate =monitor.onIceCandidate;
			monitor.pc.onconnecting = monitor.onSessionConnecting;
			monitor.pc.onopen = monitor.onSessionOpened;
			monitor.pc.onaddstream = monitor.onRemoteStreamAdded;
			monitor.pc.onremovestream = monitor.onRemoteStreamRemoved;
		},
		onSessionConnecting:function(message){
			monitor.log("开始链接");
		},
		onSessionOpened:function(message){
			monitor.log("链接打开");
		},
		onRemoteStreamAdded:function(event){
			monitor.log("远程视频添加");
			if(monitor.remoteVideo!=null){
				var url = window.URL.createObjectURL(event.stream);
				
				monitor.remoteVideo.attr("src",url);
				monitor.remoteStream = event.stream;
				monitor.waitForRemoteVideo();
			}
			
		},
		waitForRemoteVideo:function(){
			if (monitor.remoteVideo[0].currentTime > 0) { // 判断远程视频长度
				monitor.transitionToActive();
			} else {
				setTimeout(monitor.waitForRemoteVideo, 100);
			}
		},
		transitionToActive:function(){
			monitor.log("链接成功!");
			monitor.sendMessageByString("connection_open");
		},
		onRemoteStreamRemoved:function(event){
			monitor.log("远程视频移除");
		},
		onIceCandidate:function(event){
			if (event.candidate) {
				monitor.sendMessage({
					type : "candidate",
					label : event.candidate.sdpMLineIndex,
					id : event.candidate.sdpMid,
					candidate : event.candidate.candidate
				});
			} else {
				monitor.log("End of candidates.");
			}
		},
		processSignalingMessage:function(message){
			var msg = JSON.parse(message);
			if (msg.type === "offer") {
				if (!monitor.started)
					monitor.maybeStart();
				    monitor.pc.setRemoteDescription(new RTCSessionDescription(msg),function(){
				    monitor.doAnswer();
				},function(){
				});
			} else if (msg.type === "answer" && monitor.started) {
				monitor.pc.setRemoteDescription(new RTCSessionDescription(msg));
			} else if (msg.type === "candidate" && monitor.started) {
				var candidate = new RTCIceCandidate({
					sdpMLineIndex : msg.label,
					candidate : msg.candidate
				});
				monitor.pc.addIceCandidate(candidate);
			} 
		},
		doAnswer:function (){
			monitor.pc.createAnswer(monitor.setLocalAndSendMessage, function(e){
				monitor.log("建立相应失败"+e);
			});
		},
		doCall:function(){
			monitor.log("开始呼叫");
			monitor.pc.createOffer(monitor.setLocalAndSendMessage,function(){
			});
		},
		setLocalAndSendMessage:function(sessionDescription){
			monitor.pc.setLocalDescription(sessionDescription);
			monitor.sendMessage(sessionDescription);
		},
		sendMessage:function(message){
			var msgJson = JSON.stringify(message);
			monitor.sendMessageByString(msgJson);
		},
		sendMessageByString:function(message){
			monitor.socket.send(message);
			monitor.log("发送信息 : " + message);
		},
		onRemoteClose:function(){
			monitor.started = false;
			monitor.pc.close();
			monitor.sendMessageByString("connection_colse");
		}
};

还须要注意的一点是,,若是视频的两我的未处在同一个内网中,那则须要部署打洞服务器,,我用的restund 比较简单...有须要的同窗能够百度,部署安装web