Flv+NodeMediaServer实现前端实时推拉流

1,853 阅读2分钟

大家好,大傻最近在研究实时音视频相关内容,在不断地爬坑中,也成功完成了一个小demo

前言

技术相关:

  1. 前端:flv.js
  2. 服务器:NodeMediaServer
  3. 客户端 ffmpeg

image.png

原理

image.png 原理就是流媒体服务器通过接受到音视频文件的流数据进而转发给我们的前端想要的数据格式,在此处,我们的NodeMediaServer就充当了这么一个工作。

准备工作

首先前端通过src引入flv的cdn资源,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!-- index.html -->
<script src="https://cdn.bootcss.com/flv.js/1.4.0/flv.min.js"></script>
<video id="videoElement" style="width: 80%" controls="controls"></video>
<div id="clock">

</div>
<button id="start">开始</button>
<script>

    let flvPlayer
    if (flvjs.isSupported()) {
        let videoElement = document.getElementById('videoElement')
        flvPlayer = flvjs.createPlayer({
            type: 'flv',
            //  这个ip也记得改一下
            //   url: '本机NodeMedia服务的ip /live/STREAM_NAME.flv'
            url: 'http://localhost:8000/live/STREAM_NAME.flv'
        })
        flvPlayer.attachMediaElement(videoElement)
        flvPlayer.load()
        flvPlayer.play()

    }

    var oBox= document.getElementById('clock');
    var maxtime = 6 * 60;
    function CountDown() {
        if (maxtime >= 0) {
            minutes = Math.floor(maxtime / 60);
            seconds = Math.floor(maxtime % 60);
            msg = "距离结束还有" + minutes + "分" + seconds + "秒";
            oBox.innerHTML = msg;
            if (maxtime == 5 * 60)alert("还剩5分钟");
            --maxtime;
        } else{
            clearInterval(timer);
            alert("时间到,结束!");
        }
    }
    document.getElementById('start').onclick=()=>{
        timer = setInterval("CountDown()", 1000);
    }

</script>
</body>
</html>

在这我们利用了一个简单的倒计时来观察实时直播的延迟时间

image.png 然后是我们服务端代码,如下:

// app.js
const NodeMediaServer = require('node-media-server');

const streamConfig = {
    //  接受推过来的流量
    rtmp: {
        port: 1935,
        chunk_size: 60000,
        gop_cache: true,
        ping: 30,
        ping_timeout: 60
    },
    //  转发推流的信息
    http: {
        port: 8000,
        allow_origin: '*'
    }
};

let Servers = new NodeMediaServer(streamConfig)
Servers.run();

在这我们通过接受来自ffmpeg的推流并把流数据在转发给我们的前端页面,我们也可以打开http://localhost:8000/admin/ 来进行观看流数据推拉情况以及CPU和内存占用情况 image.png image.png 最后是我们客户端的工具FFmpeg:在Linux服务器上我们可以直接通过 brew install ffmpeg来进行下载安装,如果我们是windows,那么我们需要安装一个windows的版本。接下来我们通过命令行来进行推流工作:

  • 推送视频: ffmpeg -re -i 视频名称 -c copy -f flv rtmp://ip:1935/live/STREAM_NAME
  • 推送摄像头:ffmpeg -f avfoundation -video_size 640x480 -framerate 30 -i 0:0 -vcodec libx264 -preset veryfast -f flv rtmp://ip:1935/live/STREAM_NAME
  • Linux
    • 推送屏幕:ffmpeg -f avfoundation -i "1" -vcodec libx264 -preset ultrafast -acodec libfaac -f flv rtmp://ip:1935/live/STREAM_NAME
  • Windows
    • 推送屏幕:ffmpeg -f gdigrab -i "desktop" -vcodec libx264 -preset ultrafast -acodec libfaac -f flv rtmp://ip:1935/live/STREAM_NAME 这里需要提到的是Linux 和 windows 区别 在于 linux下有avfoundation ‘1’ 而在windows下是gdigrab "desktop",其意义都是推送桌面的实时数据。 至此我们的内容已经可以正常运行让我们看下延迟大概有多少。

test.gif 本次测试,大傻的延迟大概是在7-10s左右,对于一般的直播要求是可以接受的,那有没有更好的解决方案呢,答案是WebRTC,这里就不对WebRTC的方案介绍了,大傻也是简单了解了RTC以及绝对的速度领先。