zoukankan      html  css  js  c++  java
  • 如何实现Web视频聊天?

          在网页里实现文字聊天是比较容易的,但若要实现视频聊天,就比较麻烦了。这里,我们将实现一个简单的网页版视频聊天Demo,可以支持所有类型的浏览器。

          本Demo除了视频聊天功能外,还包含以下功能:

    1.上下线通知:假设所有用户都是好友,任何一个用户上线,都会出现在其他人的好友列表中,下线则会从好友列表中移除。

    2.掉线后会自动进行断线重连。

    3.当同名的用户登陆时,会把前面的用户挤掉。

    4.所有在线用户之间进行文字聊天。

    5.与在线好友进行视频聊天。 

    一. Demo运行效果

        先来看看Demo的最终效果吧!文字聊天:

        

         视频聊天:

        

    二. JS 实现过程

    1.实现账号登录

        登录界面如下:     

        

    打开视频聊天demo网页时,会出现登录界面,输入视频服务器IP、账号(使用随机生成的就可以),点击登录按钮就可以登录到视频聊天服务器。

    调用ESFramework框架的RapidPassiveEngine()的initialize方法,以及OMCS框架的MultimediaManager的Initialize方法以完成登录。

    登录成功后会自动进入用户主界面。

            //OMCS登录
            $('#Singin').bind("click", function () {
                this.multimediaManager = MultimediaManagerFactory.GetSingleton();
                var id = document.getElementById("userID").value;//用户id
                var posw = document.getElementById("logonPassword").value;//用户密码
                var serverIP = document.getElementById("serverIP").value;//ip地址
                // var serverPort = document.getElementById("serverPort").value;//端口
                try {
                    if (this.multimediaManager.Connected() == true) {
                        this.multimediaManager.Initialize(id, posw, serverIP, 9900);             
                    } else {
                        alert("登录失败");
                        console.log("多媒体webSocket还未连成功");
                    }
                }
                catch (ex) {
                    console.log(ex);
                }
            })
            //ESFramework登录
            $('#Singin').bind("click", function () {                       
                engine.initialize({
                    serverIP: serverIP,//服务器IP
                    serverPort: serverPort,//服务器端口
                    userID: userID,//登录用户名
                    useWss: false,
                    logonPassword: hex_md5(logonPassword),//md5后的密码
                    heartBeat: 5000,//心跳间隔时间(单位为ms)
                    callBackTimeout: 5000,//回调方法超时时间(单位为ms)
                    maxLengthOfUserID: 11,//设置用户名最大长度
                    customizeHandler: new CustomizeHandler(),//用户自定义消息处理器
                    loginResutCallBack: function (loginResult) {//登录结果回调方法
                        if (loginResult.logonResult == 0) {//登录成功
                            $("#chatBox").html("登录服务器成功");
                            document.getElementById('loginid').innerHTML = '当前账号 '+userID;
                            document.getElementById('login').style.display = 'none';
                            document.getElementById('main').style.display = 'block'                      
                            //esf登录
                            engine.ContactsOutter.addEventListener(new contractsListener());//注册联系人事件
                            engine.BasicOutter.addEventListener(new basicListener());//注册基础事件
                            
                });
        };

    2. 实现文字聊天

    使用通信框架最基础的需求就是收发信息,ESFramework(WebSocket)底层已经为我们封装好了所有与信息收发相关的操作,  当RapidPassiveEngine被new出来以后,RapidPassiveEngine对象就实例化了CustomizeOutter 属性,在对象的initialize函数被调用后,即可调用CustomizeOutter 里面的相关函数来发送消息,以及实现customizeHandler后就可以处理收到的信息。

    Web端可以收到来自其它客户端或服务端的信息、大数据块、以及同步调用。

    (1)发送文字聊天消息

    发送文字聊天信息可时通过调用CustomizeOutter中send()来进行操作,再发送前点击在线用户即可改变targetUser的值从而绑定你要发送信息的对象。

    //选择聊天对象
    function selectUser(userid) {
        var selfid = document.getElementById('userID').value;
        targetUser = userid;
        $("#chatBox").html("正在与" + userid + "对话中.....");
        var shows = document.getElementById('showfather').children;
        //console.log(shows);
        for (var i= 0; i < shows.length; i++) {
            if (shows[i].id != (userid + 'show')) {
                shows[i]. className='othershow'
            }
            document.getElementById(userid + 'show').className = 'shownow'
        }
    }

    发送信息时可以自定义不同的参数,从而判断出不同的消息类型。

    //发送信息    
    $("#btn").bind("click", function () { if ($(".bottomtext").val() == "") { alert("不能发送空消息~"); return; } else if (targetUser.length == 0) { alert("未选中目标用户~"); return; } else { value = $(".bottomtext").val();
    var selfid=document.getElementById('userID').value; appendContent(
    "自己", value,selfid); $(".bottomtext").val(""); var time = []; var info = util.getbytes(value); //以下为与服务端定义的协议体 var stream = new OStream(time); var bodyLen = 4 + 4 + info.length + 4; stream.writeInt32(bodyLen); stream.writeInt32(info.length); stream.write(info); stream.writeInt32(1);//发送时间 距离2016.01.01 00:00:00的总秒数 engine.CustomizeOutter.send(0, stream.getBytesArray(), targetUser); } })

    (2)处理文字聊天消息

    当我们收到其他在线用户或者服务端发来的信息时,通过实现customizeHandler接口来获取和处理信息。

    我们在用户登录时调用initialize方法时转入即可自动处理接收到的信息,接收到的信息我们通过判断信息类型来执行不同的操作。

      function CustomizeHandler() {
                
                this.handleInformation = function (sourceUserID, informationType, info) {
                    if (informationType == 0)//聊天消息
                    {                  
                    } else if (informationType == 1)//视频消息
                    {                            
                    } else if (informationType == 2) {                               
                    } else if (informationType == 3) {
                    }

    (3)渲染显示文字聊天消息

    通过appendOtherContent和appendContent函数将信息在页面中渲染出来通过传入的对象OppositeID不同将收到的信息渲染到不同的聊天窗口。并且通过selectUser来切换到发送信息的用户的窗口。

    function appendContent(sendName, content, OppositeID) {
            Time = getTime();
            $("#" + OppositeID).append('<div class="selfstyle"><p class="selfname">' + sendName + ":" + Time + '</p><p>' + content + '</p></div>');
            $("#" + OppositeID).animate({ scrollTop: 99999 });
        }
    
        function appendOtherContent(sendName, content, OppositeID) {
            Time = getTime();
            selectUser(OppositeID);
            var showid = OppositeID + 'show'
            $("#" + showid).append('<div class="otherstyle"><p class="othername">' + sendName + ":" + Time + '</p><p>' + content + '</p></div>');
            $("#" + showid).animate({ scrollTop: 99999 });

     3. 实现视频聊天

          视频聊天功能可以让你与服务器上的在线用户进行视频聊天,通过OMCS服务插件来实现摄像头和麦克风的连接,所以在使用前必须打开OMCS视频服务Web插件才能正常使用。

    (1)点击视频聊天后先通过CustomizeOutter 的send向对方发送消息类型为1的视频连接请求数据,同时打开视频聊天的窗口并且打开自己的摄像头和麦克风连接

    (2)视频连接对象收到数据类型为1的视频连接请求后出接受视频连接的聊天框,可以选择接受或拒绝.

             当视频连接对象选择接受视频聊天,则会同时连接自己和对方的摄像头麦克风;

             当对方拒绝时,则关闭视频连接的请求。

             选择过后将会发送一条消息类型为2的消息给视频的发起者。

    (3)视频发起者收到数据为2的回复后,会进行判断对方的选择是接受还是拒绝,若是接受则开始连接对方的摄像头,拒绝则关闭自己的摄像头麦克风和视频连接窗口。

    (4)当某一方关闭连接或者断开连接时会发送一条消息类型为3的消息发给另一方,收到类型为3的消息后会断开自己的摄像头和麦克风连接。

    在连接过程中也可通过视频聊天窗口的控件,控制自己的摄像头麦克风的开启和关闭。

    发送视频请求时间如下(接受拒绝和关闭同理)

    $('#videomic').bind('click', function () {     
            if (targetUser.length == 0) {
                alert("未选中视频聊天用户~");
                return;
            } else {
                value = 'null';
                console.log(value);
                document.getElementById('VideoMic').style.display = 'block';
                document.getElementById('VideoHeardTxt').innerHTML = '连接中...';
                document.getElementById('VideoSelf').src = 'img/video.jpg'
                document.getElementById('VideoOther').src = 'img/head.jpg'
                ConnertVideoSelf(userID, 'VideoSelf')
                appendContent(selfid, "我发送了视频请求");
                var time = [];
                var info = util.getbytes(value);
                //以下为与服务端定义的协议体
                var stream = new OStream(time);
                var bodyLen = 4 + 4 + info.length + 4;
                stream.writeInt32(bodyLen);
                stream.writeInt32(info.length);
                stream.write(info);
                stream.writeInt32(1);//发送时间  距离2016.01.01 00:00:00的总秒数
                var userID = document.getElementById('userID').value;         
                engine.CustomizeOutter.send(1, null, targetUser);
            }
        })

    视频麦克风连接事件如下

    var microphoneConnector, dynamicCameraConnector;
    var cameraArr = [];
    var micArr = [];
    function Connectvideo(destID, whichimg) {
        var a = document.getElementById(whichimg);
        this.dynamicCameraConnector = new DynamicCameraConnector();
        this.dynamicCameraConnector.ConnectEnded = connectEnded;  //连接成功监听
        this.dynamicCameraConnector.Disconnected = disconnected;  //连接关闭监听
        this.dynamicCameraConnector.OwnerOutputChanged = videoOutput;
        this.dynamicCameraConnector.SetAutoReconnect(true);
        this.dynamicCameraConnector.AutoReconnectSucceed = videocl;
        this.dynamicCameraConnector.SetViewer(a);
        this.dynamicCameraConnector.BeginConnect(destID);//开始摄像头的连接
        cameraArr.push(this.dynamicCameraConnector);
        this.microphoneConnector = new MicrophoneConnector();
        this.microphoneConnector.ConnectEnded = microphone;
        this.microphoneConnector.OwnerOutputChanged = micOutput;
        this.microphoneConnector.SetAutoReconnect(true);
        this.microphoneConnector.AutoReconnectSucceed = miccl;
        this.microphoneConnector.BeginConnect(destID);//开始麦克风的连接
        micArr.push(this.microphoneConnector);
    }

    视频聊天的几个特性:

    (1)一方发起视频对话请求,对方同意后,即可开始视频对话。 

    (2)在对话的过程中,任何一方都可以挂断,以终止对话。 

    (3)在对话的过程中,任何一方掉线,都会自动终止对话。 

    (4)点击右下角较小视频窗口,会放大该视频显示窗口。

    (5)Web版的视频聊天可以与pc版视频聊天互通。

    三. 网页视频聊天Demo源码下载

    1. 视频聊天Demo Web端 源码(JavaScript)

    2. 视频聊天Demo 服务端+PC端 源码

          当运行本Demo 的 Web端时,如果尚未安装OMCS视频服务Web插件,网页会自动提示下载安装。

          完成安装后,刷新网页,会提示启动插件,点击同意启动后,再次刷新网页即可进行正常登录了。Web插件以托盘形式运行,如下图所示:   

          

          如果不想自己编译服务端和PC客户端,可以直接下载我们已经编译好的可直接运行的部署版本: VideoChat.Exe.rar

          部署版本压缩包里的服务端可以放到公网的服务器上,双击exe即可运行。PC客户端修改VideoChat.exe.config配置文件中的IP为公网服务器的IP,即可运行PC客户端测试。

          如此,PC客户端和Web端即可互通,以进行文字聊天和视频聊天。

    四. 注意事项

    1. 首先将服务端部署到服务器上,双击exe运行起来,然后再登录Web端和PC客户端测试。

    2. 一台电脑只能运行一个Demo Web端。

    3. 测试视频聊天时,两个用户最好在不同的房间,以防止声音相互干扰。

    4. Web版与在线用户聊天时,聊天内容并不是保存在云端的所以用户下线后记录会被清空。     

     

  • 相关阅读:
    《Linux设备驱动开发详解(第2版)》配套视频登录51cto教育频道
    异常Address already in use: JVM_Bind的处理
    你的Jsp页面有黄×么,有黄色问号么?Multiple annotations found at this line:
    dispatch_get_current_queue 废弃
    二叉树代码(较全)
    ArrayList and LinkedList
    android的tabhost+RadioGroup+PopupWindow
    子进程继承父进程的当前工作目录的问题
    oracle AWR深入研究分析,如何使用
    Linux下对后台进程通过kill传递信号不起作用的问题
  • 原文地址:https://www.cnblogs.com/components/p/15330756.html
Copyright © 2011-2022 走看看