首页
文章分类
逆向网安
中英演讲
杂类教程
学习笔记
前端开发
汇编
数据库
.NET
服务器
Python
Java
PHP
Git
算法
安卓开发
生活记录
读书笔记
作品发布
人体健康
网上邻居
留言板
欣赏小姐姐
关于我
Search
登录
1
利用AList搭建家庭个人影音库
4,655 阅读
2
浅尝Restful Fast Request插件,一句话完成 逆向过程
3,944 阅读
3
完美破解The Economist付费墙
2,714 阅读
4
i茅台app接口自动化csharp wpf实现,挂机windows服务器每日自动预约
2,607 阅读
5
青龙面板基本使用并添加修改微信/支付宝步数脚本
2,030 阅读
Search
标签搜索
PHP
Laravel
前端
csharp
安卓逆向
JavaScript
Python
Java
爬虫
抓包
Git
winform
android
Fiddler
Vue
selenium
LeetCode
每日一题
简单题
docker
Hygge
累计撰写
95
篇文章
累计收到
445
条评论
首页
栏目
逆向网安
中英演讲
杂类教程
学习笔记
前端开发
汇编
数据库
.NET
服务器
Python
Java
PHP
Git
算法
安卓开发
生活记录
读书笔记
作品发布
人体健康
页面
网上邻居
留言板
欣赏小姐姐
关于我
用户登录
搜索到
1
篇与
的结果
2023-07-13
解决RTSP推流前端切换视频导致播放黑屏频闪问题
解决RTSP推流前端切换视频导致播放黑屏频闪问题背景供应商那边设备类似于摄像头,推送的视频流格式是rtsp格式,需要进行转换到前端播放。实现效果是摄像头在前端页面展示类似实时视频直播,问题是一个页面有多个视频源,在多个源进行切换时会导致视频画面黑屏频闪。复现前提条件两个视频文件*.mp4nodejsffmpeg及配置环境变量客户端web页面1.依赖准备前端播放视频流需要导入jsmpeg-playerpackages.json... "dependencies": { "axios": "^1.4.0", "element-plus": "^2.3.5", "jsmpeg": "^1.0.0", "jsmpeg-player": "^3.0.3", "vue": "^3.2.47" }, ...App.vue<script setup> import { ref, watch, getCurrentInstance } from "vue"; import JsMpeg from "jsmpeg-player"; const ws = ref(null); const { proxy } = getCurrentInstance(); const videoObject = ref({}); // 用于存储当前正在播放的视频数据 /** * 视频的url构成规则为: rtsp://本机IP/自定义地址标识,后续将通过ffmpeg将对应视频转换为RTSP流,并通过TCP传输于该地址。 * 视频的port意义为: 不同的端口对应不同的视频,RTSP流通过TCP传输的地址前端不能直接对接,会将url发送给服务端,服务端进行接入后再于该端口进行ws推送。 */ const videoList = [ { label: "视频1-一人之下", name: "sp1", url: "rtsp://192.168.0.107/test", port: 8834, }, { label: "视频2-小猫咪", name: "sp2", url: "rtsp://192.168.0.107/test2", port: 8812, }, ]; // ... </script>2.页面准备重要:视频推流的展示是需要canvas标签,但是一个canvas标签多次复用就会导致黑屏频闪问题!!!所以将dom中的canvas标签移除,修改为每次点击按钮播放都动态创建一个canvas标签<template> <el-button v-for="item in videoList" :key="item.name" @click="playerVideo(item)" >{{ item.label }}</el-button > </template> <style scoped></style>3.播放实现const useWs = (data) => { // 建立一个新的ws视频流播放时先对旧的ws视频流进行释放 if (ws.value) ws.value.close(); // 移除所有canvas const canvasList = document.querySelectorAll("canvas"); canvasList.forEach((item) => { item.remove(); }); // 追加一个canvas#sp const sp = document.createElement("canvas"); sp.setAttribute("id", "sp"); document.body.appendChild(sp); // 与服务端建立ws通信,并未开始播放 ws.value = new WebSocket("ws://localhost:5001"); videoObject.value = data; }; // 向服务端发送信息是通过watch监听实现,当videoObject发生变化时调用,即当前视频对象切换 watch( () => videoObject.value, (newV, oldV) => { // 当ws连接打开时回调 ws.value.onopen = function () { // 向服务端发送欲播放的视频数据,服务端接收后会进行推流 ws.value.send(JSON.stringify(newV)); // 使用框架 建立ws视频流播放,不同的端口对应不同的视频。 new JsMpeg.Player(`ws://localhost:${newV.port}`, { canvas: document.getElementById('sp'), }); }; } ); const playerVideo = (e) => { useWs(e); };服务端node实现重要:ffmpeg环境变量的配置+运行目录放一个ffmpeg.exe1.依赖准备packages.json"dependencies": { "express": "^4.18.2", "node-ffmpeg-stream": "^1.1.0", "node-rtsp-stream": "^0.0.9", "node-rtsp-stream-jsmpeg": "^0.0.2", "ws": "^8.13.0" },index.jsconst Stream = require('node-ffmpeg-stream').Stream; const WebSocket = require('ws'); const ws = new WebSocket.Server({ port: 5001 }); const streams = new Map(); // 存储视频流的 Map2.端口推流ws.on('connection', (client) => { client.on('message', (msg) => { const data = JSON.parse(msg); console.log('开始播放'); // 下面固定格式 const stream = new Stream({ name: data.name, url: data.url, // eg: rtsp://192.168.0.107/test wsPort: data.port, // eg: 8834 options: { '-stats': '', // 没有必要值的选项使用空字符串 '-r': 30, // 具有必需值的选项指定键后面的值<br> } }); streams.set(data.name, stream); // 前端视频流切换时 + 页面刷新或关闭时触发,通知服务端停止推送当前流 client.on('close', () => { if (streams.has(data.name)) { const stream = streams.get(data.name); stream.stopStream(); streams.delete(data.name); console.log('连接已关闭'); } }); }); });ffmpeg转换流并进行传输这段代码使用 ffmpeg 工具来将本地的视频文件(test.mp4)转换为 RTSP 流,并将其通过 TCP 传输。让我逐行解释这段代码的含义:ffmpeg -stream_loop -1 -re -i "C:\Users\Administrator\Downloads\Video\test.mp4" -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://localhost/testffmpeg: 这是命令行中调用 ffmpeg 工具的命令。-stream_loop -1: 这个选项告诉 ffmpeg 无限循环输入文件。即使视频文件结束,它也会重新开始播放。-re: 这个选项告诉 ffmpeg 使用实时模式,以原始速度读取输入文件。在实时模式下,ffmpeg 将尽力按照视频的实际帧率发送流数据。-i "C:\Users\Administrator\Downloads\Video\test.mp4": 这是输入文件的路径。ffmpeg 将读取该文件作为输入。-rtsp_transport tcp: 这个选项指定了 RTSP 流的传输协议为 TCP。通过 TCP 传输可以提供更稳定的连接。-vcodec h264: 这个选项指定了视频编解码器为 H.264(AVC)。它将使用 H.264 编码视频流。-f rtsp: 这个选项指定了输出格式为 RTSP。rtsp://localhost/test: 这是输出的 RTSP 流的地址。ffmpeg 将流式传输的视频流发布到该地址。综上所述,这段代码的作用是使用 ffmpeg 将本地的视频文件转换为 RTSP 流,并通过 TCP 传输发布到 rtsp://localhost/test 地址上。这样其他支持 RTSP 协议的设备或应用程序就可以通过该地址来接收和播放该视频流输入命令如果卡着不动的话需要配合EasyDarwin流媒体服务,直接启动EasyDarwin后就可以了。EasyDarwinEasyDarwin 是一个开源的流媒体服务器软件,用于实现音视频流的传输和处理。它提供了一套完整的流媒体解决方案,包括流媒体推流、录制、转发、播放等功能。EasyDarwin 可以用于搭建自己的流媒体服务器,支持常见的音视频编码格式和传输协议,如 RTSP、RTMP、HLS 等。它具有跨平台的特性,可以在 Windows、Linux、macOS 等操作系统上运行。使用 EasyDarwin,您可以搭建一个可靠的流媒体服务器,从摄像头、音频设备或其他音视频源推送实时流,并将其传输到支持的客户端应用程序或播放器上进行播放。它也可以用于构建视频监控系统、直播平台、音视频会议等应用场景。EasyDarwin 的开源性质使得它具有灵活性和可定制性,您可以根据自己的需求进行定制和扩展。同时,它还提供了一些管理工具和 Web 控制台,方便用户进行配置和管理流媒体服务器。总的来说,EasyDarwin 是一个功能强大的开源流媒体服务器软件,可以帮助用户快速搭建自己的流媒体平台,并实现高质量的音视频流传输和处理。引用1.node-ffmpeg-stream:https://www.npmjs.com/package/node-ffmpeg-stream2.ffmpeg实现将视频文件转换成rtsp流:https://blog.csdn.net/weixin_44591652/article/details/123004247{cloud title="解决RTSP推流前端切换视频导致播放黑屏频闪问题.zip" type="bd" url="https://pan.baidu.com/s/1tQZu7ULVbBPLKF9w_EbTyw?pwd=pe4n" password="pe4n"/}
2023年07月13日
253 阅读
0 评论
0 点赞