介绍

YeIM-CallKit是基于LiveKit WebRTC SDK的实时音视频聊天 uni-app 原生插件,支持 Android 和 iOS,无需第三方服务支持,本地架设流媒体服务端,适合内网、公网、私有化、私密化部署。

流媒体后端服务使用开源 SFU 架构的LiveKit-Server媒体服务器,内置 TURN 中继服务,无需第三方支持即可实现公网转发。

目前该原生插件暂时仅支持一对一视频聊天、一对一语音聊天,未来会不断支持多对多、屏幕分享等多样化功能(注:不支持 x86 架构,无法使用模拟器运行通话)。

该原生插件不包含 IM 相关服务,信令等呼叫操作请自行使用其他方式进行,例如 WebSocket、HTTP。

YeIM-CallKit是音视频聊天客户端插件,LiveKit-Server是支撑音视频聊天的媒体后端服务。

使用YeIM-CallKit必须先运行LiveKit-Server,下面将告诉你怎么运行它。

LiveKit-Server

安装

Linux

curl -sSL https://raw.githubusercontent.com/wzJun1/YeIM-CallKit/main/install.sh | bash

或者使用国内镜像

curl -sSL https://raw.nuaa.cf/wzJun1/YeIM-CallKit/main/install.sh | bash

MacOS

brew install livekit

Windows

64 位 Windows10 以上操作系统下载:https://github.com/wzJun1/YeIM-CallKit/raw/main/x64-server.exe

启动

开发环境默认密钥

api-key:devkey
secret-key:secret

Linux | Mac

# --dev 以开发模式启动
# 内网环境下推荐以开发模式启动做测试
# 公网请勿以开发模式启动,因为没有启动TURN中继服务,而一般情况无法正常打洞,也就无法正常通话
livekit-server --dev
# --config 以配置文件启动
livekit-server --config config.yaml

Windows

# --dev 以开发模式启动
# 内网环境下推荐以开发模式启动做测试
# 公网请勿以开发模式启动,因为没有启动TURN中继服务,而一般情况无法正常打洞,也就无法正常通话
x64-server.exe --dev
# --config 以配置文件启动
x64-server.exe --config config.yaml

配置文件

https://raw.githubusercontent.com/wzJun1/YeIM-CallKit/main/config-内网用.yaml

https://raw.githubusercontent.com/wzJun1/YeIM-CallKit/main/config-外网用.yaml

服务启动注意事项

如果是在内网环境下使用,那么无论使用--dev或者--config启动都是可以的。启动完成后仅需将本地 7880 端口套一层 SSL 即可正常使用YeIM-CallKit,套 SSL 方法下面会说。

如果是在公网环境下使用,请使用--config配合配置文件启动

内网环境启动流程

1.准备一个域名,例如 livekit-server.xxxxxx.com,将域名解析到内网 IP
2.准备这个域名的 SSL/TLS 证书,即便使用免费证书Let's Encrypt亦可,证书可到 https://freessl.cn/ 进行免费申请,如果内网服务器使用了宝塔面板,也可直接申请免费证书
3.按照上述方法启动livekit-server或者以配置文件启动均可(以配置文件启动请自行修改 api-key 和 api-secret),服务默认端口为 7880
4.使用Nginx反代这个本地服务,并开启 SSL,这里附一份Nginx 配置文件案例,仅供参考

公网环境启动流程

1.确保公网服务器环境纯净,因 TURN 服务需占用 443 端口,所以请保证其他程序未占用 443,包括 Nginx。
2.防火墙规则开启端口:80,443,3478,4431,7880,7881,30000 到 60000 端口,请一定确认以上端口 TCP/UDP 防火墙均为允许通过,否则将无法正常使用
3.准备两个域名,例如 livekit-server.xxxxxx.com livekit-turn.xxxxxx.com,将域名解析到公网 IP
4.准备这两个域名的 SSL/TLS 证书,即便使用免费证书Let's Encrypt亦可,证书可到 https://freessl.cn/ 进行免费申请,如果内网服务器使用了宝塔面板,也可直接申请免费证书
5.以配置文件启动livekit-server,服务默认端口为 7880,TURN 端口为 443。配置文件演示如下:

config.yaml

port: 7880
log_level: info
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 60000
use_external_ip: true
keys:
这里填自定义的api-key: 这里填自定义的api-secert,32位
turn:
enabled: true
domain: livekit-turn.xxxxxx.com(这里替换成你自己的域名)
tls_port: 443
cert_file: 这里填livekit-turn.xxxxxx.com的TLS证书地址
key_file: 这里填livekit-turn.xxxxxx.com的TLS证书密钥地址

6.使用Nginx反代这个本地服务,并开启 SSL,这里附一份Nginx 配置文件案例,仅供参考

Nginx 配置文件

server
{
listen 80;
#如果作为单机实例的情况:内网环境使用音视频通话不需要TURN,可直接使用443端口。这里使用了4431是因为需要在单机公网环境下使用TURN,非负载架构TURN必须使用443端口,开发者可根据实际情况修改。
#一般情况如果是公网部署,就按此配置即可
listen 4431 ssl http2;
server_name 你的域名;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/home;
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
ssl_certificate /www/server/panel/vhost/cert/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
#SSL-END
#反向代理规则
location /
{
proxy_pass http://127.0.0.1:7880;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
}
}

服务启动验证

  1. 完成以上启动步骤后,使用浏览器访问https://livekit-server.xxxxxx.com:4431,正常情况显示OK字样。
  2. 使用 https://livekit.io/connection-test 进行验证,验证如下图(此步骤需配合 Token,可先查看 Token 生成相关文档,再使用此网站进行验证服务是否正常。)

LiveKit-Backend

说明

LiveKit-Backend是操控LiveKit-Server的集成 SDK,可以对通话房间Room使用 API 进行一系列控制,也可以用于生成 Token。

LiveKit-Backend拥有多种语言的实现,包括 JavaScript、GO、Python、Java、PHP,这里可以查看相关 SDK 源码:https://docs.livekit.io/references/client-sdks/

Room

LiveKit-Server为通话者创建的房间,用户需要在房间内通过推送视频流和音频流进行交互。

Token

用户进入房间的凭证。

安装

你可以在你自己的项目中安装LiveKit-Backend依赖,从而实现对通话房间Room使用 API 进行一系列控制,也可以用于生成 Token。

JavaScript

npm install livekit-server-sdk --save
JavaScript 生成 Token
import express from 'express';
import { AccessToken } from 'livekit-server-sdk';
const createToken = () => {
const room = '房间号';
const identity = '用户ID标识';
const at = new AccessToken('api-key', 'secret-key', {
identity: participantName,
});
at.addGrant({ roomJoin: true, room: room });
return at.toJwt();
};
const app = express();
const port = 3000;
app.get('/getToken', (req, res) => {
res.send(createToken());
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});

Java

<dependencies>
<dependency>
<groupId>io.livekit</groupId>
<artifactId>livekit-server</artifactId>
<version>0.5.3</version>
</dependency>
</dependencies>
Java 生成 Token
AccessToken token = new AccessToken("apiKey", "secret");
token.setIdentity("用户ID标识");
token.addGrants(new RoomJoin(true), new RoomName("房间号"));
System.out.println("New access token: " + token.toJwt())

PHP

composer require agence104/livekit-server-sdk
PHP 生成 Token
$room = '房间号';
$identity = '用户ID标识';
$tokenOptions = (new AccessTokenOptions())
->setIdentity($identity);
$videoGrant = (new VideoGrant())
->setRoomJoin();
->setRoomName($room);
$token = (new AccessToken('api-key', 'secret-key'))
->init($tokenOptions)
->setGrant($videoGrant)
->toJwt();

GO

go get github.com/livekit/server-sdk-go
GO 生成 Token
import (
"http"
"log"
"time"
lksdk "github.com/livekit/server-sdk-go"
"github.com/livekit/protocol/auth"
)
func getJoinToken(apiKey, apiSecret, room, identity string) string {
config = readFile(config)
at := auth.NewAccessToken(os.GetEnv("api-key"), os.GetEnv("secret"))
grant := &auth.VideoGrant{
RoomJoin: true,
Room: room,
}
at.AddGrant(grant).
SetIdentity(identity).
SetValidFor(time.Hour)
return at.ToJWT()
}
func main() {
http.HandleFunc("/getToken", func(w http.ResponseWriter, r *http.Request) {
w.write(getJoinToken())
})
log.Fatal(http.ListenAndServe(":8080", nil))
}

Python

pip install livekit-server-sdk-python
Python 生成 Token
import livekit
grant = livekit.VideoGrant(room_join=True, room="房间号")
access_token = livekit.AccessToken(os.environ("api-key"), os.environ("secret"), grant=grant, identity="用户ID标志", name="Bob")
token = access_token.to_jwt()

YeIM-CallKit

插件不包含 IM 相关服务,信令等呼叫操作请自行使用其他方式进行,例如 WebSocket、HTTP

以下演示通话流程:

呼叫方用户通过点击事件或者其他事件调用startC2CVideoCall方法进入呼叫页面,此时项目开发者应通过 WebSocket 或者 HTTP 通知接听方调用answerC2CVideoCall进入接听页面,接听方在接听页面点击接听按钮,双方开始进入通话。

一对一视频呼叫

startC2CVideoCall(options, callback) -> Void

options
字段类型必填默认说明
wsURLString媒体服务器域名,必须使用 wss 协议
tokenString用户凭证
userInfoObject本人用户信息
callerUserInfoObject对方用户信息
videoOptionsObject可选视频参数
audioOptionsObject可选音频参数
callRingString呼叫铃声,支持本地和网络 URL,为空则不播放
  • 例如:1. /static/1.mp3
  • 例如:2. http://xxx.com/1.mp3
  • answerRingString接听铃声
    hungupRingString挂断铃声
    userInfo
    字段类型必填默认说明
    nicknameString用户昵称
    avatarString头像 URL
    identityString用户 ID 标志
    videoOptions
    字段类型必填默认说明
    positionStringfront初始摄像头,可选值
  • front
  • back
  • encodingStringQHD视频清晰度,可选值
  • QHD
  • HD
  • FHD
  • audioOptions
    字段类型必填默认说明
    bitrateNumber20000音频码率
    dtxBooleantrue开启后将再静弱音场景下降低传输速率,减少带宽占用,适合语音聊天,不建议音乐相关对音频质量要求高的场景开启。
    noiseSuppressionBooleantrue噪声抑制
    echoCancellationBooleantrue回声消除
    autoGainControlBooleantrue自动增益
    highPassFilterBooleantrue高音过滤
    typingNoiseDetectionBooleantrue打字噪音检测
    视频清晰度
    视频清晰度分辨率FPS码率
    QVGA320x18015125kbps
    VGA640x36030400kbps
    QHD960x54030800kbps
    HD1280x720302500kbps
    FHD1920x1080304000kbps
    代码演示
    const YeIMCallKit = uni.requireNativePlugin('wz-YeIMCallKit');
    YeIMCallKit.startC2CVideoCall(
    {
    wsURL: 'wss://媒体服务器反代你的域名,如以上案例中的wss://livekit-server.xxxxxx.com:4431',
    token: '通过后端服务生成的Token。通话双方生成Token传入的用户ID不能一样,传入的房间号必须一样',
    userInfo: {
    nickname: '对方用户昵称',
    avatar: '对方头像URL',
    },
    },
    (e) => {
    console.log(e);
    },
    );

    一对一视频接听

    answerC2CVideoCall(options, callback) -> Void

    options

    参数同 startC2CVideoCall 接口

    代码演示
    const YeIMCallKit = uni.requireNativePlugin('wz-YeIMCallKit');
    YeIMCallKit.answerC2CVideoCall(
    {
    wsURL: 'wss://媒体服务器反代你的域名,如以上案例中的wss://livekit-server.xxxxxx.com:4431',
    token: '通过后端服务生成的Token,通话双方生成Token传入的用户ID不能一样,传入的房间号必须一样',
    userInfo: {
    nickname: '对方用户昵称',
    avatar: '对方头像URL',
    },
    },
    (e) => {
    console.log(e);
    },
    );

    一对一语音呼叫

    startC2CVoiceCall(options, callback) -> Void

    options
    字段类型必填默认说明
    wsURLString媒体服务器域名,必须使用 wss 协议
    tokenString用户凭证
    userInfoObject本人用户信息
    callerUserInfoObject对方用户信息
    audioOptionsObject可选音频参数
    callRingString呼叫铃声,支持本地和网络 URL,为空则不播放
  • 例如:1. /static/1.mp3
  • 例如:2. http://xxx.com/1.mp3
  • answerRingString接听铃声
    hungupRingString挂断铃声
    userInfo
    字段类型必填默认说明
    nicknameString用户昵称
    avatarString头像 URL
    identityString用户 ID 标志
    audioOptions
    字段类型必填默认说明
    bitrateNumber20000音频码率
    dtxBooleantrue开启后将再静弱音场景下降低传输速率,减少带宽占用,适合语音聊天,不建议音乐相关对音频质量要求高的场景开启。
    noiseSuppressionBooleantrue噪声抑制
    echoCancellationBooleantrue回声消除
    autoGainControlBooleantrue自动增益
    highPassFilterBooleantrue高音过滤
    typingNoiseDetectionBooleantrue打字噪音检测
    const YeIMCallKit = uni.requireNativePlugin('wz-YeIMCallKit');
    YeIMCallKit.startC2CVoiceCall(
    {
    wsURL: 'wss://媒体服务器反代你的域名,如以上案例中的wss://livekit-server.xxxxxx.com:4431',
    token:
    '通过LiveKit-Backend生成的Token,通话双方生成Token传入的用户ID不能一样,传入的房间号必须一样',
    userInfo: {
    nickname: '对方用户昵称',
    avatar: '对方头像URL',
    },
    },
    (e) => {
    console.log(e);
    },
    );

    一对一语音接听

    answerC2CVoiceCall(options, callback) -> Void

    options

    参数同 answerC2CVoiceCall 接口

    代码演示
    const YeIMCallKit = uni.requireNativePlugin('wz-YeIMCallKit');
    YeIMCallKit.answerC2CVoiceCall(
    {
    wsURL: 'wss://媒体服务器反代你的域名,如以上案例中的wss://livekit-server.xxxxxx.com:4431',
    token:
    '通过LiveKit-Backend生成的Token,通话双方生成Token传入的用户ID不能一样,传入的房间号必须一样',
    userInfo: {
    nickname: '对方用户昵称',
    avatar: '对方头像URL',
    },
    },
    (e) => {
    console.log(e);
    },
    );

    接口回调状态码

    状态码:Code描述
    10001服务端 URl 错误
    10002Token 错误
    10003连接错误,通用
    10004方法参数错误
    10005呼叫拒绝
    10006通话挂断,异常挂断。一般本地的网络连接异常断开,没网或者 1 分钟内多次重连无效会导致此情况,对方网络断开或者异常也会导致此情况
    10007无摄像头和麦克风权限
    20001双方对接完毕,开始通话
    20002通话挂断,手动挂断

    CallKit V2 多人通话 会议室 版本费用说明

    • 通话插件均包含双端:iOS + Android

    V1 版本包含 1v1 语音、视频通话。(插件市场 249 元版本:查看,直接购买即可,如果需要离线打包,需要单独再付 3000 元离线包费用,具体请联系开发者)


    V2.0 版本包括 1v1 语音、视频通话,多人语音视频通话,会议室。(价格 15000 元) V2.1 版本包括 1v1 语音、视频通话,多人语音视频通话,会议室,视频人像背景虚化+背景切换。(价格 23000 元)

    具体功能见下

    CallKit V2 版本(单独付费版,非当前版本)

    V2 版本新增了多人语音视频通话、会议室功能,需单独付费。

    V2 版本具体功能新增如下:

    • 优化 1v1 通话逻辑,新增支持切换视频通话小窗与大屏
    • 视频通话和多人语音视频通话支持开启背景虚化(v2.1)
    • 多人通话支持开启麦克风、摄像头
    • 多人通话支持通话过程中邀请其他人参与
    • 多人通话支持单独放大视频画面
    • 多人通话默认启用流量控制,即仅接收屏幕可见范围内视频流,减小服务器压力
    • 通话支持呼叫接听铃声和震动
    • 支持 JS 端调用关闭通话界面
    • 多人通话和会议室支持用户网络质量显示
    • 多人通话和会议室支持弱网流控、断线重连
    • 会议室支持普通模式和审核模式,审核模式下用户进入会议室需要主持人同意
    • 会议室支持屏幕共享
    • 会议室支持主持人、联席主持人模式
    • 会议室主持人支持单人静音、静画,全局静音、静画
    • 会议室支持举手功能
    • 会议室支持三屏显示,第一屏显示屏幕分享、第二屏显示发言人、第三屏显示参会者列表
    • 会议室支持视频背景虚化、人像背景切换(v2.1)
    • 未完待续.........

    CallKit V2 版本部分截图

    7232d7e9d871c3f6e78593fd1340c8ee.jpegc668334c95e349be96e35a446bf585de.jpeg9ff33f5a297d883ed346713390e4949d.jpeg7cc6c167750e41b971faf21cc770ba2e.jpeg04be7e24aec23ac7d75d08c48a84df8b.jpeg06677ef731249ad8b8a6fd590dcb1081.jpeg4adef55df88f1c288f80bceaa87edafe.jpeg29d2d77ecca52ce0b6d95da00bdbaeb9.jpegfbc9d74c29f2dff5287bf13819207cb9.jpeg984e470cd275fa25a2fa916755bf8efc.jpeg0cb72724c18565a586b704d20ef87b52.jpegdae92ef0ac41c5422396b8a99036af78.jpeg9f1793a333b423b7daf509a3af75d8a6.jpeg5f3eb885a621e296b56c0e5010bcab46.jpeg

    演示及注意事项

    请联系作者索取演示 App,因通话和会议室的开放性和部分政策原因,所以不提供公开演示 App.

    如需购买 V2 版本,请确认您的业务是完全正规合法的,否则不予提供任何服务.

    联系方式 | 定制开发

    QQ 号:2654166809

    微信号:Sentinel-110

    微信二维码: 8eb53b81a874fd11cdea2d22b0d0a173.jpeg

    作者只有这两个联系方式,其他联系方式均为诈骗,请勿采信

    特别注意

    项目禁止用于任何违法犯罪途径,一旦发现截图直接举报【公安部网络违法犯罪举报网站(http://cyberpolice.mps.gov.cn/wfjb/)】

    更新日志

    1.0.9 - 2024-01-29

    • 修复 Android 通话时间超过 2 小时网络异常断开的问题
    • 优化代码

    1.0.8 - 2023-12-29

    • 修复 Android 打开悬浮窗后进入其他 App 导致的通话中断
    • 修复 iOS 因网络异常或房间错误导致的无法退出通话

    1.0.7 - 2023-09-20

    • 修复 Android 语音通话啸叫

    1.0.6 - 2023-09-13

    • Android 修复因 1.0.5 版本引出的视频通话异常

    1.0.5 - 2023-09-03

    • Android 通话 SDK 版本升级至1.2.2
    • Android 修复网络状态异常下本地视频显示问题
    • Android iOS 语音通话扬声器设置默认开启
    • Android iOS 移除因对方网络状态异常导致的呼叫方挂断
    • iOS 修复悬浮窗异常

    1.0.4 - 2023-08-28

    • 修复安卓呼叫信息昵称显示异常

    1.0.3 - 2023-07-08

    • 新增悬浮窗,安卓支持全局、iOS 仅支持应用内
    • 新增呼叫、接听、挂断铃声配置
    • 修复部分华为机型前后置切换异常
    • 修复部分鸿蒙机型因解码问题导致的摄像头花屏、黑屏
    • 修复其他已知 BUG

    1.0.2 - 2023-06-06

    • 新增插件的视频、音频参数配置
    • 修复因服务端异常导致的打开页面闪退