JavaScript简易实现RTSP视频流在网页端播放

2,439 阅读2分钟

前言

RTSP是指实时流传输协议(Real Time Streaming Protocol,RTSP)目前的浏览器还不支持接收这种协议的数据,所以是没办法做到是直接接收的,需要通过后端转流封装成新的格式推流到前端才能进行播放。

具体流程

用Nodejs调用Ffmpeg来接收RTSP协议数据流,并进行转流封装为.flv的视频格式使用websocket推流到前端,最后前端使用flv.js进行接收来实现实时RTSP流视频播放。

后端

var express =  require("express");
var expressWebSocket = require("express-ws");
var ffmpeg = require("fluent-ffmpeg");
ffmpeg.setFfmpegPath("D:/Program Files (x86)/ffmpeg-4.2.2-win64-static/bin/ffmpeg");
var webSocketStream = require("websocket-stream/stream");
var WebSocket = require("websocket-stream");
function localServer() {
    let app = express();
    app.use(express.static(__dirname));
    expressWebSocket(app, null, {
        perMessageDeflate: true
    });
    app.ws("/rtsp/:id/", rtspRequestHandle)
    app.listen(8888);
    console.log("express listened")
}
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();

ffmpeg的原生命令行较为复杂,而 fluent-ffmpeg 则将这些命令抽象为一个npm包,对于前端来说,无疑是借助这种方式上手更舒服(只不过作者已经好久没更新了。。。)

ffmpeg.setFfmpegPath 这个函数将外部的ffmpeg库载入,有全局的话可以直接写即可

ffmpeg.setFfmpegPath('ffmpeg')

前端

<script src="flv.min.js"></script>
<video id="videoElement"></video>
<script>
    if (flvjs.isSupported()) {
        var videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',//flv格式
            isLive: true,//标记为直播流
            url: `ws://localhost:8888/rtsp/${1}/?url=${you rtsp url}`,
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();
        flvPlayer.play();
    }
</script>

前端使用flv.js开源播放器。

不过这样传参会个问题,RTSP地址也带参数的话会和?url所冲突。不过也好解决用对URL地址编码和解码即可:

//前端
url: `ws://localhost:8888/rtsp/${1}/?url=${encodeURIComponent(you rtsp url)}`,
//后端
const querystring = require('querystring'); 
let url = querystring.unescape(req.query.url);

总结

这样一个简易的播放RTSP就实现了

最后感谢阅读