/** * WebPtt类,用于实现WebPtt功能。 */ class WebPtt { /** * @param {Object} options * @param {String} options.server=ws://121.36.101.115:9006 - PTT服务器地址 * @param {String|Element} options.speak - video元素或id,用于发送语音 * @param {String|Element} options.listen - video元素或id,用于接收语音 * @param {String} options.account - PTT账号 * @param {String} options.password - PTT密码 * @param {Function} options.onLogin - 登录成功回调 * @param {Function} options.onLogout - 离线回调 * @param {Function} options.onJoinGrp - 加入组群回调 * @param {Function} options.onTempGrp - 加入临时组群回调 * @param {Function} options.onDuplexCall - 全双工回调回调 * @param {Function} options.onSpeak - 讲话状态回调 * @param {Function} options.onAddStream - 音频流状态回调 * @param {Function} options.onMessage - 消息接收回调 * @param {Function} options.onError - 异常状态回调 */ constructor(options) { // 初始化webPtt实例的属性和方法 const { server, speak, listen, account, password } = options; if (!speak) throw new Error("speak element is required"); if (!listen) throw new Error("speak element is required"); if (listen === speak) throw new Error("speak element is equal to listen element"); this.server = server ?? process.env.VUE_APP_PTT_SERVER; this.spkSession = null; this.remoteuid = null; this.pttSpeakElement = typeof speak === "string" ? document.getElementById(speak) : speak instanceof Element ? speak : null; if (!this.pttSpeakElement) throw new Error("Cannot find speak element"); this.pttSpeakElement = speak; this.pttListenElement = typeof listen === "string" ? document.getElementById(listen) : listen instanceof Element ? listen : null; if (!this.pttListenElement) throw new Error("Cannot find listen element"); this.pttListenElement = listen; this.account = account; this.password = password; Connect(this, options); } // 方法示例:发送PushToTalk请求 login() { PttLogin(this.account, this.account, this.password); } logout() { console.log("logout", this.pttListenElement.srcObject); PttLogout(this.account, this.pttListenElement.srcObject); } startCall() { this.spkSession = PttStartCall(this.account); console.log("speak session=", this.spkSession); } stopCall() { console.log("stop call", this.pttSpeakElement.srcObject); PttStopCall(this.spkSession, this.pttSpeakElement.srcObject); } joinGroup(gid) { PttInGroup(this.account, parseInt(gid)); } leaveGroup() { PttOutGroup(this.account); } } function hasFn(obj, fnName) { return Object.prototype.hasOwnProperty.call(obj, fnName) && obj[fnName] && typeof obj[fnName] === "function"; } function Connect(self, options) { WebPttInit(self.server, { pttCb: { onLogin: (status, uid) => { // 登陆回调 // status == 0 登陆成功,uid 为当前用户 id // status < 0 登陆失败 if (hasFn(options, "onLogin")) options.onLogin(status, uid); }, onJoinGrp: (status, gid) => { // 进组回调 // status == 0 进组成功,gid 为当前群组 id // status < 0 进组失败 console.log("ptt join group status=", status, " gid=", gid); if (hasFn(options, "onJoinGrp")) options.onJoinGrp(status, gid); }, onTempGrp: (status, uid, name) => { // status == 0 临时群组创建成功 uid 为对端 id // status == 1 退出临时群组 // status == 2 收到临时群组邀请,uid 为对端 id,name 为对端名字 console.log("ptt temp group status=", status, " uid=", uid, " name=", name); if (hasFn(options, "onTempGrp")) options.onTempGrp(status, uid, name); }, onDuplexCall: function (status, uid) { // 全双工回调 // status == 10 && uid == 0 全双工主叫开始 // status == 10 && uid > 0 全双工被叫开始,uid 为对端id // status == 11 全双工呼叫建立 // status == 15 全双工呼叫结束 console.log("ptt duplex call status=", status, " uid=", uid); if (status === 10) { if (uid !== 0) { console.log("ptt recv remote duplex call request", uid); self.remoteuid = uid; } else { console.log("ptt send duplex call request"); } } else if (status === 11) { console.log("ptt recv remote duplex call accept"); } else if (status === 15) { console.log("ptt recv remote duplex call refuse"); } if (hasFn(options, "onDuplexCall")) options.onDuplexCall(status, uid); }, onSpeak: (status, uid) => { // 讲话状态回调 // status < 0 本机讲话失败 // status == 0 uid == 0 其他成员讲话结束 // status == 0 uid > 0 其他成员讲话开始,uid 为讲话者 id console.log("ptt speak status===", status, " uid=", uid); if (hasFn(options, "onSpeak")) options.onSpeak(status, uid); }, onAddStream: (dir, stream) => { // 音频流状态回调 // dir == 1 本机讲话音频流创建成功,stream 为音频流 // dir == 0 本机监听音频流创建成功,stream 为音频流 if (dir === 1) { self.pttSpeakElement = typeof self.pttSpeakElement === "string" ? document.getElementById(self.pttSpeakElement) : self.pttSpeakElement instanceof Element ? self.pttSpeakElement : null; if (self.pttSpeakElement) self.pttSpeakElement.srcObject = stream; } else { self.pttListenElement = typeof self.pttListenElement === "string" ? document.getElementById(self.pttListenElement) : self.pttListenElement instanceof Element ? self.pttListenElement : null; if (self.pttListenElement) self.pttListenElement.srcObject = stream; console.log("onAddStream", self.pttListenElement.srcObject); } if (hasFn(options, "onAddStream")) options.onAddStream(dir, stream); }, onMessage: (msg) => { console.log("ptt recv msg=", msg); // document.getElementById("message").innerText = "recv msg:"+JSON.stringify(msg); if (hasFn(options, "onMessage")) options.onMessage(msg); }, onLogout: () => { console.log("ptt logout"); if (hasFn(options, "onLogout")) options.onLogout(); }, onError: (code, info) => { // 异常状态回调 // code 为 0 表示无异常,否则为出现异常 if (hasFn(options, "onError")) options.onError(code, info); }, }, }); } export default WebPtt;