uniapp微信小程序视频实时流+pc端预览方案
方案类型 | 技术实现 | 是否免费 | 优点 | 缺点 | 适用场景 | 延迟范围 | 开发复杂度 |
---|---|---|---|---|---|---|---|
WebSocket+图片帧 | 定时拍照+Base64传输 | ✅ 完全免费 | 无需服务器 纯前端实现 | 高延迟高流量 帧率极低 | 个人demo测试 超低频监控 | 500ms-2s | ⭐⭐ |
RTMP推流 | TRTC/即构SDK推流 | ❌ 付费方案 (部分有免费额度) | 专业直播方案 支持高并发 | 需流媒体服务器 SDK可能收费 | 中小型直播场景 | 1-3s | ⭐⭐⭐⭐ |
开源WebRTC | 自建coturn+mediasoup | ✅ 开源免费 | 超低延迟 完全可控 | 需自建信令服务器 维护成本高 | 技术团队内网项目 | 200-500ms | ⭐⭐⭐⭐⭐ |
商业WebRTC | 腾讯TRTC/声网Agora | ❌ 付费方案 (免费试用) | 企业级服务 全球节点 | 按流量/时长计费 绑定厂商 | 商业视频通话应用 | 200-800ms | ⭐⭐⭐⭐ |
HLS切片方案 | FFmpeg切片+nginx | ✅ 服务器可自建免费 | 兼容所有浏览器 支持CDN分发 | 延迟10秒以上 | 非实时录播场景 | 10s+ | ⭐⭐⭐ |
UDP自定义协议 | 开发原生插件 | ✅ 协议层免费 ❌ 人力成本高 | 完全自定义优化 | 需原生开发能力 过审风险 | 军工/工业特殊场景 | 200-500ms | ⭐⭐⭐⭐⭐⭐ |
免费方案选择建议:
-
完全零成本:
- WebSocket图片帧(仅适合原型验证)
- 开源WebRTC(需技术储备)
-
轻度付费:
- 腾讯云RTMP(免费10GB/月流量)
- 阿里云直播(免费20GB/月流量)
-
企业级推荐:
- 声网Agora(首月赠送1万分钟)
- 即构科技(首月免费)
下面我将介绍WebSocket+图片帧的实现方法:
WebSocket + 图片帧传输方案详解
该方案是 Uniapp微信小程序 + PC端视频实时预览 的一种 低成本、纯前端实现 的技术方案,适用于 低帧率、非严格实时 的场景。
🔹 方案原理
-
小程序端:
- 使用
<camera>
组件获取实时画面。 - 通过
uni.createCameraContext().takePhoto()
定时拍照(如300ms/次)。 - 将图片转为 Base64 格式,通过 WebSocket 发送到服务器。
- 使用
-
PC端:
- 建立 WebSocket 连接,接收 Base64 图片数据。
- 使用
<img>
或<canvas>
连续渲染图片,模拟视频流效果。
uniapp微信小程序端:
<template><view><camera :device-position="devicePosition" :flash="flash" @error="error" style="width:100%; height:300px;"></camera><button @click="startPushing">开始推流</button><button @click="stopPushing">停止推流</button><button @click="switchFlash">切换闪光灯</button><button @click="flipCamera">翻转摄像头</button><button style="font-size: 24rpx;">webscoket连接状态:{{pushState}}</button></view>
</template><script>
export default {data() {return {pushState: "未连接",devicePosition: 'front',flash: 'off',timer: null,ws: null}},methods: {flipCamera() {this.devicePosition = this.devicePosition === 'back' ? 'front' : 'back';},switchFlash() {this.flash = this.flash === 'off' ? 'torch' : 'off';},startPushing() {// 如果已连接,则不再重复连接if (this.pushState === '连接成功') return;const randomToken = new Date().getTime();const url = 'ws://192.168.1.34:7097/liveWebSocket?linkInfo=a-' + randomToken;this.ws = uni.connectSocket({url,success: () => {console.log('正在尝试连接WebSocket', url);}});this.ws.onOpen(() => {uni.showToast({ title: '连接成功' });this.pushState = '连接成功';this.startCapture();});this.ws.onError((err) => {uni.showToast({ title: '连接异常', icon: 'none' });this.pushState = '连接异常';this.stopPushing();});this.ws.onClose(() => {this.pushState = '已关闭';this.stopPushing();});},stopPushing() {if (this.timer) {clearInterval(this.timer);this.timer = null;}if (this.ws) {this.ws.close();this.ws = null;this.pushState = "未连接";}},startCapture() {const context = uni.createCameraContext(this);// 调整为300ms间隔,减轻设备压力this.timer = setInterval(() => {context.takePhoto({quality: 'low',success: (res) => {this.processAndSendImage(res.tempImagePath);},fail: (err) => {console.error('拍照失败:', err);}});}, 300);},processAndSendImage(tempImagePath) {uni.getFileSystemManager().readFile({filePath: tempImagePath,encoding: 'base64',success: (res) => {const base64Image = `data:image/jpeg;base64,${res.data}`;if (this.ws) {this.ws.send({data: base64Image,success: () => {console.log('图片发送成功');this.cleanTempFile(tempImagePath);},fail: (err) => {console.warn('图片发送失败:', err);}});}},fail: (err) => {console.warn('读取图片失败:', err);}});},cleanTempFile(filePath) {setTimeout(() => {uni.getFileSystemManager().removeSavedFile({filePath,success: () => {console.log('临时文件已删除');},fail: (err) => {console.warn('删除临时文件失败:', err);}});}, 2000);},error(e) {console.error('摄像头错误:', e);}},onUnload() {this.stopPushing();}
}
</script>
pc端预览:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>管理员监控页面</title><script src="./vue2.js"></script>
</head><body><div id="app"><button @click="toSend">开始请求</button><div v-if="videos && videos.length> 0" style="display: flex;"><div v-for="item in videos" :key="item.sessionId" style="margin: 10px;display: flex;flex-flow: column;":id="item.sessionId">状态:{{item.status}}<img :src="item.videoSrc" style="width: 200px; height: 200px; border: 1px solid red;" alt=""></div></div><div style="background-color: green;margin: 20px 0;display: flex;width: 50%;word-wrap: break-word">接口数据:<div v-html="datas"></div></div><div style="background-color: red;width: 50%">视频列表:<template v-if="videos && videos.length> 0"><p v-for="item2 in videos">{{item2}}</p></template></div></div><script>new Vue({el: '#app',data: {datas: "",videos: [// {// sessionId: '1',// status: '未连接',// videoSrc: '' //图片帧// }]},mounted() {},methods: {// 开始请求toSend() {//断开所有webscoket连接if (this.videos && this.videos.length > 0) {this.videos.forEach(item => {if (item.ws) {item.ws.close();}});}this.datas = "";this.videos = [];// 请求直播人员列表fetch('http://192.168.1.34:7097/liveWebStock/getAcceptList').then(response => response.json()).then(data => {if (data.code == 200) {// console.log(6666, data.data); this.datas = data.data;// 初始化每个视频流对象并建立 WebSocket this.videos = data.data.map(item => ({...item,status: '未连接',videoSrc: '',ws: null}));// 建立 WebSocket 连接this.videos.forEach(item => {this.initWebSocket(item.sessionId);});}}).catch(error => {console.error('请求直播人员列表失败:', error);});},initWebSocket(sessionId) {if (!sessionId) return;const wsUrl = `ws://192.168.1.34:7097/liveWebSocket?linkInfo=b-${sessionId}`;const index = this.videos.findIndex(v => v.sessionId === sessionId);if (index === -1) return;const ws = new WebSocket(wsUrl);ws.onopen = () => {this.$set(this.videos, index, {...this.videos[index],status: '已连接到服务器',ws});};// 处理接收到的数据ws.onmessage = (event) => {console.log("接收到base64图片", event);// 假设是 base64 数据const base64Data = event.data;const url = base64Data;this.$set(this.videos, index, {...this.videos[index],videoSrc: url});};ws.onerror = (error) => {this.$set(this.videos, index, {...this.videos[index],status: `WebSocket 错误: ${error.message}`});console.error(`WebSocket 错误 (${sessionId}):`, error);};ws.onclose = () => {this.$set(this.videos, index, {...this.videos[index],status: 'WebSocket 连接已关闭'});};}}});</script>
</body></html>
相关文章:

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...