关于 RTSP 用 FFMPEG 转 flv 播放延迟问题
資深大佬 : yangheng4922 9
最近在用 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>
大佬有話說 (12)