技术分享| 小程序实现音视频通话
Posted anyRTC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技术分享| 小程序实现音视频通话相关的知识,希望对你有一定的参考价值。
上一期我们把前期准备工作做完了,这一期就带大家实现音视频通话!
sdk 二次封装
为了更好的区分功能,我分成了六个 js 文件
-
config.js 音视频与呼叫邀请配置
-
store.js 实现音视频通话的变量
-
rtc.js 音视频逻辑封装
-
live-code.js 微信推拉流状态码
-
rtm.js 呼叫邀请相关逻辑封装
-
util.js 其他方法
config.js
配置 sdk 所需的 AppId
,如需私有云可在此配置
-
RTC 音视频相关
-
RTM 实时消息(呼叫邀请)
module.exports = AppId: "", // RTC 私有云配置 RTC_setParameters: setParameters: // //配置私有云网关 // ConfPriCloudAddr: // ServerAdd: "", // Port: , // Wss: true, // , , , // RTM 私有云配置 RTM_setParameters: setParameters: // //配置内网网关 // confPriCloudAddr: // ServerAdd: "", // Port: , // Wss: true, // , , ,
store.js
整个通话系统使用的变量设置
module.exports =
// 网络状态
networkType: "",
// rtm连接状态
rtmNetWorkType: "",
// rtc连接状态
rtcNetWorkType: "",
// 视频通话0 语音通话1
Mode: 0,
// 当前场景 0:首页 1:呼叫页面 2:通信页面
State: 0,
// 本地用户uid
userId: "",
// 远端用户uid
peerUserId: "",
// 频道房间
channelId: "",
// RTM 客户端
rtmClient: null,
// RTC 客户端
rtcClient: null,
// 本地录制地址(小程序特有推流)
livePusherUrl: "",
// 远端播放(小程序特有拉流)
livePlayerUrl: "",
// 主叫邀请实例
localInvitation: null,
// 被叫收到的邀请实例
remoteInvitation: null,
// 是否正在通话
Calling: false,
// 是否是单人通话
Conference: false,
// 通话计时
callTime: 0,
callTimer: null,
// 30s 后无网络取消通话
networkEndCall: null,
networkEndCallTime: 30*1000,
// 断网发送查询后检测是否返回消息
networkSendInfoDetection: null,
networkSendInfoDetectionTime: 10*1000,
rtc.js
音视频 sdk 二测封装,方便调用
// 引入 RTC
const ArRTC = require("ar-rtc-miniapp");
// 引入 until
const Until = require("./util");
// 引入 store
let Store = require("./store");
// 引入 SDK 配置
const Config = require("./config");
// 初始化 RTC
const InItRTC = async () =>
// 创建RTC客户端
Store.rtcClient = new ArRTC.client();
// 初始化
await Store.rtcClient.init(Config.AppId);
Config.RTC_setParameters.setParameters && await Store.rtcClient.setParameters(Config.RTC_setParameters.setParameters)
// 已添加远端音视频流
Store.rtcClient.on('stream-added', rtcEvent.userPublished);
// 已删除远端音视频流
Store.rtcClient.on('stream-removed', rtcEvent.userUnpublished);
// 通知应用程序发生错误
Store.rtcClient.on('error', rtcEvent.error);
// 更新 Url 地址
Store.rtcClient.on('update-url', rtcEvent.updateUrl);
// 远端视频已旋转
Store.rtcClient.on('video-rotation', rtcEvent.videoRotation);
// 远端用户已停止发送音频流
Store.rtcClient.on('mute-audio', rtcEvent.muteAudio);
// 远端用户已停止发送视频流
Store.rtcClient.on('mute-video', rtcEvent.muteVideo);
// 远端用户已恢复发送音频流
Store.rtcClient.on('unmute-audio', rtcEvent.unmuteAudio);
// 远端用户已恢复发送视频流
Store.rtcClient.on('unmute-video', rtcEvent.unmuteAudio);
// RTC 监听事件处理
const rtcEvent =
// RTC SDK 监听用户发布
userPublished: (
uid
) =>
console.log("RTC SDK 监听用户发布", uid);
Store.networkSendInfoDetection && clearTimeout(Store.networkSendInfoDetection);
if (Store.Mode == 0)
wx.showLoading(
title: '远端加载中',
mask: true,
)
// 订阅远端用户发布音视频
Store.rtcClient.subscribe(uid, (url) =>
console.log("远端用户发布音视频", url);
// 向视频页面发送远端拉流地址
Until.emit("livePusherUrlEvent",
livePlayerUrl: url
);
, (err) =>
console.log("订阅远端用户发布音视频失败", err);
)
,
// RTC SDK 监听用户取消发布
userUnpublished: (
uid
) =>
console.log("RTC SDK 监听用户取消发布", uid);
Store.networkSendInfoDetection && clearTimeout(Store.networkSendInfoDetection);
Store.networkSendInfoDetection = setTimeout(() =>
wx.showToast(
title: '对方网络异常',
icon: "error"
);
setTimeout(() =>
rtcInternal.leaveChannel(false);
, 2000)
, Store.networkSendInfoDetectionTime);
,
// 更新 Url 地址
updateUrl: (
uid,
url
) =>
console.log("包含远端用户的 ID 和更新后的拉流地址", uid, url);
// 向视频页面发送远端拉流地址
Until.emit("livePusherUrlEvent",
livePlayerUrl: url
);
,
// 视频的旋转信息以及远端用户的 ID
videoRotation: (
uid,
rotation
) =>
console.log("视频的旋转信息以及远端用户的 ID", uid, rotation);
,
// 远端用户已停止发送音频流
muteAudio: (
uid
) =>
console.log("远端用户已停止发送音频流", uid);
,
// 远端用户已停止发送视频流
muteVideo: (
uid
) =>
console.log("远端用户已停止发送视频流", uid);
,
// 远端用户已恢复发送音频流
unmuteAudio: (
uid
) =>
console.log("远端用户已恢复发送音频流", uid);
,
// 远端用户已恢复发送视频流
unmuteAudio: (
uid
) =>
console.log("远端用户已恢复发送视频流", uid);
,
// 通知应用程序发生错误。 该回调中会包含详细的错误码和错误信息
error: (
code,
reason
) =>
console.log("错误码:" + code, "错误信息:" + reason);
,
// RTC 内部逻辑
const rtcInternal =
// 加入频道
joinChannel: () =>
Store.rtcClient.join(undefined, Store.channelId, Store.userId, () =>
console.log("加入频道成功", Store.rtcClient);
// 发布视频
rtcInternal.publishTrack();
// 加入房间一定时间内无人加入
Store.networkSendInfoDetection && clearTimeout(Store.networkSendInfoDetection);
Store.networkSendInfoDetection = setTimeout(() =>
wx.showToast(
title: '对方网络异常',
icon: "error"
);
setTimeout(() =>
rtcInternal.leaveChannel(false);
, 2000)
, Store.networkSendInfoDetectionTime);
, (err) =>
console.log("加入频道失败");
);
,
// 离开频道
leaveChannel: (sendfase = true) =>
console.log("离开频道", sendfase);
console.log("RTC 离开频道", Store);
Store.networkSendInfoDetection && clearTimeout(Store.networkSendInfoDetection);
if (Store.rtcClient)
// 引入 RTM
const RTM = require("./rtm");
Store.rtcClient.destroy(() =>
console.log("离开频道", RTM);
if (sendfase)
// 发送离开信息
RTM.rtmInternal.sendMessage(Store.peerUserId,
Cmd: "EndCall",
)
Until.clearStore();
// 返回首页
wx.reLaunch(
url: '../index/index',
success:function ()
wx.showToast(
title: '通话结束',
icon:'none'
)
);
, (err) =>
console.log("离开频道失败", err);
)
else
Until.clearStore();
,
// 发布本地音视频
publishTrack: () =>
Store.rtcClient.publish((url) =>
console.log("发布本地音视频", url);
// 本地录制地址(小程序特有推流)
Store.livePusherUrl = url;
// 向视频页面发送本地推流地址
Until.emit("livePusherUrlEvent",
livePusherUrl: url
);
, (
code,
reason
) =>
console.log("发布本地音视频失败", code, reason);
)
,
// 切换静音
switchAudio: (enableAudio = false) =>
/**
* muteLocal 停止发送本地用户的音视频流
* unmuteLocal 恢复发送本地用户的音视频流
*/
Store.rtcClient[enableAudio ? 'muteLocal' : 'unmuteLocal']('audio', () =>
wx.showToast(
title: enableAudio ? '关闭声音' : '开启声音',
icon: 'none',
duration: 2000
)
, (
code,
reason
) =>
console.log("发布本地音视频失败", code, reason);
)
,
module.exports =
InItRTC,
rtcInternal,
live-code.js
微信推拉流状态码
module.exports =
1001: "已经连接推流服务器",
1002: "已经与服务器握手完毕,开始推流",
1003: "打开摄像头成功",
1004: "录屏启动成功",
1005: "推流动态调整分辨率",
1006: "推流动态调整码率",
1007: "首帧画面采集完成",
1008: "编码器启动",
"-1301": "打开摄像头失败",
"-1302": "打开麦克风失败",
"-1303": "视频编码失败",
"-1304": "音频编码失败",
"-1305": "不支持的视频分辨率",
"-1306": "不支持的音频采样率",
"-1307": "网络断连,且经多次重连抢救无效,更多重试请自行重启推流",
"-1308": "开始录屏失败,可能是被用户拒绝",
"-1309": "录屏失败,不支持的android系统版本,需要5.0以上的系统",
"-1310": "录屏被其他应用打断了",
"-1311": "Android Mic打开成功,但是录不到音频数据",
"-1312": "录屏动态切横竖屏失败",
1101: "网络状况不佳:上行带宽太小,上传数据受阻",
1102: "网络断连, 已启动自动重连",
1103: "硬编码启动失败,采用软编码",
1104: "视频编码失败",
1105: "新美颜软编码启动失败,采用老的软编码",
1106: "新美颜软编码启动失败,采用老的软编码",
3001: "RTMP -DNS解析失败",
3002: "RTMP服务器连接失败",
3003: "RTMP服务器握手失败",
3004: "RTMP服务器主动断开,请检查推流地址的合法性或防盗链有效期",
3005: "RTMP 读/写失败",
2001: "已经连接服务器",
2002: "已经连接 RTMP 服务器,开始拉流",
2003: "网络接收到首个视频数据包(IDR)",
2004: "视频播放开始",
2005: "视频播放进度",
2006: "视频播放结束",
2007: "视频播放Loading",
2008: "解码器启动",
2009: "视频分辨率改变",
"-2301": "网络断连,且经多次重连抢救无效,更多重试请自行重启播放",
"-2302": "获取加速拉流地址失败",
2101: "当前视频帧解码失败",
2102: "当前音频帧解码失败",
2103: "网络断连, 已启动自动重连",
2104: "网络来包不稳:可能是下行带宽不足,或由于主播端出流不均匀",
2105: "当前视频播放出现卡顿",
2106: "硬解启动失败,采用软解",
2107: "当前视频帧不连续,可能丢帧",
2108: "当前流硬解第一个I帧失败,SDK自动切软解",
;
rtm.js
实时消息(呼叫邀请)二次封装。使用 p2p 消息发送接受(信令收发),呼叫邀请
// 引入 anyRTM
const ArRTM = require("ar-rtm-sdk");
// 引入 until
const Until = require("./util");
// 引入 store
let Store = require("./store");
// 引入 SDK 配置
const Config = require("../utils/config");
// 引入 RTC
const RTC = require("./rtc");
// 本地 uid 随机生成
Store.userId = Until.generateNumber(4) + '';
// 监听网络状态变化事件
wx.onNetworkStatusChange(function (res)
// 网络状态
Store.networkType = res.networkType
// 无网络
if (res.networkType == 'none')
wx.showLoading(
以上是关于技术分享| 小程序实现音视频通话的主要内容,如果未能解决你的问题,请参考以下文章