七牛云rtc实时音视频——vue版本demo

谨记: 不支持安卓内嵌webview h5

支持的通话方式:

  • h5
  • web网页

源码地址

https://github.com/qlanto224/rtc-7niu.git

java后台

websocket 处理拿在线用户

package com.ql.webrtc.controller.WebSocket;

import com.alibaba.fastjson.JSONObject;
import com.ql.webrtc.constant.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

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;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * WebSocket业务类
 * 此类用来作为RTC的信令服务器
 */
@Component
@Slf4j
@ServerEndpoint("/websocket/{uname}") //此注解相当于设置访问URL
public class WebSocketController {

    private Session session;
    private String uname;
    private static CopyOnWriteArraySet<WebSocketController> webSockets = new CopyOnWriteArraySet<>();
    private static Map<String, Session> sessionPool = new HashMap<String, Session>();


    @OnOpen
    public void onOpen(Session session, @PathParam(value = "uname") String uname) {
    }

    @OnClose
    public void onClose() {
    }

    @OnMessage
    public void onMessage(String message) {
        log.debug("【websocket消息】收到客户端消息:" + message);
    }

    // 此为广播消息
    public void sendAllMessage(String message) {
        
    }

    // 此为单点消息
    public void sendOneMessage(String userId, String message) {
        
    }

    // 此为单点消息(多人)
    public void sendMoreMessage(String[] userIds, String message) {
		
    }

    private List<Map<String, String>> onlineList() {
        // ..  在线用户
    }
}

spring controller 处理计算roomtoken

package com.ql.webrtc.controller.WebSocket;

import com.qiniu.rtc.RtcRoomManager;
import com.qiniu.util.Auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author qinlei
 * @description todo
 * @date 2021/6/8 17:34
 */
@RestController
@RequestMapping
@Slf4j
public class UserSigController {

    @Value("${qiniu.accessKey}")
    private String accessKey;
    @Value("${qiniu.secretKey}")
    private String secretKey;

    private String auth(String appid, long expireAt, String roomname, String userid, String permission){
        Auth auth = Auth.create(accessKey, secretKey);
        RtcRoomManager rmanager = new RtcRoomManager(auth);
        try {
            String token = rmanager.getRoomToken(appid, roomname, userid, expireAt, permission);
            return token;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("身份认证文件生成失败!",e);
            return null;
        }
    }

    @GetMapping("/createToken")
    public String createToken(@RequestParam("ad") String appid, @RequestParam("roomname") String roomname,
                              @RequestParam("userid") String userid,@RequestParam("permission") String permission,
                              @RequestParam("expireAt") long expireAt){
        return this.auth(appid,expireAt,roomname,userid,permission);
    }
}

vue 前端

  • 加入房间
joinRoom() {
       return new Promise((resolve, reject) => {
                   var date1 = new Date();
                   var date2 = new Date(date1);
                   date2.setDate(date1.getDate() + 1);
                   this.$axios.get(window._CONFIG['qMediaSockURL'] + "/createToken", {
                       params: {
                           ad: this.appid,
                           roomname: this.roomname,
                           userid: this.uname,
                           permission: "user",
                           expireAt: date2.getTime()
                       }
                   }).then((res) => {
                       if (res.status == 200) {
                           let roomtoken = res.data
                           this.roomtoken = roomtoken
                           // 这里替换成刚刚生成的 RoomToken
                           this.myRoom.joinRoomWithToken(this.roomtoken).then(() => {
                               console.log("joinRoom success!");
                               this.aCallShow = true
                               this.isLinked = true
                               resolve()
                           }).catch((err) => {
                               reject(err)
                           })
                       }
                   }).catch((err) => {
                       reject(err)
                   })
               })
     },
  • 发布媒体流
publish() {
        QNRTC.deviceManager.getLocalTracks({
          audio: {
            enabled: true,
            tag: "audio"
          },
          video: {
            enabled: true,
            tag: "video",
            facingMode: "environment"
          },
        }).then((localTracks) => {
          if (localTracks.length === 0) {
            return;
          }
          console.log("本地音视频流", localTracks);
          for (let localTrack of localTracks) {
            if (localTrack.info.trackId) {
              this.localTrackList.push(localTrack)
            }
            if (localTrack.info.tag === 'video') {
              localTrack.setMaster(true);
            }
            if (localTrack.info.tag === 'audio') {
              localTrack.setMaster(true);
            }
          }
          // 将刚刚的 Track 列表发布到房间中
          this.myRoom.publish(localTracks).then(() => {
            // 获取页面上的一个元素作为播放画面的父元素
            const localElement = document.getElementById("local");
            // 遍历本地采集的 Track 对象
            for (const localTrack of localTracks) {
              if (localTrack.info.trackId) {
                if (localTrack.info.kind !== 'audio') {
                  localTrack.play(localElement, true);
                }
                this.publishTrackList.push(localTrack)
                // 调用 Track 对象的 play 方法在这个元素下播放视频轨
              }
            }
          });
          console.log("publish success!");
        })
      },
  • 订阅远程接收方媒体流
autoSubscribe() {
        const trackInfoList = this.myRoom.trackInfoList;
        console.log("远程视频流", trackInfoList);
        this.subscribe(trackInfoList)
        // 添加事件监听,当房间中出现新的 Track 时就会触发,参数是 trackInfo 列表
        this.myRoom.on("track-add", (tracks) => {
          console.log('新的tack', tracks)
          this.subscribe(tracks);
        });
      },

后记下

本来想用webrtc原生的做,但是遇到各种各样的问题,sdp信息和ica都互相交换了,但是就是收不到视频流,领导催的急,就先用7牛云sdk顶顶,(反正老板不差钱^ _ ^),后面有空在好好研究下.

实际是要手机app和web网页通话,现在搞的 又得去学点安卓了. 本来是用uniapp做的安卓壳子,这么做 用web的sdk行不通,还是要用安卓的sdk.

试了tx,al的web的也都不能再安卓中嵌套


如果需要嵌入webview使用rtc通话,测试声网api可行

你可能感兴趣的:(中间件,websocket,rtc视频通话,vue)