1. 程式人生 > >Java使用websocket和WebRTC實現視訊通話

Java使用websocket和WebRTC實現視訊通話

最近這段時間折騰了一下WebRTC,這兩天終於是抽了時間把WebRTC搞定了,去年就想弄的,但是確實沒時間。看了網上的https://apprtc.appspot.com/的例子(可能需要翻牆訪問),這個例子是部署在Google App Engine上的應用程式,依賴與GAE的環境,後臺的語言是python,而且還依賴Google App Engine Channel API,所以無法在本地執行,也無法擴充套件。費了一番功夫研讀了例子的python端的原始碼,決定用Java實現,Tomcat7之後開始支援WebSocket,打算用WebSocket代替Google App Engine Channel API實現前後臺的通訊,在整個例子中Java+WebSocket起到的作用是負責客戶端之間的通訊,並不負責視訊的傳輸,視訊的傳輸依賴於WebRTC。

首先WebRTC,這個可以百度一下,大概就是一個音訊和視訊通訊技術,可以跨平臺,只要能用瀏覽器的基本都可以使用,當然要你的瀏覽器支援。

這裡引用了google的js庫:channel.js。不過還是下載下來放到本地伺服器吧,因為很多地方訪問google.com很吃力啊。最開始就是這個js沒有載入完鬱悶了很久,還一直以為是程式碼寫錯了。

另外在進入頁面的時候,注意初始化頁面js中的一個引數:initiator:如果是建立人這個引數設為false;如果是加入的時候這個設定為true。為true的時候,才會發起視訊通話的請求。

實現

對於前端JS程式碼及用到的物件大家可以去檢視詳細的程式碼介紹,我就貼一個連線的方法。首先建立一個客戶端實時獲取狀態的連線,在GAE的例子上是通過GAE Channel API實現,我在這裡用WebSocket實現,程式碼:

function openChannel() {  
     console.log("開啟websocket");
     socket = new WebSocket("ws://192.168.1.158:8080/WebRTC/acgist.video/${requestScope.uid}");                
     socket.onopen = onChannelOpened;
     socket.onmessage = onChannelMessage;
     socket.onclose = onChannelClosed;  
     socket.onerror = onChannelError();
    }  

服務端程式碼很簡單,就是收到使用者的請求,傳送給另外一個使用者就可以了,這裡處理的其實是使用者WebRTC的一些資訊,並不是去傳輸視訊,如下:

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

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;

/**
 * @author 李智
 * @date 2017/3/11
 *
 * WebRTC視訊通話
 */

@ServerEndpoint("/acgist.video/{uid}")
public class AcgistVideo {
    // 最大通話數量
    private static final int MAX_COUNT = 10;
    private static final long MAX_TIME_OUT = 1 * 60 * 1000;
    // 使用者和使用者的對話對映
    private static final Map<String, String> user_user = Collections.synchronizedMap(new HashMap<String, String>()); 
    // 使用者和websocket的session對映
    private static final Map<String, Session> sessions = Collections.synchronizedMap(new HashMap<String, Session>());

    /**
     * 開啟websocket
     * @param session websocket的session
     * @param uid 開啟使用者的UID
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("uid")String uid) {
        session.setMaxIdleTimeout(MAX_TIME_OUT);
        sessions.put(uid, session);
    }

    /**
     * websocket關閉
     * @param session 關閉的session
     * @param uid 關閉的使用者標識
     */
    @OnClose
    public void onClose(Session session, @PathParam("uid")String uid) {
        remove(session, uid);
    }

    /**
     * 收到訊息
     * @param message 訊息內容
     * @param session 傳送訊息的session
     * @param uid
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("uid")String uid) {
        try {
            if(uid != null && user_user.get(uid) != null && AcgistVideo.sessions.get(user_user.get(uid)) != null) {
                Session osession = sessions.get(user_user.get(uid)); // 被呼叫的session
                if(osession.isOpen())
                    osession.getAsyncRemote().sendText(new String(message.getBytes("utf-8")));
                else
                    this.nowaiting(osession);
            } else {
                this.nowaiting(session);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 沒有人在等待
     * @param session 傳送訊息的session
     */
    private void nowaiting(Session session) {
        session.getAsyncRemote().sendText("{\"type\" : \"nowaiting\"}");
    }

    /**
     * 是否可以繼續建立通話房間
     * @return 可以:true;不可以false;
     */
    public static boolean canCreate() {
        return sessions.size() <= MAX_COUNT;
    }

    /**
     * 判斷是否可以加入
     * @param oid 被申請對話的ID
     * @return 如果能加入返回:true;否則返回false;
     */
    public static boolean canJoin(String oid) {
        return !(oid != null && user_user.containsKey(oid) && user_user.get(oid) != null);
    }

    /**
     * 新增視訊物件
     * @param uid 申請對話的ID
     * @param oid 被申請對話的ID
     * @return 是否是建立者:如果沒有申請對話ID為建立者,否則為為加入者。建立者返回:true;加入者返回:false;
     */
    public static boolean addUser(String uid, String oid) {
        if(oid != null && !oid.isEmpty()) {
            AcgistVideo.user_user.put(uid, oid);
            AcgistVideo.user_user.put(oid, uid);

            return false;
        } else {
            AcgistVideo.user_user.put(uid, null);

            return true;
        }
    }

    /**
     * 移除聊天使用者
     * @param session 移除的session
     * @param uid 移除的UID
     */
    private static void remove(Session session, String uid) {
        String oid = user_user.get(uid);

        if(oid != null) user_user.put(oid, null); // 設定對方無人聊天

        sessions.remove(uid); // 異常session
        user_user.remove(uid); // 移除自己

        try {
            if(session != null && session.isOpen()) session.close(); // 關閉session
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

自己測試的時候搞個公用的stun伺服器弄一弄就好了。不過人多的時候會延遲很就是了,成功截圖就不放了,人醜家貧。

相關推薦

Java使用websocketWebRTC實現視訊通話

最近這段時間折騰了一下WebRTC,這兩天終於是抽了時間把WebRTC搞定了,去年就想弄的,但是確實沒時間。看了網上的https://apprtc.appspot.com/的例子(可能需要翻牆訪問),這個例子是部署在Google App Engine上的應用程式

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

package org.rtc.servlet; import java.io.IOException; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.WebSe

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

function initialize() { console.log("Initializing; room=${roomKey}."); card = document.getElementById("card"); localVideo = document.getElementById("local

基於socket.io即時通訊IM實現webRTC實現視訊通話

Socket.io-FLSocketIM-iOS 基於Socket.io iOS即時通訊客戶端 iOS IM Client based on Socket.io 實現功能 文字傳送 圖片傳送(從相簿選取,或者拍攝) 短視

iOS WebRTC語音視訊通話實現與demo

pod install AppRTC 從那裡你可以看到在這個回購ARTCVideoChatViewController類。以下步驟詳細具體更改您將需要在您的應用程式新增視訊聊天。 Initialize SSL Peer ConnectionWebRTC可以通過SSL安全通訊。這是必需的,如果你想測試在ht

ffmpegmencoder實現視訊轉碼

  最近研究了一下視訊轉碼的問題,參考了部落格https://blog.csdn.net/wdy_2099/article/details/71453602?utm_source=blogxgwz3 具體內容這裡不再說了,安裝可參考https://www.cnblogs.com/new-ass/p/7704

使用Resiprocate 部署 WebRTC IM 視訊通話平臺

為什麼選用SIP協議來部署WebRTC 通訊系統? 1,互通性,基於sip 協議有大量的軟硬體裝置,例如: ip 話機,軟電話,ip攝像頭等等,MCU 裝置等。 2,穩定性,sip 協議歷史悠久,且大量的公司使用它開發ip 通訊系統,文件豐富,功能強大。 3,支援與電話系統

iOS下WebRTC視訊通話(一)

在iOS下做IM功能時,難免都會涉及到音訊通話和視訊通話。QQ中的QQ電話和視訊通話效果就非常好,但是如果你沒有非常深厚的技術,也沒有那麼大的團隊,很難做到QQ那麼快速和穩定的通話效果。 但是利用WebRTC技術,即使一個人也能夠實現效果不錯的音視訊通話。本篇

100行Javascript程式碼實現視訊通話

視訊聊天室 上一篇文章通過JavaScript呼叫AnyChat實現視訊聊天室 簡單地講述瞭如何通過AnyChat做視訊聊天室。通過學習,我自己也做了個簡單的小例子,幾十行JavaScript指令碼就能輕鬆實現視訊通話;也不用去下載指定的什麼瀏覽器,因為IE、firefo

AnyChatSDK 實現視訊通話

package com.bairuitech.main; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.Dialog; import android.

x-lite asterisk 成功實現視訊通話

       首先,在此感謝asterisk協會的各位大牛們,沒有他們的幫助,我也不可能在這麼短的時間內實現,x-lite+asterisk音視訊通話。在此將實現的過程記錄如下,分享給asterisk的愛好者們。        1. 修改asterisk伺服器的sip.co

FreeSwitch 1.9.0 安裝配置及使用MySQL管理賬戶,並實現視訊通話

最近因為專案上的需要入手了FreeSwitch。 之前嘗試過Asterisk,但個人感覺對H264的支援不是特別友好,所以用才選擇了FreeSwitch。 安裝FreeSwitch前的準備工作: 1、VMare上安裝一個CentOS的虛擬機器 安裝CentOS 7:

使用SurfaceViewMediaPlayer實現視訊做為背景

場景:像我們在Uber應用開場,看到一一段視訊作為開始,這樣子讓使用者很快投入應用使用的場景中去,這種以視訊作為開場的應用,我們是不是覺得很高大上呢,哈哈,其實是使用了SerfaceView去載入一段小視訊,然後使用mediaplayer進行播放,然後迴圈。 先上圖吧。

利用MediaExtractorMediaMuxer實現視訊剪下

客戶要在android手機上做個能視訊剪下的app,由於視訊源只是MP4,所以就想到了用MediaExtractor和MediaMuxer來實現功能,直接上程式碼。 public class VideoDecoder { private final

如何結合 CallKit Agora SDK 實現視訊 VoIP 通話應用

作者簡介:龔宇華,聲網Agora.io 首席 iOS 研發工程師,負責 iOS 端移動應用產品設計和技術架構。 CallKit 是蘋果在 iOS10 中推出的,專為 VoIP 通話場景設計的系統框架,在 iOS 上為 VoIP 通話提供了系統級的支援。 在 iOS10 以前,VoI

基於socketio實現webrtc視訊通話的流程

按照發起方A往下走流程,呼叫requestServerCreateRoom方法,在這個方法裡建立socket連線,將發起方A和接收方B的使用者id傳遞給伺服器,傳送事件為“videoChat”。伺服器接收到videoChat事件,按照請求生成房間,並將房間號返回給發起方A。發起方A收到房間號後,執行conne

使用WebRTC實現電腦與手機通過瀏覽器進行視訊通話

      最近一直在研究WebRTC,做了一個小專案:www.meet58.com,這個專案利用WebRTC、WebSocket可以讓各種裝置只通過瀏覽器進行視訊聊天,無論是電腦、手機或者是平板。下面就是手機和電腦進行視訊通話的截圖:PC端手機端這個專案目前只有簡單的視訊通

Android藍芽socket實現視訊實時傳輸,以及圖片文字傳輸

目標 兩臺手機裝置之間能夠正常進行藍芽配對(藍芽模組兒和硬體掛鉤,所以需要兩臺真機) socket實現藍芽文字傳輸 實現圖片傳輸 實現實時視訊傳輸 程式碼下載:https://download.csdn.net/download/m0_37781149/10434336

vue專案利用vue-video-player實現視訊相容IOS安卓放大播放

首先,圖片和視訊混合一起,預設圖片製作poster點選彈窗手機播放器 <template> <div class="look-v"> <section class="view-wrap" v-if="accObj"> <div c

使用opencv實現視訊分解圖片圖片合成視屏

# 視訊分解成圖片 import cv2 cap = cv2.VideoCapture("22.mp4") # 獲取開啟的控制代碼 isOpened = cap.isOpened # 判斷是否開啟 print(isOpened) fps = cap.get(cv2.CAP_PROP_FPS) w