⚡直播推流测试服务器,不知道怎么搞?NodeJS搭一个就行啦

1,689 阅读8分钟

前言

一直对直播功能蛮感兴趣的。之前调研的时候一直苦于没有服务器测试推流和拉流的流程,导致本地开发测试流程一直卡壳,甚至后来还买了一个腾讯云的虚拟主机,一顿操作猛于虎之后还是没配置成功~~~ ,然后这个直播功能就搁置了。

直到最近公司的项目迭代中有一个直播的功能,不由得又勾起了我对直播的兴趣。

小插曲

因为最近ChatGPT蛮火,问了ChatGPT怎么用nodejs搭一个推流服务器。它给了案例,然后少了三行关键代码,困扰了我好几天~~~

image.png

网上也搜过一些教程,发现很多流程不是很详细,对刚接触的新手小伙伴不是很友好,所以这里汇总了一下具体流程。

省流,本文主要实现

  • NodeJS + NodeMediaServer 搭建推流服务器
  • 推流 - ffmpeg 实时采集 Windows 计算机的摄像头视频流并以 FLV 格式推流到 NodeJS 搭建的服务器
  • 拉流 - 开发一个页面进行拉流实时展示直播内容

正文

1 NodeJS + NodeMediaServer 搭建推流服务器

磨刀不误砍柴工

首先介绍两个核心知识点,NodeJSNodeMediaServer。很多小伙伴肯定对NodeJS多少有点了解,这里大概赘述下。

1.1 NodeJS到底是干什么的?

1.1.1 打包工具

常见的打包工具例如 Webpack ,就是基于 NodeJS 运行的,都是使用了CommonJS模块化规范。

  • Webpack 配置文件(webpack.config.js)是使用 Node.js 的模块系统进行编写的,比如require 引入依赖模块, module.exports 导出模块,fs (文件系统),path (路径处理)。

  • webpack 的主要编程语言是 js,想要在你的机器上跑 js 脚本,就需要一个解释执行 js 的环境, nodejs 基于 V8 引擎进行了一系列封装,使得我们可以在非浏览器环境下解析执行 js。 (比如在你使用node xxx.js本地测试代码的时候)

  • webpack 基于NodeJS搭建了开发环境

1.1.2 服务器端开发

  • 搭建服务器

  • 平时联调时的接口可以用NodeJS自己开发(配合express或者koa)

  • 实时数据处理,使用websokcet开发聊天功能

  • Node.js 支持多种数据库,包括关系型数据库 SQL Server、MySQL、PostgreSQL、Oracle 等,以及非关系型数据库 MongoDB、Redis、Elasticsearch 等(这个没试过,之前是用phpstudy集成的)

1.1.3. 前端代码的打包和压缩

Node.js 可以利用 npm 包管理工具,为前端工程师提供各种打包、压缩工具和安装包的方式。

1.2 NodeMediaServer到底是干什么的?

NodeMediaServer 是一个基于 Node.js 实现的开源流媒体服务,主要功能有:

  • 直播推流:支持常见的推流协议,例如 RTMP、RTSP、HTTP、HLS 等。用户可以使用各种设备和软件推送视频和音频流。

  • 直播拉流:支持从其他流媒体服务器或设备上拉取视频和音频流。例如,可以从 IP 摄像头或其他 RTMP 服务器拉取视频和音频流,进行转码处理或直接进行播放。

  • 录播:支持将直播视频和音频流录制下来,生成 MP4、FLV 或 HLS 格式的文件。

  • 转码:支持将直播视频和音频流进行转码处理,并推送到其他服务器或平台。

两个核心知识点了解完了,那就开始搭建吧~~~

  • 首先安装 node,传送门

  • 然后安装 express 和 node-media-server 依赖包

npm install -S express node-media-server
  • 随便在一个位置新建一个app.js文件,名字可以随便起

  • 下面的代码复制一下,核心参数我加了注释,想了解的可以看一下

const express = require("express");
const app = express();

// 引入 Node-Media-Server 模块
const NodeMediaServer = require("node-media-server");
const nms = new NodeMediaServer({
  rtmp: {
    port: 1935, // 推流端口
    chunk_size: 60000,
    gop_cache: true, // 是否启用 GOP 缓存,缓存关键帧以提高快进、快退时的响应速度,默认为开启;
    ping: 60, // RTMP 连接保持时间,一旦超过这段时间,连接就会断开
    ping_timeout: 30, // 定义 RTMP 服务器不响应 ’ping’ 请求的超时时间(秒),默认为 30 秒
  }, 
  http: { 
    port: 8090, // 拉流端口
    allow_origin: '*' //允许跨域
  }
});

nms.run(); //启动流媒体服务器
  • 然后输入node app.js

image.png

以上,一个流媒体服务器就搭建完成了,推流的地址和拉流的地址也有啦,接下来就是开始推流了。

RTMP 推流地址: rtmp://本地ip:1935/live/streaming

拉流地址: http://本地ip:8090/live/streaming.flv

本地ip不清楚的可以见下图,调出黑窗口,输入ipconfigIPv4就是你的本地ip

image.png

2 推流 - ffmpeg 实时采集计算机的摄像头视频流并以 FLV 格式推流到 NodeJS 搭建的服务器

2.1 老样子,简单科普下啥是ffmpeg?

FFmpeg 是一款跨平台的开源多媒体处理工具,可以处理视频、音频等多种格式的媒体文件。该工具提供了各种命令行接口,支持多种媒体格式的转换、编辑、解码、编码等操作,包括了常见的媒体处理任务,例如视频剪辑、音频剪辑、媒体格式转换、速率变换、水印添加等。

  • 视频转码:可以将多种格式的视频文件转换为其他格式,如 MPEG、AVI、FLV、MP4、MOV 等;

  • 音频转码:可以将多种格式的音频文件转换为其他格式,如 MP3、WAV、AAC;

  • 处理视频:可以旋转、翻转、缩放、剪裁、添加水印等;

  • 处理音频:可以调整音频的音量、音调等;

  • 解码和编码:可以将音视频文件解码为原始的数据流,也可以将原始数据流编码为指定格式的音视频文件;

  • 封装和分离:可以将音视频数据流封装为特定的容器格式,如 MP4、FLV、AVI 等,也可以将容器格式中的音视频数据流分离出来;

  • 转换流媒体格式:可以将 RTMP 流转为 HTTP-FLV 或 HLS 流,也能把 GB 连接控制协议(GKCP) 数据传输到 RTSP 流中。

说了这么多,其实我只本地试了给一个视频加水印,裁剪自定义时间区间内的视频,倒是蛮好用的,感兴趣的小伙伴可以去试试。

安装ffmpeg 传送门

安装完之后,在任何位置都可以使用ffmpeg命令啦

说回正文,其实一行命令就行啦,哈哈~~~

Windows

ffmpeg -f dshow -i video="摄像头名称" -video_size 1280x720 -framerate 30 -vcodec libx264 -preset veryfast -f flv rtmp://本地ip:1935/live/streaming

Mac

ffmpeg -f avfoundation -i 0:0 -video_size 1280x720 -framerate 30 -vcodec libx264 -preset veryfast -f flv rtmp://本地ip:1935/live/streaming

这里说几个核心参数的意思

  • -f dshow: 指定输入设备为 DirectShow,表示使用 Windows 平台上的摄像头作为输入源。Mac是 -f avfoundation

  • -i video="摄像头名称"

  • -framerate 30: 指定输出的视频帧率为 30 帧/秒;

  • -vcodec libx264: 指定视频编码器为 H.264,可以输出较高质量的视频;

  • -f flv: 指定输出格式为 FLV

  • rtmp://本地ip:1935/live/streaming: 推流地址

2.2 如果不知道自己的摄像头名称,请看这里 右键我的电脑 => 管理 => 设备管理器

image.png

运行命令之后,如下图,一直在刷屏,并且你的笔记本的摄像头亮了。恭喜你,已经完成2/3了,摄像头已经开始采集你的脸并且往rtmp://本地ip:1935/live/streaming这个地址推送数据了

image.png

3 拉流 - 开发一个页面进行拉流实时展示直播内容

核心是使用B站开源的flv.js,把拉流地址里的数据处理一下,最后放到video标签里展示

西瓜视频测试flv(截至2023/4/26可用,测试你的拉流代码是否正常运行): sf1-hscdn-tos.pstatp.com/obj/media-f…

这块是网上搜到的,没有自己写了。代码是react的,小伙伴们不想自己写的话,可以直接github搜一个react技术栈的项目,把代码放在里面运行。直接上代码

import * as React from "react";

import { Button, Input, Row, Col } from "antd";
import flv from "flv.js";

const { useState, useEffect } = React;

interface LiveDemoProps {
	defaultUrl?: string;
	onUrlChange?: Function;
}
export default function LiveDemo({ defaultUrl = "http://10.43.49.84:8090/live/streaming.flv", onUrlChange }: LiveDemoProps) {
	let player = null;
	let playerDom = null;

	const [liveUrl, setLiveUrl] = useState(defaultUrl);

	useEffect(() => {
		if (flv.isSupported) {
			player = flv.createPlayer(
				{
					type: "flv",
					isLive: true,
					hasAudio: false,
					hasVideo: true,
					url: liveUrl,
					cors: true
				},
				{
					enableWorker: false,
					lazyLoadMaxDuration: 3 * 60,
					seekType: "range"
				}
			);
			player.attachMediaElement(playerDom);
			player.load();
		} else {
			console.log("Your browser is not support flv.js");
		}
	}, []);

	function updatePlayer() {
		if (player) {
			player.unload();
			player.detachMediaElement();
			player.destroy();
			player = null;
		}

		player = flv.createPlayer(
			{
				type: "flv",
				isLive: true,
				hasAudio: false,
				hasVideo: true,
				url: liveUrl,
				cors: true
			},
			{
				enableWorker: false,
				lazyLoadMaxDuration: 3 * 60,
				seekType: "range"
			}
		);
		player.attachMediaElement(playerDom);
		player.load();
	}

	return (
		<div className="live-demo">
			<div className="modify-url">
				<Row>
					<Col md={6}>
						<Input
							value={liveUrl}
							onChange={value => {
								setLiveUrl(value);
							}}
						/>
					</Col>
					<Col md={6}>
						<Button
							type={"primary"}
							onClick={() => {
								updatePlayer();
								onUrlChange && onUrlChange(liveUrl);
							}}
						>
							修改
						</Button>
					</Col>
				</Row>
			</div>
			<video style={{ width: "100%", height: "100%" }} controls className="video-demo" ref={e => (playerDom = e)}></video>
		</div>
	);
}

效果展示

output.gif

完结

这篇文章本该发出来啦,只是一直没时间搞,都用来做其他的事了。这里把所有流程和本地测试的笔记整理了一下,希望对小伙伴有帮助。

后续我会尝试更新在h5页面进行推流的文章,不借助ffmpeg。

欢迎转载,但请注明来源。

最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。

image.png

参考文档:

ffmpeg使用指令实现推流实现直播流程

前端如何实现整套视频直播技术流程