jssip+webRtc+freeswitch 实现web端语音通话

1 篇文章 0 订阅
1 篇文章 0 订阅

该文章只说明前端代码逻辑,如有错误,感谢指出。
jssip官方网站
jssip中文文档api

html部分代码
主要通过ontrack事件监听媒体流,实现语音实时通话

<template>
  <el-card id="sip">
    <header>
      <h1>SIP呼叫</h1>
    </header>
    <el-divider></el-divider>
    <main>
      <div class="btns">
        <el-input
          type="text"
          placeholder="输入号码"
          v-model="phoneNum"
          size="small"
          style="width: 15%; margin-right: 10px"
        ></el-input>
        <el-button type="success" size="small" @click="call()"
          >SIP拨号</el-button
        >
        <el-button type="danger" size="small" @click="hangup()">挂断</el-button>
      </div>
      <!-- //挂断、接通、执行的录音 -->
      <audio id="audio" autoplay="autoplay" src="" controls></audio>
    </main>
  </el-card>
</template>

/
/
js代码部分

<script>
export default {
  data() {
    return {
      ua: null,
      socket: null,
      eventHandlers: null,
      phoneNum: null,
      config: {},
      isRegister: false, // 是否已注册
      registerState: false,
    };
  },
  mounted() {},
  methods: {
    // 挂断
    hangup() {
      if (this.ua) {
        this.ua.stop();
      }
    },
    // 拨号
    call() {
      this.$nextTick(async () => {
        await this.getSipInfo();
        console.log("获取接口");

        if (!this.registerState) {
          this.callPhone(); // 注册
          console.log("注册事件");
        }
        await this.testCall();
        console.log("判断是否注册");
      });
    },
    testCall(sip_phone_number_) {
      console.log("sip3");

      // Register callbacks to desired call events
      // 判断是否注册
      if (this.isRegister) {
      }
      let options = {
        eventHandlers: this.eventHandlers,
        mediaConstraints: {
          audio: true,
          video: false,
          mandatory: { maxWidth: 640, maxHeight: 360 },
        },
      };

      // 后端请求返回的参数格式
      // let obj = {
      //   sip: "47.98.172.37:5960",
      //   wsip: "wss://h5.zzz888.cn:7443",
      //   username: "26ac631ac14213882738650",
      //   password: "28ca40e86b27c4a8f1b606587eec80f6",
      //   uri: `sip:26ac631ac14215171505290@47.98.172.37:5960`,
      // };

      // console.log("this.config", this.config);
      let obj = {
        sip: this.config.sip,
        wsip: this.config.wssip,
        username: this.config.ws_user,
        password: this.config.ws_pass,
        uri: `sip:${this.config.ws_user}@${this.config.sip}`,
      };

      this.ua.call("sip:fs" + this.phoneNum + "@" + obj["sip"], options);
    },
    //sip 配置
    getUa() {},
    // 调用接口,获取sip信息
    async getSipInfo(phone) {
      console.log("sip11111111");
      // this.phoneNum = "13882738650";
      // 获取主叫号码
      let activePhone = localStorage.getItem("ms_username");
      let parentId = localStorage.getItem("parentId");
      let params = {
        activePhone: activePhone,
        passivePhone: this.phoneNum,
        parentId,
      };
      let res = await callAppBind(params);
      if (res.data.statusCode == "00000") {
        Message.success("sip拨打成功");
      } else if (res.data.statusCode != "00000") {
        Message.error(res.data.message);
      } else {
        Message.error(res.data.data);
      }
      this.config = res.data.data;
    },
    // 注册sip
    callPhone() {
      console.log("sip2");
      // debugger;
      // 拨打号码
      // this.getSipInfo()
      JsSIP.C.SESSION_EXPIRES = 120;
      JsSIP.C.MIN_SESSION_EXPIRES = 120;
      let obj = {
        sip: this.config.sip,
        wsip: this.config.wssip,
        username: this.config.ws_user,
        password: this.config.ws_pass,
        uri: `sip:${this.config.ws_user}@${this.config.sip}`,
      };

      this.eventHandlers = {
        progress: function (e) {
          console.log("call is in progress");
        },
        failed: function (e) {
          console.log("call failed: ", e);
        },
        ended: function (e) {
          console.log("call ended : ", e);
        },
        confirmed: function (e) {
          console.log("call confirmed");
        },
      };
      // 配置信息
      if (this.ua) {
        this.ua.stop();
      }
      this.socket = new JsSIP.WebSocketInterface(obj.wsip);
      // const socket = new this.JsSIP.WebSocketInterface(obj.wsip);
      const configuration = {
        sockets: [this.socket],
        uri: obj.uri,
        password: obj.password,
        register: false, //指示JsSIP用户代理是否应在启动时自动注册
        //utbound_proxy_set: obj.wsip,
        contact_uri:
          "sip:" +
          obj["username"] +
          "@" +
          obj["sip"] +
          ";transport=" +
          (obj["wsip"].substr(0, 3) == "wss" ? "wss" : "ws"),
      };
      console.log("configuration", configuration);
      // 创建UA
      let options = {
        eventHandlers: this.eventHandlers,
        mediaConstraints: { audio: true, video: false },
      };

      this.ua = new JsSIP.UA(configuration);
      console.log("call号码", "sip:bob" + "18398754423" + "@" + obj["sip"]);
      // this.ua.call("sip:fs" + "17381586338" + "@" + obj["sip"], options);
      // 状态回调
      this.ua.on("connected", function (e) {
        console.log("--------已连接---------");
      });
      this.ua.on("disconnected", function (e) {
        console.log("-------未连接--------");
      });
      this.ua.on("registered", function (e) {
        console.log("--------已注册-------");
        // this.isRegister = true;
        // this.ua.unregister((options = null));
        this.registerState = true;
      });
      this.ua.on("unregistered", function (e) {
        console.log("------未注册--------");
        this.registerState = false;
      });
      this.ua.on("registrationFailed", (e) => {
        // this.$message.error("SIP注册失败,请联系管理员");
      });
      //客户接到了电话才会走这里
      this.ua.on("newRTCSession", (e) => {
        let audio = document.getElementById("audio");
        let session = e.session;
        let peerconnection = session.connection;
        if (e.originator === "local") {
          // addstream方法已被淘汰,所以现在不适用了,但还是可以正常使用
          // peerconnection.addEventListener("addstream", (event) => {
          //   // try {
          //     audio.srcObject = event.stream;
          //     console.log("打电话", event.stream);
          //   // } catch (e) {
          //     // console.log(e);
          //   // }
          // });
          peerconnection.ontrack = (event) => {
            audio.srcObject = event.streams[0];
            // console.log("打电话", event.stream);
          };
        } else {
          let callers = session.remote_identity.uri.user;
          //emitter.setCallinStatus.call(true, callers);
        }

        // 接听失败
        session.on("failed", (mdata) => {
          //emitter.setCallinStatus.call(false);
          // console.log("来电的时候 拒接或者 还没接听对方自己就挂断了");
        });

        // 接听成功
        session.on("accepted", (response, cause) => {
          console.log("接听成功");
          //  可以在这里执行媒体流的操作
        });

        // 接听成功后 挂断
        session.on("ended", () => {
          console.log("接听结束");
        });

        // 通话被挂起
        session.on("hold", (data) => {
          let org = data.originator;
          if (org === "local") {
            // console.log("通话被本地挂起:", org);
          } else {
            // console.log("通话被远程挂起:", org);
          }
        });

        // 通话被继续
        session.on("unhold", (data) => {
          let org = data.originator;
          if (org === "local") {
            console.log("通话被本地继续:", org);
          } else {
            console.log("通话被远程继续:", org);
          }
        });

        e.session.on("confirmed", (e) => {
          console.log("--------------------------电话接通,开始通话");
        });
        e.session.on("ended", (e) => {
          console.log("---------------------------电话已挂断,开始问卷");
        });
        //绑定回调后先给坐席‘滴’一声
        // e.session.answer();
      });
      // 登陆
      this.ua.start();
      // 登出
      // ua.stop();
    },
  },
};
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值