linux 运行开源音视频livekit,实现html视频语音聊天。

打印 上一主题 下一主题

主题 571|帖子 571|积分 1713

linux版本:
centos 7.9
先附上官方当地安装文档:
Running LiveKit locally | LiveKit Docs
步调:
1、首先在linux内里安装运行livekit:
  1. 1.任意目录创建文件livekit,cd到livkit目录,然后在livekit目录下运行下面的命令。
  2. 2.安装服务
  3. curl -sSL https://get.livekit.io | bash
  4. 3.先测试运行,8.218.***.**替换成你的ip,是云服务器就替换成公网IP,局域网就用局域网ip
  5. livekit-server --dev --node-ip=8.218.***.** --bind 0.0.0.0
  6. 结束运行按键盘:ctrl+c
  7. 4.带配置文件运行
  8. 可以直接根据配置文件运行
  9. livekit-server --config ./livekit.yaml --node-ip=8.218.***.** --bind 0.0.0.0
  10. 结束运行按键盘:ctrl+c
  11. 5.后台运行,在livekit目录创建run.sh文件,然后运行命令
  12. sh run.sh
复制代码
livekit.yaml文件的内容:
  1. port: 7880
  2. rtc:
  3.     udp_port: 7882
  4.     tcp_port: 7881
  5.     use_external_ip: true
  6.     enable_loopback_candidate: false
  7. keys:
  8.     APIbxDWetqcjHaa: RlZfytYLmdMOgV2u6fSFAbMhrYQok9B4aVWq48eIE1aa
  9. logging:
  10.     json: false
  11.     level: info
复制代码
留意use_external_ip一定要设置true.这个是启用外部ip访问的。
然后就是keys:这个是创建token需要的,
前面的APIbxDWetqcjHaa是apikey,
后面的RlZfytYLmdMOgV2u6fSFAbMhrYQok9B4aVWq48eIE1aa是secret。
再附上run.sh,这个是后台运行的:
  1. #!/bin/sh
  2. nohup livekit-server --config ./livekit.yaml > log.log 2>&1 &
复制代码
测试是否运行成功。欣赏器输入http://8.218.***.**:7880/,表现ok及代表运行成功。

2、创建token。
token是客户端访问livekit服务器所需要的凭证,内里包含了房间名称和用户id等信息。
我是用java创建token,还有其他方式创建token的办法,详见官方文档。
Authentication | LiveKit Docs
java创建token的方法:
首先导入maven包:
  1.         <dependency>
  2.             <groupId>io.livekit</groupId>
  3.             <artifactId>livekit-server</artifactId>
  4.             <version>0.5.9</version>
  5.         </dependency>
复制代码
然后随便创建一个main方法:
  1. package com.example.demo1;
  2. import io.livekit.server.*;
  3. import java.util.ArrayList;
  4. import java.util.Date;
  5. import java.util.List;
  6. public class LiveKitTest {
  7.     public static void main(String[] args) {
  8.         System.out.println(createToken(100));
  9.         System.out.println(createToken(101));
  10.         System.out.println(createToken(102));
  11.         System.out.println(createToken(103));
  12. //        System.out.println(createToken(96));
  13. //        System.out.println(createToken(98));
  14.     }
  15.     public static String createToken(int num) {
  16. //        用户ID
  17.         int userID = 10000+num;
  18. //        用户名称
  19.         String name = "用户"+num;
  20.         String roomName = "测试房间2";
  21.         String apiKey = "APIbxDWetqcjHaa";
  22.         String apiSecret = "RlZfytYLmdMOgV2u6fSFAbMhrYQok9B4aVWq48eIE1aa";
  23.         AccessToken token = new AccessToken(apiKey, apiSecret);
  24.         token.setName(name);
  25.         token.setIdentity(userID+"");
  26.         token.setMetadata("metadata");
  27. //        令牌的过期时间(可能)
  28.         token.setExpiration(new Date(System.currentTimeMillis()+ 1000L *60*60*24*365));
  29. //        token所拥有的权限
  30.         List<String> list = new ArrayList<>();
  31. //        摄像头
  32.         list.add("camera");
  33. //        麦克风
  34.         list.add("microphone");
  35. //        list.add("screen_share"); //屏幕共享
  36. //        list.add("screen_share_audio"); //屏幕共享音频
  37. //        允许参与者发布相机,但不允许其他来源
  38.         CanPublishSources canPublishSources = new CanPublishSources(list);
  39. //        配置解释:https://docs.livekit.io/realtime/concepts/authentication/
  40. //        RoomJoin:加入房间许可   Room:房间名称
  41.         token.addGrants(new RoomJoin(true), new Room(roomName),canPublishSources);
  42.         return token.toJwt();
  43.     }
  44. }
复制代码
这内里的apikey和apisecret就是livekit.yam文件内里的。
运行main方法即可得出类似如许的token:
  1. eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMDEwMCIsIm1ldGFkYXRhIjoibWV0YWRhdGEiLCJpc3MiOiJBUElieERXZXRxY2pIM2siLCJuYW1lIjoi55So5oi3MTAwIiwidmlkZW8iOnsicm9vbUpvaW4iOnRydWUsInJvb20iOiLmtYvor5XmiL_pl7QyIiwiY2FuUHVibGlzaFNvdXJjZXMiOlsiY2FtZXJhIiwibWljcm9waG9uZSJdfSwiZXhwIjoxNzQxOTQzOTc1LCJqdGkiOiIxMDEwMCJ9.lkjLjZb6qv96DxTxIUpLLUJSVdILaNi7_IeqZzLDbhA
复制代码
如许token就创建成功了。
3.测试运行
我这里利用的是html+js测试的。
其他客户端运行方式可以看官方文档:
Client Quickstarts | LiveKit Docs
这里附上html源码:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>LiveKit Example</title>
  7. </head>
  8. <body>
  9. <div id="videoTestDiv"></div>
  10. <div id="videoDiv" style="width: 80%"></div>
  11. <input type="text" id="tokenInput" value=""/>
  12. <br/>
  13. <button onclick="user1Fun()" style="margin: 10px;">用户90</button>
  14. <button onclick="user2Fun()" style="margin: 10px;">用户92</button>
  15. <button onclick="user3Fun()" style="margin: 10px;">用户96</button>
  16. <button onclick="user4Fun()" style="margin: 10px;">用户98</button>
  17. <br/>
  18. <button onclick="connect()" style="margin: 10px;">视频链接</button>
  19. <button onclick="connect()" style="margin: 10px;">语音链接</button>
  20. <button onclick="ext()" style="margin: 10px;">登出</button>
  21. <button onclick="openVideo()" style="margin: 10px;">打开摄像头</button>
  22. <script src="livekit-client.umd.min.js"></script>
  23. <script src="eruda.js"></script>
  24. <script>
  25.     // 手机上的调试插件
  26.     eruda.init();
  27.     const tokenInput = document.getElementById("tokenInput");
  28.     // 获取页面的高度和宽度
  29.     let pageHeight = document.documentElement.clientHeight;
  30.     let pageWidth = document.documentElement.clientWidth;
  31.     user1Fun();
  32.     // 检查是否支持webrtc和是否存在麦克风和摄像头
  33.     // 如果手机上访问必须是https,不是则调用不了麦克风和摄像头
  34.     // checkVideo();
  35.     // const wsURL = "wss://gscs.yuming.com:7443"
  36.     const wsURL = "ws://8.218.***.**:7880"
  37.     const room = new LivekitClient.Room({
  38.         // 自动管理订阅的视频质量
  39.         adaptiveStream: true,
  40.         // 优化已发布曲目的发布带宽和CPU
  41.         dynacast: true,
  42.         // 默认捕获设置
  43.         videoCaptureDefaults: {
  44.             resolution: LivekitClient.VideoPresets.h720.resolution,
  45.         },
  46.     });
  47.     // 链接livekit
  48.     async function connect() {
  49.         let token = tokenInput.value;
  50.         console.log(token);
  51.         console.log(wsURL);
  52.         if (token == "") {
  53.             alert("请输入token");
  54.             return;
  55.         }
  56.         // 预热连接,这可以在页面加载后立即调用
  57.         // room.prepareConnection(wsURL, token);
  58.         // 设置事件侦听器
  59.         allHandle();
  60.         // 链接
  61.         await room.connect(wsURL, token);
  62.         console.log('链接成功', room.roomInfo);
  63.         alert('链接成功');
  64.         // 发布本地相机和麦克风曲目 下面可以单独开麦克风和相机
  65.         // await room.localParticipant.enableCameraAndMicrophone();
  66.         const p = room.localParticipant;
  67.         // 打开本地用户的相机和麦克风,这可能会触发浏览器提示
  68.         // 以确保授予权限
  69.         await p.setCameraEnabled(true);
  70.         await p.setMicrophoneEnabled(true);
  71.         // 开始共享用户的屏幕,这将触发浏览器提示选择
  72.         // 要共享的屏幕。
  73.         // await p.setScreenShareEnabled(true);
  74.     }
  75.     // 所有监听事件
  76.     function allHandle() {
  77.         // 房间有人加入事件
  78.         room.on(LivekitClient.RoomEvent.ParticipantConnected, function () {
  79.             console.log("一个远程参与者 在本地参与者之后加入。");
  80.         })
  81.         room.on(LivekitClient.RoomEvent.ParticipantDisconnected, function () {
  82.             console.log("远程参与者离开");
  83.         })
  84.         room.on(LivekitClient.RoomEvent.Reconnecting, function () {
  85.             console.log("与服务器的连接已中断,它正在尝试重新连接。");
  86.         })
  87.         room.on(LivekitClient.RoomEvent.Reconnected, function () {
  88.             console.log("重新连接已成功");
  89.         })
  90.         room.on(LivekitClient.RoomEvent.Disconnected, function () {
  91.             console.log("由于房间关闭或无法恢复的故障而与房间断开连接");
  92.         })
  93.         room.on(LivekitClient.RoomEvent.TrackPublished, function () {
  94.             console.log("本地参与者加入后,新曲目将发布到房间");
  95.         })
  96.         room.on(LivekitClient.RoomEvent.TrackUnpublished, function () {
  97.             console.log("远程参与者已取消发布轨道");
  98.         })
  99.         room.on(LivekitClient.RoomEvent.TrackMuted, function () {
  100.             console.log("轨道被静音,本地轨道和远程轨道都会触发");
  101.         })
  102.         room.on(LivekitClient.RoomEvent.TrackUnmuted, function () {
  103.             console.log("轨道未静音,本地轨道和远程轨道都会触发");
  104.         })
  105.         room.on(LivekitClient.RoomEvent.LocalTrackPublished, function () {
  106.             console.log("本地曲目已成功发布");
  107.         })
  108.         room.on(LivekitClient.RoomEvent.LocalTrackUnpublished, function (track, publication, participant) {
  109.             console.log("本地曲目未发布");
  110.             publication.track.detach();
  111.         })
  112.         room.on(LivekitClient.RoomEvent.ActiveSpeakersChanged, function () {
  113.             console.log("当前活动的发言人已更改");
  114.         })
  115.         room.on(LivekitClient.RoomEvent.IsSpeakingChanged, function () {
  116.             console.log("当前参与者已更改发言状态");
  117.         })
  118.         // 参与者的连接质量已更改
  119.         room.on(LivekitClient.RoomEvent.ConnectionQualityChanged, function () {
  120.             console.log("参与者的连接质量已更改");
  121.         })
  122.         room.on(LivekitClient.RoomEvent.ParticipantMetadataChanged, function () {
  123.             console.log("通过服务器API更新了参与者的元数据");
  124.         })
  125.         room.on(LivekitClient.RoomEvent.RoomMetadataChanged, function () {
  126.             console.log("与房间相关联的元数据已更改");
  127.         })
  128.         room.on(LivekitClient.RoomEvent.DataReceived, function () {
  129.             console.log("从另一个参与者或服务器接收的数据");
  130.         })
  131.         // 指示订阅的曲目是否因带宽而暂停
  132.         room.on(LivekitClient.RoomEvent.TrackStreamStateChanged, function () {
  133.             console.log("指示订阅的曲目是否因带宽原因而暂停");
  134.         })
  135.         room.on(LivekitClient.RoomEvent.TrackSubscriptionPermissionChanged, function () {
  136.             console.log("订阅的曲目之一已更改当前参与者的曲目级别权限");
  137.         })
  138.         room.on(LivekitClient.RoomEvent.ParticipantPermissionsChanged, function () {
  139.             console.log("当前参与者的权限更改时");
  140.         })
  141.         // 有新成员加入是会访问这个方法
  142.         room.on(LivekitClient.RoomEvent.TrackSubscribed, handleTrackSubscribed)
  143.         // 曲目取消订阅
  144.         room.on(LivekitClient.RoomEvent.TrackUnsubscribed, function (track, publication, participant) {
  145.             track.detach();
  146.             let videoDiv = document.getElementById("videoDiv");
  147.             videoDiv.innerHTML="";
  148.             console.log("有人退出了房间!")
  149.         })
  150.     }
  151.     // 从服务器接收曲目始于订阅。有新成员加入是会访问这个方法
  152.     function handleTrackSubscribed(track, publication, participant) {
  153.         console.log("有人加入了房间!")
  154.         // 将音轨附加到新的HTMLVideoElement或HTMLAudioElement
  155.         const element = track.attach();
  156.         let videoDiv = document.getElementById("videoDiv");
  157.         videoDiv.appendChild(element);
  158.         let video = videoDiv.querySelector("video");
  159.         if (video) {
  160.             video.style.width = pageWidth + "px";
  161.             video.style.height = (pageHeight - 200) + "px";
  162.         }
  163.         // 或附加到现有元素
  164.         // track.attach(element)
  165.     }
  166.     // 退出登录
  167.     function ext() {
  168.         room.disconnect();
  169.     }
  170.     function user1Fun() {
  171.         // 我是90
  172.         tokenInput.value = ""
  173.     }
  174.     function user2Fun() {
  175.         // 我是92
  176.         tokenInput.value = ""
  177.     }
  178.     function user3Fun() {
  179.         // 我是96
  180.         tokenInput.value = ""
  181.     }
  182.     function user4Fun() {
  183.         // 我是98
  184.         tokenInput.value = ""
  185.     }
  186.     // 打开摄像头
  187.     function openVideo() {
  188.         let videoTestDiv = document.getElementById("videoTestDiv");
  189.         // 创建一个新的 video 元素
  190.         const videoElement = document.createElement('video');
  191.         videoElement.style.width = pageWidth + "px";
  192.         videoElement.style.height = (pageHeight - 200) + "px";
  193.         videoElement.setAttribute('playsinline', '');
  194.         videoElement.setAttribute('autoPlay', '');
  195.         videoTestDiv.appendChild(videoElement);
  196.         navigator.mediaDevices.getUserMedia({video: true, audio: true}).then(function (stream) {
  197.             console.log(stream);
  198.             videoElement.srcObject = stream;
  199.             // videoTest.src = window.webkitURL.createObjectURL(stream);
  200.         });
  201.     }
  202.     /**
  203.      * 检查摄像头和麦克风是否可用
  204.      */
  205.     function checkVideo() {
  206.         // 检查是否支持 getUserMedia 方法
  207.         if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  208.             // 请求访问摄像头和麦克风
  209.             navigator.mediaDevices.getUserMedia({video: true, audio: true})
  210.                 .then(function (stream) {
  211.                     // 摄像头和麦克风设备可用
  212.                     console.log('摄像头和麦克风可用');
  213.                 })
  214.                 .catch(function (error) {
  215.                     // 摄像头和麦克风设备不可用
  216.                     console.error('摄像头或麦克风不可用', error);
  217.                 });
  218.         } else {
  219.             alert('浏览器不支持webRtc');
  220.         }
  221.     }
  222. </script>
  223. </body>
  224. </html>
复制代码
js的官方地点:
https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js
我把官方地点复制下来当地利用的。
还有就是eruda.js,这个是可以在手机欣赏器上调试的插件,我是下载下来当地利用的,
网上地点:https://cdn.jsdelivr.net/npm/eruda
这里的html需要修改wsURL的地点,也就是把ws://8.218.***.**:7880这个替换成你liveKit的IP,
利用默认端口7880。
然后就是输入你创建的token即可链接livekit了。
假如利用的是ws+ip访问的,只能测试能不能链接成功,不能利用利用视频大概语音。
由于利用视频和语音需要调用麦克风和摄像头,调用摄像头这些则需要域名+SSL证书。
配置成wss的地点。也就是类似如许:wss://gscs.baidu.cn:7443。
申请SSL证书我是在腾讯云申请的,有域名就可以免费申请。
申请后我是用用nginx摆设的证书,具体摆设的方法这里就不具体说明白。
附上部分:
  1. server {
  2.         listen 7443 ssl; #监听的端口
  3.         server_name gscs.****.fun;
  4.         root html;
  5.         index index.html index.htm;
  6.         ssl_certificate cert/gscs.****.fun_bundle.pem;
  7.         ssl_certificate_key cert/gscs.****.fun.key;
  8.         #ssl会话超时时间
  9.         ssl_session_timeout 5m;
  10.         ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  11.         ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  12.         ssl_prefer_server_ciphers on;
  13.         location / {
  14.             proxy_pass http://8.218.***.**:7880;
  15.             proxy_set_header Host $host:$server_port;
  16.             proxy_http_version 1.1;
  17.             proxy_set_header Upgrade $http_upgrade;
  18.             proxy_set_header Connection "upgrade";
  19.             proxy_set_header X-real-ip $remote_addr;
  20.             proxy_set_header X-Forwarded-For $remote_addr;
  21.         }
  22.     }
复制代码
我这里是单独用7443这个端口作为证书的端口,由于其他地方已经用了443端口了,你也可以利用443,如许访问的时候就不需要单独加上端口。
摆设好证书后访问https://gscs.****.fun:7443/,表现ok则代表SSL配置成功。
然后把html内里的wsURL替换成“wss://gscs.****.fun:7443”,即可访问摄像头和语音聊天。
最后附上链接后的网页:

最后假如碰到不能利用摄像头和麦克风的问题:
1、SSL证书的问题,必须利用wss+域名访问liveKit
2、欣赏器不支持webRtc,html源码有个checkVideo方法可以验证。不支持就换个欣赏器,我测试时就碰到小米欣赏器不支持webRtc。


假如有什么问题,欢迎大佬指正。
 最后假如对你有一点点帮助,麻烦支持一下。
全国寄快递5元起,影戏票8.8折。更多优惠微信关注公众号:【折价寄件】
感谢阅读!!!!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

傲渊山岳

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表