JsSIP、Nginx接入Freeswitch音视频通话(三)
1、下载安装JsSIP
参考JsSIP官方文档,使用npm install jssip进行依赖安装
JsSIP官网地址:https://jssip.net/download/
JsSIP文档地址:https://jssip.net/documentation/
2、在Freeswitch所在的主机安装SSL证书
JsSIP利用现代Web浏览器中存在的 WebRTC 堆栈来实现音频/视频实时通信。而WebRTC在非本地局域网内使用必须是安全加密协议Web Socket Secure,简称WSS。
在Centos7系统上使用openssl生成证书。
#
openssl genrsa -des3 -out ssufs.key 2048
# 取消密码
openssl rsa -in ssufs.key -out ssufs.key
openssl req -new -key ssufs.key -out ssufs.csr
openssl req -new -x509 -key ssufs.key -out ca.crt -days 3650
openssl x509 -req -days 3650 -in ssufs.csr -CA ca.crt -CAkey ssufs.key -CAcreateserial -out ssufs.crt
所有指令执行完,总共是5个文件,只需要用到ssufs.key、ssufs.crt文件。在nginx安装目录下,创建certs文件夹,将ssufs.key、ssufs.crt拷贝到certs目录。我这里是随意建的,也可以放到其他的目录,只要配置文件指定证书所在目录即可。
进入nginx conf目录,修改nginx.conf文件,进行域名映射,域名与生成证书时输入的域名保持一致
user root;
worker_processes 1;
events {
worker_connections 1024;
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#gzip on;
upstream 95f5024653ff52061359b6086677cf24 {
server 192.168.0.11:5066 weight=10 max_fails=2 fail_timeout=6s;
server {
listen 80;
server_name 192.168.0.11;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'Upgrade';
proxy_read_timeout 86400s;
proxy_pass http://192.168.0.11:5066;
server {
listen 443 ssl;
server_name ssufs.com.cn;
#证书文件名称
ssl_certificate /usr/local/nginx/certs/ssufs.crt;
##私钥文件名称
ssl_certificate_key /usr/local/nginx/certs/ssufs.key;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'Upgrade';
proxy_read_timeout 86400s;
proxy_pass http://192.168.0.11:7443;
location = /favicon.ico {
log_not_found off;
access_log off;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
保存,进入到nginx sbin目录,使用./nginx -s reload重新加载配置文件。(nginx在编译安装时必须把SSL模板编译进来哟,否则这步配置会报错)
因为并没有申请真正的域名,使用的虚拟域名,为了能进行正常的解析,同时在/etc/hosts文件中添加IP和虚拟域名。
同时在客户端主机(JsSIP所在主机)也修改hosts文件添加IP、域名解析。进入到C:\Windows\System32\drivers\etc ,编辑hosts文件
这种方式有种弊端,即每个客户端主机都需要在hosts文件中添加IP、域名解析。还有一种方式可以通过路由器来配置做局域网内域名解析,当然也可以搭建域名解析服务器啦,这都是后话了。
3、防火墙开放端口
确保Freeswtich的5066、7443端口开放,5066是ws协议,7443是wss协议。JsSIP与freeswitch可以用5066或7443端口通信。因为是测试环境,我是直接把防火墙服务暂停了,生产服务器可不敢这么操作哟。
4、JsSIP代码示例
<template>
<div class="div_all">
<el-form :inline="true" :model="callParam" class="demo-form-inline head-form" size="medium">
<el-form-item label="通话服务器地址" prop="url">
<el-input v-model="callParam.url" placeholder="请输入通话服务地址" clearable :style="{width: '100%'}">
</el-input>
</el-form-item>
<el-form-item label="号码" prop="number">
<el-input v-model="callParam.number" placeholder="请输入通话号码" clearable :style="{width: '100%'}">
</el-input>
</el-form-item>
<el-form-item label="密码" prop="pwd">
<el-input v-model="callParam.pwd" placeholder="请输入通话密码" clearable :style="{width: '100%'}">
</el-input>
</el-form-item>
<el-form-item>
<el-button class="search-btn" @click="register()" icon="el-icon-search" size="medium">注册</el-button>
</el-form-item>
</el-form>
style="width: 424px; height: 324px;background-color: #333333; border: 2px solid blue; padding:0px; margin-top: 4px;">
<video id="video" width="420px" height="320px" autoplay></video>
<audio id="audio" controls></audio>
</template>
<script>
import JsSIP from 'jssip'
import axios from 'axios'
import pagination from '@/components/pagination'
export default {
components: {
pagination
data() {
return {
searchParam: {
time: null,
module: '',
userName: '',
pageNum: 1,
pageSize: 10,
total: 0
pageData: [],
callParam: {
url: 'ssufs.com.cn',
number: 1009,
pwd: 1234,
},//保存通话相关数据
mounted() {
methods: {
* 通话方法
register() {
var socket = new JsSIP.WebSocketInterface("ws://" + this.callParam.url);
console.log("socket",socket)
//注册号码
var configuration = {
sockets: [socket],
uri: 'sip:' + this.callParam.number + '@192.168.0.11',
password: this.callParam.pwd,
register: true,
session_timers: false
var ua = new JsSIP.UA(configuration);
ua.start();
ua.on('connected', (e) => console.log('[SIP Phone] : Connected (On Call)', e));
ua.on('registered', (e) => {
// console.log('[SIP Phone] : Registered (On Call)', e);
console.log('账号注册响应:::', e.response)
ua.on('registrationFailed', (e) => console.log('[SIP Phone] : Registration Failed (On Call)', e));
// 注册打电话的回调事件
var eventHandlers = {
'progress': function (e) {
console.log('call is in progress');
'failed': function (e) {
var res = JSON.stringify(e);
console.log('call failed with cause: ',res.message);
console.log('call failed with cause: ',res);
'ended': function (e) {
console.log('call ended with cause: ' + e);
'confirmed': function (e) {
console.log('call confirmed');
var options = {
'eventHandlers': eventHandlers,
'mediaConstraints': {'audio': true, 'video': true}
//拨打电话
var session = ua.call('sip:1019@192.168.0.11', options);
console.log("session:::", session)