• ffmpeg+flv视频推拉流实现(demo版)


    前言

    工作需要,记录一下前后端推拉流方案,基于HTTP-FLV协议,使用node + flv.js + ffmpeg进行前后端交互。
    此方案为demo版,目的是打通前后端链路,项目应用正在研究中。

    步骤

    1.安装ffmpeg

    后端推流需要借助ffmpeg流媒体服务器,需要在本机安装,安装方式参考如下:

    参考:https://zhuanlan.zhihu.com/p/324472015添加链接描述

    2.前端代码实现

    引入flv.js,更多用法参照官网

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body>
        <video id="videoElement"></video>
        <button id="btn">click</button>
        <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.min.js"></script>
        <script>
          const btn = document.getElementById("btn");
          btn.addEventListener("click", function () {
            if (flvjs.isSupported()) {
              var videoElement = document.getElementById("videoElement");
              var flvPlayer = flvjs.createPlayer({
                type: "flv",
                isLive: true,
                // 在线视频流,20230926亲测可用
                url: "ws://127.0.0.1:9999/rtsp/78910/?url=rtmp://ns8.indexforce.com/home/mystream",
              });
              flvPlayer.attachMediaElement(videoElement);
              flvPlayer.load();
              flvPlayer.play();
            }
          });
        </script>
      </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3.后端代码实现

    后端项目自行构建,这里只提供js文件代码;
    借助了express,websocket,ffmpeg组件,需要自行安装;
    整体逻辑:建立前后端socket链接–》获取页面传过来的视频流–》调用ffmpeg解析并推流

    var express = require("express");
    var expressWebSocket = require("express-ws");
    var ffmpeg = require("fluent-ffmpeg");
    ffmpeg.setFfmpegPath("ffmpeg");
    var webSocketStream = require("websocket-stream/stream");
    var WebSocket = require("websocket-stream");
    var http = require("http");
    
    // config
    let rtspServerPort = 9999;
    
    function localServer() {
      let app = express();
      app.use(express.static(__dirname));
      expressWebSocket(app, null, {
        perMessageDeflate: true,
      });
      app.ws("/rtsp/:id/", rtspRequestHandle);
      app.listen(rtspServerPort);
      console.log("express listened on port : " + rtspServerPort);
    }
    
    function rtspRequestHandle(ws, req) {
      console.log("rtsp request handle");
      const stream = webSocketStream(
        ws,
        {
          binary: true,
          browserBufferTimeout: 1000000,
        },
        {
          browserBufferTimeout: 1000000,
        }
      );
      let url = req.query.url;
      console.log("rtsp url:", url);
      console.log("rtsp params:", req.params);
      try {
        ffmpeg(url)
          // .addInputOption("-rtsp_transport", "tcp", "-buffer_size", "102400") // 这里可以添加一些 RTSP 优化的参数
          .on("start", function () {
            console.log(url, "Stream started.");
          })
          .on("codecData", function () {
            console.log(url, "Stream codecData.");
            // 摄像机在线处理
          })
          .on("error", function (err) {
            console.log(url, "An error occured: ", err.message);
          })
          .on("end", function () {
            console.log(url, "Stream end!");
            // 摄像机断线的处理
          })
          .outputFormat("flv")
          .videoCodec("copy")
          .noAudio()
          .pipe(stream);
      } catch (error) {
        console.log(error);
      }
    }
    
    localServer();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    4.结果

    点击按钮后加载视频

    在这里插入图片描述

  • 相关阅读:
    实现单点登录的方式
    Docker OCI runtime create failed
    【计算机网络系列】物理层②:信道复用技术(频分复用、时分复用、波分复用及码分复用)
    解决第三方模块ts声明文件编译错误问题
    检查 Oracle 版本的 7 种方法
    微信实现消息自动回复、群发等功能,还可限时免费使用!
    idea启动非maven javaWeb项目,idea打包非maven javaWeb项目
    软件工程师,全面思考问题很重要
    得帆信息携手深信服,联合打造高安全PaaS超融合一体化解决方案
    【0基础学Java第七课】-- 类和对象02
  • 原文地址:https://blog.csdn.net/qq_42825643/article/details/133296858