前言

node-media-server 是基于 node.jsRTMP/HTTP-FLV/WS-FLV/HLS/DASH 流媒体服务器三方库

目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
src-
|- core-
| |- avcodec.js
| |- avpacket.js
| |- context.js
| |- logger.js
|
|- protocol-
| |- amf.js
| |- flv.js
| |- rtmp.js
|
|- server-
| |- broadcast_server.js
| |- http_server.js
| |- rtmp_server.js
|
|- session-
|- base_session.js
|- flv_session.js
|- rtmp_session.js

core

该文件夹包含了:

  1. 对ffmpeg AVPacket的对接类的定义
  2. 节点存储
  3. 常用的 log

avcodec.js

注: 看雷神ffmpeg的帖子 https://blog.csdn.net/leixiaohua1020

avpacket.js

对接ffmpeg中的AVPacket

1
2
3
4
5
6
7
8
9
10
11
12
13
class AVPacket {
constructor() {
this.codec_id = 0;
this.codec_type = 0;
this.duration = 0;
this.flags = 0;
this.pts = 0; //编码时间戳
this.dts = 0; //解码时间戳
this.size = 0; //data的大小
this.offset = 0;
this.data = Buffer.alloc(0);
}
}

context.js

1
2
3
4
5
6
7
8
9
10
11
class Context {
constructor(config) {
this.config = config;

/** @type {Map<string, BaseSession>} */
this.sessions = new Map();

/** @type {Map<string, BroadcastServer>} */
this.broadcasts = new Map();
}
}

logger.js

统一管理 log

1
2
3
4
5
6
7
8
log(message, logLevel = "info") {
const messageLevel = this.levels.indexOf(logLevel);
const currentLevel = this.levels.indexOf(this.level);

if (messageLevel >= currentLevel) {
console.log(`[${this.getTime()}] [${logLevel.toUpperCase()}] ${message}`);
}
}

protocol

常用协议格式

amf.js

flv.js

rtmp.js

RTMP(Real-Time Messaging Protocol)是由Adobe Systems开发的一种用于音视频以及数据在因特网上进行高效传输的协议, 被广泛用于各种实时流媒体传输。

该节会很长,影响对整体信息的把握,另开一章。

server

broadcast_server.js

重要成员变量

变量 类型 描述
publisher BaseSession 推流的节点
subscribers Map 拉流的节点
flvHeader Buffer flv 不同于 rtmp 的头部
x-MetaData Buffer flv rtmp 都有的
x-AudioHeader Buffer flv rtmp 都有的音频的头部
x-VideoHeader Buffer flv rtmp 都有的视频的头部
x-GopCache Set flv rtmp 都有的

重要函数

函数 描述
postPlay 传入节点, 通过节点发送 (flv在前面额外发送 flvHeader) MetaData AudioHeader VideoHeader 以及 GopCache 中的每一个 Cache. 最后将节点设置为订阅者
donePlay 播放完毕, 删除传入的节点
postPush 将传入节点设置为 publisher
donePush 上传完毕, 如果传入的节点仍然是 publisher, 删除缓存
broadcastMessage 广播, 将传入的 packet 转换成对应协议的数据, 并对 subscibers 内每一个订阅节点发送数据

http_server.js / rtmp_server.js

两个协议的 server 内容相似,都是通过简单的三方库调用获取相应的 server 来监听对应端口

session

发布订阅模式,节点可作为发布者也可作为订阅者

base_session.js

下面两个 session 的基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class BaseSession {
constructor() {
this.id = randomId();
this.ip = "";
this.protocol = "";
this.streamHost = "";
this.streamApp = "";
this.streamName = "";
this.streamPath = "";

this.videoCodec = 0;
this.videoWidth = 0;
this.videoHeight = 0;
this.videoFramerate = 0;
this.videoDatarate = 0;
this.audioCodec = 0;
this.audioChannels = 0;
this.audioSamplerate = 0;
this.audioDatarate = 0;
}

/**
* @abstract
* @param {Buffer} buffer
*/
sendBuffer = (buffer) => {
};
}

flv_session.js

使用 flv 协议的节点,可推可拉

重要成员变量

变量 类型 描述
ctx Context 内容
req express.Request 请求数据
res express.Response 请求后的返回值
flv Flv Flv
streamPath string ffmpeg 推流时设置的 host 之后的部分
broadcast BroadcastServer 广播服务器

重要函数

函数 描述
onPlay 调用广播服务器的 postPlay
onPush 调用广播服务器的 postPush, 关闭 req
onData stream 操作, req 接收到数据时调用; 解析 data
sendBuffer 向 req 中写入数据

rtmp_session.js

使用 rtmp 协议的节点,可推可拉

重要成员变量

变量 类型 描述
ctx Context 内容
socket net.Socket 与 flv 不同, rtmp 不使用 http包装的请求协议, 而是传输层的套接字
rtmp Rtmp Rtmp
broadcast BroadcastServer 广播服务器

重要函数

函数 描述
onConnent 在 ctx 中设置流路径和广播服务器的键值对, 也是 flv_session 构造函数中所做的
onPlay 调用广播服务器的 postPlay
onPush 调用广播服务器的 postPush, 关闭 socket
onOutput 向 socket 中写入数据
onPacket 广播服务器广播 AVPacket
onData stream 操作, socket 接收到数据时调用; 解析 data
sendBuffer 向 req 中写入数据