FFmpeg+WebSocket+JsMpeg实时视频流实现方案

之前写的使用FFmpeg + Nginx + HLS流媒体播放方案,适合对实时性要求不高的需求,存在延迟,FFmpeg需要将视频流存储到本地文件,而本次方案FFmpeg不需要将视频流存储到本地文件,而是直接将转换后的视频流(如MJPEG格式)通过标准输出(stdout)传递给WebSocket服务器,WebSocket服务器再将数据实时推送到前端。这种方式是实时流传输,适合需要低延迟的场景。

以下是详细的实现逻辑:


1. FFmpeg 直接输出到 WebSocket 服务器

FFmpeg 通过命令行参数将 RTSP 流转换为 MJPEG 格式,并将输出直接发送到标准输出(stdout),而不是保存到文件。WebSocket 服务器通过 Node.js 的 child_process 模块捕获 FFmpeg 的输出,并将其转发给连接的客户端。

FFmpeg 命令
ffmpeg -i rtsp://your_rtsp_stream_url -f mjpeg -qscale:v 2 -
  • -i rtsp://your_rtsp_stream_url:输入 RTSP 流地址。
  • -f mjpeg:输出格式为 MJPEG。
  • -qscale:v 2:设置视频质量(值越小质量越高)。
  • -:将输出发送到标准输出(stdout),而不是文件。

2. WebSocket 服务器捕获 FFmpeg 输出

WebSocket 服务器通过 Node.js 启动 FFmpeg 进程,并监听其 stdout 数据流。每当 FFmpeg 输出一帧数据时,WebSocket 服务器就将这帧数据发送给所有连接的客户端。

WebSocket 服务器代码 (server.js)
const { spawn } = require('child_process');
const WebSocket = require('ws');

// 创建 WebSocket 服务器
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('Client connected');

    // 启动 FFmpeg 进程
    const ffmpeg = spawn('ffmpeg', [
        '-rtsp_transport', 'tcp', // 使用 TCP 传输 RTSP 流(如果 UDP 不稳定)
        '-i', 'rtsp://admin:password@192.168.1.60:554/Streaming/Channels/101/', // RTSP 流地址
        '-f', 'mpegts', // 输出格式为 MPEG-TS
        '-codec:v', 'mpeg1video', // 使用 MPEG-1 编码
        '-s', '640x360', // 分辨率
        '-b:v', '800k', // 视频比特率
        '-bf', '0', // 禁用 B 帧
        '-an', // 禁用音频
        'pipe:1' // 输出到标准输出
    ]);

    // 将 FFmpeg 的输出发送到 WebSocket 客户端
    ffmpeg.stdout.on('data', (data) => {
        if (ws.readyState === ws.OPEN) {
            ws.send(data); // 发送二进制数据
        }
    });

    // 处理 FFmpeg 的错误输出
    ffmpeg.stderr.on('data', (data) => {
        console.error(`FFmpeg error: ${data}`);
    });

    // 处理 FFmpeg 进程退出
    ffmpeg.on('close', (code) => {
        console.log(`FFmpeg process exited with code ${code}`);
    });

    // 客户端断开连接时关闭 FFmpeg 进程
    ws.on('close', () => {
        console.log('Client disconnected');
        ffmpeg.kill(); // 杀死 FFmpeg 进程
    });
});

console.log('WebSocket server is running on ws://localhost:8080');

3. 前端使用 JsMpeg 播放视频流

前端通过 JsMpeg 库连接到 WebSocket 服务器,并实时解码和播放 MJPEG 视频流。

前端代码 (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Video Streaming</title>
    <script src="https://cdn.jsdelivr.net/npm/jsmpeg/jsmpeg.min.js"></script>
</head>
<body>
    <canvas id="video-canvas"></canvas>
    <script>
        // 创建 JsMpeg 播放器
        const canvas = document.getElementById('video-canvas');
        const player = new JSMpeg.Player('ws://localhost:8080', {
            canvas: canvas
        });
    </script>
</body>
</html>

4. 运行流程

  1. FFmpeg

    • 从 RTSP 流中读取视频数据。
    • 将视频数据转换为 MJPEG 格式。
    • 将转换后的数据通过标准输出(stdout)发送。
  2. WebSocket 服务器

    • 启动 FFmpeg 进程并捕获其 stdout 数据。
    • 将捕获到的数据通过 WebSocket 发送给前端。
  3. 前端

    • 使用 JsMpeg 连接到 WebSocket 服务器。
    • 接收并解码 MJPEG 数据,实时显示在 <canvas> 中。

5. 优点

  • 实时性:视频流直接从 FFmpeg 推送到前端,延迟较低。
  • 无需存储:视频流不需要保存到本地文件,节省磁盘空间。
  • 简单易用:只需运行 FFmpeg 和 WebSocket 服务器即可。

6. 注意事项

  • FFmpeg 性能:如果 RTSP 流的分辨率较高,FFmpeg 的转换可能会占用较多 CPU 资源。可以通过调整 -qscale:v 参数来优化性能。
  • 网络带宽:MJPEG 格式的视频流数据量较大,确保网络带宽足够。
  • WebSocket 连接数:如果有多个客户端连接,WebSocket 服务器需要处理更多的数据转发,可能会增加服务器负载。

7. 总结

通过这种方式,FFmpeg 直接将 RTSP 流转换为 MJPEG 格式并输出到 WebSocket 服务器,WebSocket 服务器再将数据实时推送到前端,前端使用 JsMpeg 进行播放。整个过程无需存储视频文件,适合实时视频流传输的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/975392.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java方法学习

java 方法 在Java中&#xff0c;方法是类&#xff08;或对象&#xff09;的行为或功能的实现。&#xff08;一起实现一个功能&#xff09;java的方法类似于其他语言的函数&#xff0c;是一段用来完成特定功能的代码片段。 方法是解决一类问题步骤的有序结合。 方法包含于类或…

网络运维学习笔记 015网工初级(HCIA-Datacom与CCNA-EI)NAT网络地址转换

文章目录 NAT(Network Address Translation&#xff0c;网络地址转换)思科&#xff1a;1&#xff09;PAT2&#xff09;静态端口转换 华为&#xff1a;1&#xff09;EasyIP2&#xff09;NAT Server静态NAT&#xff1a;动态NAT&#xff1a;实验1&#xff1a;在R1上配置NAPT让内网…

强化学习的数学原理-六、随机近似与随机梯度下降

代码来自up主【强化学习的数学原理-作业】GridWorld示例代码&#xff08;已更新至DQN、REINFORCE、A2C&#xff09;_哔哩哔哩_bilibili SGD、GD、MGD举例&#xff1a; # 先初始化一个列表&#xff0c;未来要在这100个样本里面再sample出来 np.random.seed(0) X np.linspace(-…

问卷数据分析|SPSS实操之相关分析

皮尔逊还是斯皮尔曼的选取主要看数据的分布 当数据满足正态分布且具有线性关系时&#xff0c;用皮尔逊相关系数 当有一个不满住时&#xff0c;用斯皮尔曼相关系数 1. 选择分析--相关--双变量 2. 将Z1-Y2加入到变量中&#xff0c;选择皮尔逊 3. 此处为结果&#xff0c;可看我案…

jsherp importItemExcel接口存在SQL注入

一、漏洞简介 很多人说管伊佳ERP&#xff08;原名&#xff1a;华夏ERP&#xff0c;英文名&#xff1a;jshERP&#xff09;是目前人气领先的国产ERP系统虽然目前只有进销存财务生产的功能&#xff0c;但后面将会推出ERP的全部功能&#xff0c;有兴趣请帮点一下 二、漏洞影响 …

解决华硕主板的Boot界面无法设置M.2的系统启动盘问题

一、问题描述 当我们的华硕主板电脑开机后&#xff0c;发现电脑无法正常进入Windows系统界面&#xff0c;直接显示PXE网络网络信息&#xff1b;且知道我们进入到BIOS界面也无法找到选择系统盘&#xff0c;界面只显示【UEFI:PXE IP4 Intel(R) Ethernet】、【UEFI:PXE IP6 Intel(…

BuildFarm Worker 简要分析

更多BuildFarm/Bazel/Remote Execution API的文章见我的个人博客&#xff1a; Bazel 报错&#xff1a;/tmp/external/gcc_toolchain_x86_64_files/bin/x86_64-linux-gcc&#xff1a; No such file or directory 记录Bazel 编译 java 代码为独立运行的 jar 包的方法BuildFarm S…

docker修改镜像默认存储路径(基于页面迁移)

文章目录 1、停止服务2、拷贝镜像3、docker界面设置路径4、重新启动服务5、重启电脑 1、停止服务 桌面底部右键打开任务管理器 停止docker服务 2、拷贝镜像 从原目录拷贝到新的目录下&#xff0c;新的目录自己定&#xff0c;如果没有权限&#xff0c;需要先对原文件添加权限…

基于ffmpeg+openGL ES实现的视频编辑工具-opengl相关逻辑(五)

在我们的项目中,OpenGL ES 扮演着至关重要的角色,其主要功能是获取图像数据,经过一系列修饰后将处理结果展示到屏幕上,以此实现各种丰富多样的视觉效果。为了让大家更好地理解后续知识,本文将详细介绍 OpenGL 相关代码。需要注意的是,当前方案将对 OpenGL 的所有操作都集…

机器学习实战(7):聚类算法——发现数据中的隐藏模式

第7集&#xff1a;聚类算法——发现数据中的隐藏模式 在机器学习中&#xff0c;聚类&#xff08;Clustering&#xff09; 是一种无监督学习方法&#xff0c;用于发现数据中的隐藏模式或分组。与分类任务不同&#xff0c;聚类不需要标签&#xff0c;而是根据数据的相似性将其划…

七星棋牌顶级运营产品全开源修复版源码教程:6端支持,200+子游戏玩法,完整搭建指南(含代码解析)

棋牌游戏一直是移动端游戏市场中极具竞争力和受欢迎的品类&#xff0c;而七星棋牌源码修复版无疑是当前行业内不可多得的高质量棋牌项目之一。该项目支持 6大省区版本&#xff08;湖南、湖北、山西、江苏、贵州&#xff09;&#xff0c;拥有 200多种子游戏玩法&#xff0c;同时…

uniapp邪门事件

很久之前在这篇《THREEJS 在 uni-app 中使用&#xff08;微信小程序&#xff09;》&#xff1a;THREEJS 在 uni-app 中使用&#xff08;微信小程序&#xff09;_uni-app_帶刺的小葡萄-华为开发者空间 中学到了如何在uniapp的微信小程序里接入three.js的3d模型 由于小程序自身很…

【OS安装与使用】part6-ubuntu 22.04+CUDA 12.4运行MARL算法(多智能体强化学习)

文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明2.2 应用步骤2.2.1 下载源码并安装2.2.2 安装缺失的依赖项2.2.3 训练执行MAPPO算法实例 三、疑问四、总结 一、待解决问题 1.1 问题描述 已配置好基础的运行环境&#xff0c;尝试运行MARL算法。 1…

人工智能(AI)的不同维度分类

人工智能(AI)的分类 对机器学习进行分类的方式多种多样&#xff0c;可以根据算法的特性、学习方式、任务类型等不同维度进行分类这些分类都不是互斥的&#xff1a; 1、按数据模态不同:图像&#xff0c;文本&#xff0c;语音&#xff0c;多态等 2、按目标函数不同:判别式模型…

从零开始用react + tailwindcs + express + mongodb实现一个聊天程序(一)

项目包含5个模块 1.首页 (聊天主页) 2.注册 3.登录 4.个人资料 5.设置主题 一、配置开发环境 建立项目文件夹 mkdir chat-project cd chat-project mkdir server && mkdir webcd server npm init cd web npm create vitelatest 创建前端项目时我们选择javascrip…

【论文精读】VLM-AD:通过视觉-语言模型监督实现端到端自动驾驶

论文地址&#xff1a; VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision 摘要 人类驾驶员依赖常识推理来应对复杂多变的真实世界驾驶场景。现有的端到端&#xff08;E2E&#xff09;自动驾驶&#xff08;AD&#xff09;模型通常被优化以模仿…

基于Springboot学生宿舍水电信息管理系统【附源码】

基于Springboot学生宿舍水电信息管理系统 效果如下&#xff1a; 系统登陆页面 系统用户首页 用电信息页面 公告信息页面 管理员主页面 用水信息管理页面 公告信息页面 用户用电统计页面 研究背景 随着高校后勤管理信息化的不断推进&#xff0c;学生宿舍水电管理作为高校后勤…

POI pptx转图片

前言 ppt页面预览一直是个问题&#xff0c;office本身虽然有预览功能但是收费&#xff0c;一些开源的项目的预览又不太好用&#xff0c;例如开源的&#xff1a;kkfileview pptx转图片 1. 引入pom依赖 我这个项目比较老&#xff0c;使用版本较旧 <dependency><gro…

【JAVA】封装多线程实现

系列文章目录 java知识点 文章目录 系列文章目录&#x1f449;前言&#x1f449;一、封装的目标&#x1f449;二、常见的封装方式及原理&#x1f449;壁纸分享&#x1f449;总结 &#x1f449;前言 在 Java 中&#xff0c;封装多线程的原理主要围绕着将多线程相关的操作和逻辑…

nginx 反向代理 配置请求路由

nginx | 反向代理 | 配置请求路由 nginx简介 Nginx&#xff08;发音为“Engine-X”&#xff09;是一款高性能、开源的 Web 服务器和反向代理服务器&#xff0c;同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;于 2004…