关于 RTSP 用 FFMPEG 转 flv 播放延迟问题

2020-07-21 22:58:06 +08:00
 yangheng4922

最近在用 Electron 开发一个客户端 需要集成监控摄像头

摄像头是海康的网络摄像头 通过 RTSP 协议获取到推流视频

通过在 node 主进程创建一个服务 通过 websocket 接受 rtsp 连接

在通过 ffmpeg 转码通过 stream 推到渲染进程

渲染进程通过 flv.js 播放视频

通过转码可以实现 web 页面播放 rtsp 的视频流

但是会有 5~6 秒的延迟 体验很不好

而且 客户端集成 ffmpeg 体积太大了

想了解下 关于 rtsp 转码的方法还有那些 在 node 端可以实现的

主进程创建的 web 服务

import * as express from 'express'
import * as expressWebSocket from 'express-ws'
import ffmpeg from 'fluent-ffmpeg'
import webSocketStream from 'websocket-stream/stream'
const path = require('path')

let ffmpegPath
if (process.env.NODE_ENV === 'development') {
  ffmpegPath = path.join(__static, 'ffmpeg', 'bin', 'ffmpeg.exe')
} else {
  ffmpegPath = path.join(process.cwd(), 'ffmpeg', 'bin', 'ffmpeg.exe')
}
ffmpeg.setFfmpegPath(ffmpegPath)

// 启动视频转码服务服务
function videoServer () {
  let app = express()
  app.use(express.static(__dirname))
  expressWebSocket(app, null, {
    perMessageDeflate: true
  })
  app.ws('/rtsp/', rtspRequestHandle)
  app.listen(8888)
  console.log('express listened')
}

// RTSP 转码方法
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)
  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)
  }
}

export default videoServer

渲染进程通过播放视频

<template>
  <div class="video">
    <video class="video-box" ref="player"></video>
  </div>
</template>

<script>
  import flvjs from 'flv.js'
  export default {
    name: 'videopage',
    props: {
      rtsp: String
    },
    data () {
      return {
        player: null
      }
    },
    mounted () {
      if (flvjs.isSupported()) {
        let video = this.$refs.player
        if (video) {
          this.player = flvjs.createPlayer({
            type: 'flv',
            isLive: true,
            url: 'ws://localhost:8888/rtsp/?url=' + this.rtsp
          })
          this.player.attachMediaElement(video)
          try {
            this.player.load()
            this.player.play()
          } catch (error) {
            console.log(error)
          }
        }
      }
    },
    methods: {
      getCurrentFrame () {
        let video = this.$refs.player
        let scale = 1
        let canvas = document.createElement('canvas')
        canvas.width = video.videoWidth * scale
        canvas.height = video.videoHeight * scale
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)
        return canvas.toDataURL('image/png')
      }
    },
    beforeDestroy () {
      this.player.destory()
    }
  }
</script>

<style lang="scss">
.video {
  width: 100%;
  height: 100%;
  font-size: 0;
  video {
    width: 100%;
    height: 100%;
  }
}
</style>
4275 次点击
所在节点    Node.js
17 条回复
yangheng4922
2020-07-21 23:23:06 +08:00
不要沉啊
yangheng4922
2020-07-22 01:59:33 +08:00
有大佬遇到过这种问题么
circleee
2020-07-22 08:59:12 +08:00
能转成 rtmp 吗?
jiobanma
2020-07-22 09:11:41 +08:00
c 的话不知道怎么做,不过我开源了一套 java 的 rtsp-rtmp 的服务,使用开源的 javacv 框架(调用底层 ffmpeg ) 使用了转封装的技术,直接将音视频解复用,然后转封装为 flv 格式的包推出去,因为不涉及编解码 所以 cpu 内存占用率很低。延迟的话大概 1-3s ggitee 地址: https://gitee.com/banmajio/RTSPtoRTMP github: https://github.com/banmajio/RTSPtoRTMP 如果有帮助,劳烦点个 star
leega0
2020-07-22 09:26:55 +08:00
@circleee rtmp 最多用到年底
lower
2020-07-22 16:13:56 +08:00
有没有可能直接集成个 vlc 直接取 rtsp 流?
tangchi695
2020-07-23 11:34:20 +08:00
想问下海康的视频流怎么获取的呢?同样在弄一个有监控的项目,以前没做过视频,不知道怎么在 nvr 上做二次开发。
SongGG3
2020-07-23 14:14:31 +08:00
试试 input output 添加 -fflags nobuffer -tune zerolatency

然后 flv.js 添加 enableStashBuffer: true
yangheng4922
2020-07-23 16:38:42 +08:00
@SongGG3 #8
在 ffmpeg 的配置里面添加么
yangheng4922
2020-07-23 16:39:02 +08:00
@tangchi695 #7 海康可以通过 rtsp 协议获取视频流
yangheng4922
2020-07-24 01:08:20 +08:00
@SongGG3 #8
```javascript
ffmpeg(url)
.addInputOption('-rtsp_transport', 'tcp', '-buffer_size', '102400', '-fflags', 'nobuffer', '-tune', 'zerolatency')
```

```javascript
flvjs.createPlayer({
type: 'flv',
isLive: true,
url: 'ws://localhost:8888/rtsp/?url=' + this.rtsp,
enableStashBuffer: true // 添加行
})
```
yangheng4922
2020-07-24 01:08:40 +08:00
@SongGG3 #8 是这样子么
yangheng4922
2020-07-26 09:53:53 +08:00
@SongGG3 #8
我修改了一下参数 但是还是没有明显的改善
SongGG3
2020-07-27 14:03:02 +08:00
@yangheng4922 output 的参数也加上去 -fflags nobuffer.
flv.js enableStashBuffer: false 才对,忘记改了
yangheng4922
2020-07-27 14:06:10 +08:00
@SongGG3 #14 改了一下 差不多延时控制在 一秒左右
yangheng4922
2020-07-29 15:44:05 +08:00
@SongGG3 #14 我查了文档说是可以通过设置 video.currentTime = this.player.buffered.end(0) 来清除延迟
是可以 但是 视频会一卡一卡的
lifefriend
2020-07-30 10:47:44 +08:00
@yangheng4922 怎么做到 1s 延迟的。我按照 lz 给出的代码,延迟在 5s 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/692057

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX