当前位置: 首页 > news >正文

【Flutter】使用LiveKit和Flutter构建实时视频聊天应用

引言

在当今快速发展的数字世界中,实时视频通信已成为许多应用程序的核心功能。无论是远程工作、在线教育还是社交网络,高质量的实时视频功能都至关重要。LiveKit作为一个开源的WebRTC解决方案,提供了构建可扩展实时音视频应用所需的一切工具。结合Flutter的跨平台能力,我们可以轻松创建出色的视频聊天体验。

本文将带你了解如何使用LiveKit Server和LiveKit Flutter SDK构建一个实时视频聊天应用。

准备工作

  1. 设置LiveKit Server
    首先,我们需要设置LiveKit服务器,这里直接用网上下载的https://github.com/livekit/livekit。
    本地启动
    请使用cmd运行
c:\Users\用户名\Documents\GithubProjects\livekit\livekit-server.exe --dev --bind 0.0.0.0

默认key是apikey,密码是secert。
记住你的API_KEY和API_SECRET,稍后客户端连接时会用到。
2. 创建Flutter项目
创建一个新的Flutter项目:

flutter create livekit_flutter_demo
cd livekit_flutter_demo

集成LiveKit Flutter SDK

  1. 添加依赖
    在pubspec.yaml中添加LiveKit Flutter SDK:
dependencies:# LiveKit SDK用于实时音频/视频通信livekit_client: ^2.3.6livekit_components: ^1.1.1# 权限处理插件permission_handler: ^11.3.0crypto: ^3.0.6

然后运行:

flutter pub get
  1. 配置权限
    对于Android,在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

对于iOS,在Info.plist中添加:

<key>NSCameraUsageDescription</key>
<string>需要摄像头权限来进行视频通话</string>
<key>NSMicrophoneUsageDescription</key>
<string>需要麦克风权限来进行语音通话</string>

构建视频聊天界面

  1. 初始化LiveKit客户端
 Future<Result<Room>> connectToRoom(String url, String token) async {final room = Room(roomOptions: RoomOptions(adaptiveStream: true));try {await room.prepareConnection(url, token);await room.connect(url, token);state = room;return Result.success(room);} catch (e) {state = null;return Result.failure(e);}}

2.生成token
token本应是服务器给,但是有时需要客户端生成,jwt形式。

auth_service.dart
import 'dart:convert';import 'package:crypto/crypto.dart';class AuthService {/// 生成视频通话的JWT令牌////// [roomName] - 房间名称/// [identity] - 用户标识/// [expiresIn] - 令牌有效期,可选值:///   - 1小时 (1h)///   - 6小时 (6h)///   - 24小时 (24h)///   - 168小时 (7天)///   - 720小时 (30天)///   - 8760小时 (1年)/// [key] - API密钥/// [secret] - API密钥对应的密钥static String generateVideoToken(String roomName, String identity,Duration expiresIn, String key, String secret) {final now = DateTime.now().toUtc();final nbf = now.millisecondsSinceEpoch ~/ 1000;final exp = now.add(expiresIn).millisecondsSinceEpoch ~/ 1000;final header = {'alg': 'HS256', 'typ': 'JWT'};final videoGrants = {'room': roomName,'roomJoin': true,'canPublish': true,'canSubscribe': true,};final claims = {'iss': key,'nbf': nbf,'exp': exp,'sub': identity,'video': videoGrants,};String base64UrlEncodeNoPadding(String str) =>base64Url.encode(utf8.encode(str)).replaceAll('=', '');final encodedHeader = base64UrlEncodeNoPadding(json.encode(header));final encodedPayload = base64UrlEncodeNoPadding(json.encode(claims));final message = '$encodedHeader.$encodedPayload';final hmac = Hmac(sha256, utf8.encode(secret));final digest = hmac.convert(utf8.encode(message));final signature = base64Url.encode(digest.bytes).replaceAll('=', '');return '$encodedHeader.$encodedPayload.$signature';}
}

一切配置到这,你就可以进入房间了。
3.启用麦克风和相机

 await room.localParticipant?.setMicrophoneEnabled(true);await room.localParticipant?.setCameraEnabled(true);

4.视频推流

// 创建摄像头轨道final options = CameraCaptureOptions(cameraPosition: _isFrontCamera ? CameraPosition.front : CameraPosition.back,params: const VideoParameters(dimensions: VideoDimensions(640, 480)),final cameraTrack = await LocalVideoTrack.createCameraTrack(options);await localParticipant.publishVideoTrack(cameraTrack);

停止推流

// 停止推流try {for (final pub in localParticipant.videoTrackPublications) {if (pub.source == TrackSource.camera) {await localParticipant.unpublishAllTracks();}}} catch (e) {debugPrint('停止推流失败: $e');}

预览

VideoTrackRenderer(videoTrack,fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,)

查找房间人数

int getParticipantCount() {// 本地参与者(自己) + 远程参与者数量return 1 + room.remoteParticipants.length;
}
http://www.xdnf.cn/news/44191.html

相关文章:

  • Linux操作系统--进程的创建和终止
  • java面试篇(常见的集合底层原理)
  • 中国占全球工业机器人装机量的52%,国产机器人崛起加速洗牌,拆分机器人业务独立上市,软硬件协同增强,AI工业机械臂催生业务再增长
  • Opencv图像处理:轮廓检测、轮廓近似、绘制外接圆外接矩形
  • Linux学习——TCP
  • Viper配置管理笔记
  • 基于springboot+vue的仓库管理系统
  • AI日报 - 2025年04月19日
  • 《Operating System Concepts》阅读笔记:p748-p748
  • C# 类型、存储和变量(用户定义类型)
  • python pdf转图片再OCR
  • WebSocket启用备忘
  • 【C++】类和对象之日期类的实现(构造、运算符重载)
  • Deepseek输出的内容如何直接转化为word文件?
  • PFLM: Privacy-preserving federated learning with membership proof证明阅读
  • mysql中的group by用法详解
  • 大模型安全吗?数据泄露与AI伦理的黑暗面!
  • 【数据结构_12】二叉树(4)
  • redis 中的 String 数据结构
  • 【Linux系统】Linux基础指令(详解Linux命令行常用指令,每一个指令都有示例演示)
  • 【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的
  • 【人工智能】推荐开源企业级OCR大模型InternVL3
  • 【后端开发】MyBatis
  • 树莓派系统中设置固定 IP
  • Oracle 23ai Vector Search 系列之6 向量相似性搜索(Similarity Search)
  • 力扣DAY60-61 | 热100 | 回溯:单词搜索、分割回文串
  • 17.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--SonarQube部署与配置
  • kotlin知识体系(六) : Flow核心概念与与操作符指南
  • opencv图像库编程
  • 软件开发过程中技术债的控制策略