ubuntu16.04搭建rtmp流媒体服务器
rtmpdump2.3 安装与编译
rtmpdump下载
编译安装
make && make install
问题
- error: storage size of ‘ctx’ isn’t known HMAC_CTX ctx
handshake.h: In function ‘HMACsha256’:
handshake.h:266:12: error: storage size of ‘ctx’ isn’t known
HMAC_CTX ctx;
openssl版本太高,不匹配
nginx1.8 安装与编译
nginx下载
nginx-rtmp-module 模块
编译安装
-
./configure --prefix=/usr/local/videodevenv/nginx1.8 --add-module=../nginx-rtmp-module-master/
-
make -j6
-
make install
配置rtmp服务
配置nginx
在nginx的配置文件nginx.conf最后添加如下信息
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
#####################config rtmp start################################
# RMTP的服务器配置信息
rtmp {
server {
listen 2020; #推流的监听端口
publish_time_fix on;
# 推流其一
application live {
live on; #stream on live allow
allow publish all; # control access privilege
allow play all; # control access privilege
}
#推流其二
# application hls_alic {
# live on;
# hls on;
# hls_path /home/alic/www/hls;
# hls_fragment 5s;
# }
}
}
######################config rtmp end##############################
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
#出现:nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use),则修改HTTP的监听端口不为80
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
启动nginx服务器即相关播放指令
- 进程启动
/usr/local/nginx1.8/sbin/nginx //启动
/usr/local/nginx1.8/sbin/nginx -s reload //重启
- 播放推流
ffmpeg -re -i /home/ubuntu/code/streaming/srs-test.flv -vcodec copy -acodec copy -f flv -y \
rtmp://192.168.0.10:2020/live/livestream
flv封装协议
flv 封装格式
FLV Header解析:9字节
++FLV文件应以大端字节顺序存储多字节数据++
字段含义 | 字段大小 | 字段描述 |
---|---|---|
文件类型 | 3 字节 | 总是FLV(0x46–>0x4C 0x4c–>4c 0x56–>0x56) |
版本 | 1 字节 | 一般是0x01,表示FLV version 1 |
流信息 | 1 字节 | 倒数第一bit是1表示有视频,倒数第三bit是1表示有音频,其他都应该是0 |
header长度 | 4 字节 | 整个文件头的长度,一般是9(3+1+1+4),有时候后面还有些别的信息,就不是9了 |
46 4c 56 01 05 00 00 00 09 |FLV.............|
05–>表示音视频都有
FLV Body
body部分由一个个Tag和Tag长度组成,每个Tag的下面有一块4字节的空间用来记录这个Tag的长度,在第一个Tag之前的数据不存在,协议规定4字节的Tag长度为0。
00 00 00 00
- Tag区由两部分组成:Tag头和Tag数据区
- Tag 头部:11字节
名称 | 长度(UI:unsigned int) | 描述 |
---|---|---|
TagType(tag类型) | UI8 | UB[2]:保留给FMS,应为0 UB[1]:未加密0,对于加密标记为1 UB[5]:8–> audio(音频);9–>video(视频);18–>script data(脚本数据);all others: reserved(其他保留) |
DataSize(tag数据区大小) | UI24 | tag的数据区大小(StreamID之后的数据长度),以字节为单位,注意字节序 |
Timestamp(时间戳) | UI24 | 相对于FLV文件第一个tag的时间,以毫秒为单位,第一个tag的时间戳为0 |
TimestampExtended(时间戳扩展) | UI8 | 将时间戳扩展至32位,该字节代表高8位 |
StreamID(信息流ID) | UI24 | 恒为0 |
Data(tag数据区) | TagType == 8,AUDIODATA TagType == 9,VIDEODATA TagType == 18,SCRIPTDATAOBJECT |
- 数据区
- script data 解析
- script头部
0x12 :1字节tag类型:18
00 01 74 :3字节数据区大小:372字节
00 00 00 :3字节开始时间戳:第一个tag为0
00 :1字节扩展时间戳:0未扩展
00 00 00 :3字节流信息:恒为0;
12 00 01 74 00 00 00 00 00 00 00
- script数据区
script数据区会放一些关于FLV视频和音频的参数信息,如duration、width、height等。通常该类型Tag会跟在File Header后面作为第一个Tag出现,而且只有一个。
值 | 类型 | 说明 |
---|---|---|
0 | Number type | 8 Byte Double |
1 | Boolean type | 1 Byte bool |
2 | String type | 后面2个字节为长度 |
3 | Object type | |
4 | MovieClip type | |
5 | Null type | |
6 | Undefined type | |
7 | Reference type | |
8 | ECMA array type | 数组,类似Map |
10 | Strict array type | |
11 | Date type | |
12 | Long string type | 后面4个字节为长度 |
解析规则为:数据类型 + 数据长度(根据类型决定) + 数据 三部分组成,如:
02 00 0a 6f 6e 4d 65 74 61 44 61 74 61
0x02 :UI8--> 1字节ScriptDataValue:表示SCRIPTDATASTRING类型
0x00 0x0A :2字节数据长度:10字节数据
6f 6e 4d 65 74 61 44 61 74 61 :10字节数据-->onMetaData
08 00 00 00 10 00 08 64 75 72 61 74 69 6f 6e
0x08 :UI8--> 1字节ECMA array type:表示一个ECMA列表,其包括4字节列表项长度,列表变量名和值,列表分隔符
00 00 00 10 :4字节列表长度:16个列表项
00 08 :2字节表示长度:8字节数据
64 75 72 61 74 69 6f 6e :8字节数据:duration
00 :8字节double型
40 6a 57 6c 8b 43 95 81 :8字节转双精度doubl值:210.732(转换代码查看参考文献2)
00 05 :2字节表示长度:8字节数据
77 69 64 74 68 :5字节数据:width
00 :8字节double型
40 88 00 00 00 00 00 00 :8字节转双精度double值:768
。。。
00 08 66 69 6c 65 73 69 7a 65 00 41 59 51 4d 40 00 00 00
00 08 :2字节表示长度:8字节数据
66 69 6c 65 73 69 7a 65 :8字节数据:filesize文件大小
00 :8字节double型
41 59 51 4d 40 00 00 00 :8字节转双精度double值:6.63685e+06
数据区结尾:00 00 09 (object的结尾),00 00 09(ecma array的结尾)
00 00 09
script data区长度为:数据区(372)+ 头部(11)= 0x017f(383)
00 00 01 7f
- video data
- 视频头部:11字节
09 00 00 2e 00 00 00 00 00 00 00
0x09 :1字节tag类型:9表示视频
00 00 2e :3字节数据区长度:46字节
09 00 00 2e 00 00 00 00 00 00 00
0x09 :1字节tag类型:9表示视频
00 00 2e :3字节数据区长度:46字节
00 00 00 :3字节开始时间戳:第一个tag为0
00 :1字节扩展时间戳:0未扩展
00 00 00 :3字节流信息:恒为0;
- 视频数据区
名称 | 长度(UI:unsigned int) | 描述 |
---|---|---|
video信息 | UI8 | UB[4]表示类型: 1. keyframe 2. inner frame 3. disposable inner frame (H.263 only) 4. generated keyframe (reserved for server use only) 5. video info/command frame UB[4]表示编码器id: 1. JPEG (currently unused) 2. Seronson H.263 3. Screen video 4. On2 VP6 5. On2 VP6 without channel 6. Screen video version 2 7: AVC |
video数据区 | - | If CodecID == 2 H263VIDEOPACKET If CodecID == 3 SCREENVIDEOPACKET If CodecID == 4 VP6FLVVIDEOPACKET If CodecID == 5 VP6FLVALPHAVIDEOPACKET If CodecID == 6 SCREENV2VIDEOPACKET if CodecID == 7 AVCVIDEOPACKET |
17 前4位1:关键帧;后4位:编码类型
00 00 00 00
01 64 00 20 ff e1 00 19 67 64 00 20 ac d9 40 c0
29 b0 11 00 00 03 00 01 00 00 03 00 32 0f 18 31
96 01 00 05 68 eb ec b2 2c
video data区长度为:数据区(46)+ 头部(11)= 0x39(57)
00 00 00 39
- audio data
- 音频头部
08 00 00 04 00 00 00 00 00 00 00
0x08 :1字节tag类型:9表示音频
00 00 04 :3字节数据区长度:4字节
00 00 00 :3字节开始时间戳:第一个tag为0
00 :1字节扩展时间戳:0未扩展
00 00 00 :3字节流信息:恒为0
- 音频数据区
名称 | 长度(UI:unsigned int) | 描述 |
---|---|---|
audio信息 | UI8 | UB[4]表示音频格式: 0. 未压缩 1. ADPCM 2. MP3 3. Linear PCM, little endian 4. Nellymoser 16-kHz mono 5. Nellymoser 8-kHz mono 6. Nellymoser 7. G.711 A-law logarithmic PCM 8. G.711 mu-law logarithmic PCM 9. reserved 10. AAC 11. Speex 14. MP3 8-Khz 15. Device-specific sound UB[2]表示samplerate: 0. 5.5kHz 1. 11kHz 2. 22kHz 3. 44kHz UB[1]表示每个采样的长度: 0. snd8Bit 1. snd16Bit UB[1]表示类型: 0. sndMomo 1. sndStereo |
audio数据区 | - |
af 00 12 10
af a二进制:1010 11 1 1:AAC + 44kHz + 16Bit + Stereo
audio data区长度为:数据区(4)+ 头部(11)= 0x0f(15)
00 00 00 0f
查看flv文件:/srs3.0/trunk/doc$ hd source.200kbps.768x320.flv |more
00000000 46 4c 56 01 05 00 00 00 09 00 00 00 00 12 00 01 |FLV.............|
00000010 74 00 00 00 00 00 00 00 02 00 0a 6f 6e 4d 65 74 |t..........onMet|
00000020 61 44 61 74 61 08 00 00 00 10 00 08 64 75 72 61 |aData.......dura|
00000030 74 69 6f 6e 00 40 6a 57 6c 8b 43 95 81 00 05 77 |tion.@jWl.C....w|
00000040 69 64 74 68 00 40 88 00 00 00 00 00 00 00 06 68 |idth.@.........h|
00000050 65 69 67 68 74 00 40 74 00 00 00 00 00 00 00 0d |eight.@t........|
00000060 76 69 64 65 6f 64 61 74 61 72 61 74 65 00 40 69 |videodatarate.@i|
00000070 e8 50 00 00 00 00 00 09 66 72 61 6d 65 72 61 74 |.P......framerat|
00000080 65 00 40 39 00 00 00 00 00 00 00 0c 76 69 64 65 |e.@9........vide|
00000090 6f 63 6f 64 65 63 69 64 00 40 1c 00 00 00 00 00 |ocodecid.@......|
000000a0 00 00 0d 61 75 64 69 6f 64 61 74 61 72 61 74 65 |...audiodatarate|
000000b0 00 40 3d 54 40 00 00 00 00 00 0f 61 75 64 69 6f |.@=T@......audio|
000000c0 73 61 6d 70 6c 65 72 61 74 65 00 40 e5 88 80 00 |samplerate.@....|
000000d0 00 00 00 00 0f 61 75 64 69 6f 73 61 6d 70 6c 65 |.....audiosample|
000000e0 73 69 7a 65 00 40 30 00 00 00 00 00 00 00 06 73 |size.@0........s|
000000f0 74 65 72 65 6f 01 01 00 0c 61 75 64 69 6f 63 6f |tereo....audioco|
00000100 64 65 63 69 64 00 40 24 00 00 00 00 00 00 00 0b |decid.@$........|
00000110 6d 61 6a 6f 72 5f 62 72 61 6e 64 02 00 04 69 73 |major_brand...is|
00000120 6f 6d 00 0d 6d 69 6e 6f 72 5f 76 65 72 73 69 6f |om..minor_versio|
00000130 6e 02 00 03 35 31 32 00 11 63 6f 6d 70 61 74 69 |n...512..compati|
00000140 62 6c 65 5f 62 72 61 6e 64 73 02 00 10 69 73 6f |ble_brands...iso|
00000150 6d 69 73 6f 32 61 76 63 31 6d 70 34 31 00 07 65 |miso2avc1mp41..e|
00000160 6e 63 6f 64 65 72 02 00 0d 4c 61 76 66 35 34 2e |ncoder...Lavf54.|
00000170 36 33 2e 31 30 34 00 08 66 69 6c 65 73 69 7a 65 |63.104..filesize|
00000180 00 41 59 51 4d 40 00 00 00 00 00 09 00 00 01 7f |.AYQM@..........|
00000190 09 00 00 2e 00 00 00 00 00 00 00 17 00 00 00 00 |................|
000001a0 01 64 00 20 ff e1 00 19 67 64 00 20 ac d9 40 c0 |.d. ....gd. ..@.|
000001b0 29 b0 11 00 00 03 00 01 00 00 03 00 32 0f 18 31 |)...........2..1|
000001c0 96 01 00 05 68 eb ec b2 2c 00 00 00 39 08 00 00 |....h...,...9...|
000001d0 04 00 00 00 00 00 00 00 af 00 12 10 00 00 00 0f |................|
000001e0 09 00 14 11 00 00 00 00 00 00 00 17 01 00 00 50 |...............P|
000001f0 00 00 02 b0 06 05 ff ff ac dc 45 e9 bd e6 d9 48 |..........E....H|
00000200 b7 96 2c d8 20 d9 23 ee ef 78 32 36 34 20 2d 20 |..,. .#..x264 - |
00000210 63 6f 72 65 20 31 33 38 20 2d 20 48 2e 32 36 34 |core 138 - H.264|
00000220 2f 4d 50 45 47 2d 34 20 41 56 43 20 63 6f 64 65 |/MPEG-4 AVC code|
00000230 63 20 2d 20 43 6f 70 79 6c 65 66 74 20 32 30 30 |c - Copyleft 200|
00000240 33 2d 32 30 31 33 20 2d 20 68 74 74 70 3a 2f 2f |3-2013 - http://|
00000250 77 77 77 2e 76 69 64 65 6f 6c 61 6e 2e 6f 72 67 |www.videolan.org|
00000260 2f 78 32 36 34 2e 68 74 6d 6c 20 2d 20 6f 70 74 |/x264.html - opt|
00000270 69 6f 6e 73 3a 20 63 61 62 61 63 3d 31 20 72 65 |ions: cabac=1 re|
00000280 66 3d 33 20 64 65 62 6c 6f 63 6b 3d 31 3a 30 3a |f=3 deblock=1:0:|
00000290 30 20 61 6e 61 6c 79 73 65 3d 30 78 33 3a 30 78 |0 analyse=0x3:0x|
000002a0 31 33 33 20 6d 65 3d 68 65 78 20 73 75 62 6d 65 |133 me=hex subme|
000002b0 3d 37 20 70 73 79 3d 31 20 70 73 79 5f 72 64 3d |=7 psy=1 psy_rd=|
000002c0 31 2e 30 30 3a 30 2e 30 30 20 6d 69 78 65 64 5f |1.00:0.00 mixed_|
000002d0 72 65 66 3d 31 20 6d 65 5f 72 61 6e 67 65 3d 31 |ref=1 me_range=1|
000002e0 36 20 63 68 72 6f 6d 61 5f 6d 65 3d 31 20 74 72 |6 chroma_me=1 tr|
000002f0 65 6c 6c 69 73 3d 31 20 38 78 38 64 63 74 3d 31 |ellis=1 8x8dct=1|
00000300 20 63 71 6d 3d 30 20 64 65 61 64 7a 6f 6e 65 3d | cqm=0 deadzone=|
00000310 32 31 2c 31 31 20 66 61 73 74 5f 70 73 6b 69 70 |21,11 fast_pskip|
00000320 3d 31 20 63 68 72 6f 6d 61 5f 71 70 5f 6f 66 66 |=1 chroma_qp_off|
00000330 73 65 74 3d 2d 32 20 74 68 72 65 61 64 73 3d 38 |set=-2 threads=8|
00000340 20 6c 6f 6f 6b 61 68 65 61 64 5f 74 68 72 65 61 | lookahead_threa|
00000350 64 73 3d 31 20 73 6c 69 63 65 64 5f 74 68 72 65 |ds=1 sliced_thre|
00000360 61 64 73 3d 30 20 6e 72 3d 30 20 64 65 63 69 6d |ads=0 nr=0 decim|
RTMP流协议
定义和描述
定义 | 描述 |
---|---|
消息流 | 允许消息流动的逻辑上的通讯通道 |
消息流ID | 每个消息所关联的ID,用于区分其所在的消息流 |
消息格式 | 服务端和客户端通过在网络上发送RTMP消息进行通讯。消息可能包含音频,视频,数据,或其他的消息,RTMP消息分头和负载两部分 |
块 | 一个消息片段。消息通常在被放到网络上传输之前被分成小的部分并且被交错存取。分块确保跨流的所有消息按时间戳顺序被不断的传输 |
块流 | 允许块按照某一方向流动的逻辑上的通讯通道。块流可以从客户端流向服务端,也可以从服务端流向客户端 |
块流ID | 每个块所关联的用于区分其所在块流的ID |
块格式
- 块由头和数据组成
- 块头又由块基本头和块消息头组成:根据块头第一字节的高2位又可以扩展四种块消息头,根据块头第一字节的低6位来决定块基本头的字节数。
- 扩展时间戳:零或四字节
块基本头
块基本头编码块流ID和块类型,块类型决定编码消息头的格式。
- 第一个字节的高2位表示块类型,即存RTMP流分块的四种格式:
0,1,2,3
- 第一个字节的低6位用来决定块基本头的字节数,进而确定块流的ID号,具体看低6位的值:
- 2-63: 块基本头由一个字节组成,块流ID = 第一字节低六位值,其中2表示低层协议消息的块流ID
- 1:块基本头由三个字节组成,块流ID的范围是64-65599,块流ID = 第三个字节 * 256 + 第二个字节 + 64;
- 0:块基本头由两个字节组成,块流ID的范围是64-319,块流ID = 第二个字节 + 64;
- 本协议支持65597种流,ID从3-65599。ID 0、1、2作为保留。
块消息头
有四种格式的块消息ID,供块流基本头中第一字节的高2位来选择:
- 类型0
0 类型的块长度为11 字节:时间戳3字节,消息长度3字节,消息类型1字节,消息流id 4字节。在一个块流的开始和时间戳返回的时候必须有这种块。 - 类型1
类型1 的块占7 个字节:时间戳增量3字节,消息长度3字节,消息类型1字节。消息流ID 不包含在本块中。块的消息流ID与先前的块相同。具有可变大小消息的流,在第一个消息之后的每个消息的第一个块应该使用这个格式。 - 类型2
类型2 的块占3 个字节:时间戳增量3字节。既不包含流ID也不包含消息长度。本块使用的流ID和消息长度与先前的块相同。具有固定大小消息的流,在第一个消息之后的每个消息的第一个块应该使用这个格式。 - 类型3
类型3 的块没有头。流ID,消息长度,时间戳都不出现。这种类型的块使用与先前块相同的数据。当一个消息被分成多个块,除了第一块以外,所有的块都应使用这种类型。
扩展时间戳
只有当块消息头中的普通时间戳设置为0x00ffffff
时(当时间戳大于3字节的时候,也就是4.64小时),本字段(4字节 填充到Timestamp Extended 字节)才被传送。如果普通时间戳的值小于0x00ffffff
,那么本字段一定不能出现。如果时间戳字段不出现本字段也一定不能出现。类型3的块一定不能含有本字段。本字段在块消息头之后,块数据之前。
消息
RTMP消息分头和负载两部分
消息头
消息头包含:
- 消息类型:一个字节字段用于表示消息类型。范围在1-7内的消息ID用于协议控制消息。
- 负载长度:三个字节字段用于表示负载的字节数。设置为big-endian格式。
- 时间戳:四字节字段包含消息的时间戳。4个字节用big-endian方式打包。
- 消息流ID:三字节字段标识消息流。这些字节设置为big-endian格式。
消息负载
包中所包含的数据
消息类型
服务端和客户端通过在互连网发送消息来通讯。消息包括音频消息,视频消息,命令消息,共享对象消息,数据消息,用户控制消息。
消息类型ID | 消息类型 | 说明 |
---|---|---|
8 | 音频消息 | 客户端或服务端发送本消息用于发送音频数据 |
9 | 视频消息 | 客户端或服务端使用本消息向对方发送视频数据。消息类型值9,保留为视频消息。视频消息比较大,会造成其他消息的延迟。为了避免这种情况,这种消息被关联为最低优先。 |
20:AMF0编码,17:AMF3编码 | 命令消息 | 命令消息承载用AMF编码的客户端与服务端之间的命令。消息类型为20的用AMF0编码,消息类型为17的用AMF3编码。 这些消息用于在远端实现连接,创建流,发布,播放和暂停等操作。状态,结果等命令消息用于通知发送者请求命令的状态。命令消息由命令名,传输ID,和包含相关参数的命令对象组成。客户端或服务端可以使用命令消息向远端请求远程过程调用 |
18:AMF0编码,15:AMF3编码 | 数据消息 | 客户端或服务端通过本消息向对方发送元数据和用户数据。元数据包括数据的创建时间、时长、主题等细节。消息类型为18的用AMF0编码,消息类型为15的用AMF3编码 |
22 | 聚合消息 | 含有一个消息列表的一种消息。消息类型值22,保留用于聚合消息 |
1-7 | 用户协议控制消息 | 客户端或服务端发送本消息通知对方用户控制事件 |
用户协议控制消息
RTMP保留消息类型ID 在1-7之内的消息为用户协议控制消息。这些消息包含RTMP块流协议和RTMP协议本身要使用的信息。ID为1和2用于RTMP块流协议。ID在3-6之内用于RTMP本身。ID 7的消息用于边缘服务与源服务器。
消息类型ID | 描述 | 说明 | 流ID | 块流ID |
---|---|---|---|---|
1 | 设置块大小 | 用于通知对等端使用新的最大块大小。块大小的值被承载为4字节大小的负载。块大小默认值:128,但是如果发送者希望改变这个值,则用本消息通知对等端 | 0 | 2 |
2 | 取消消息 | 用于通知正在等待接收块以完成消息的对等端,丢弃一个块流中已经接收的部分并且取消对该消息的处理。对等端把这个消息的负载当作要丢弃的消息的块流ID(32位)。当发送者已经发送了一个消息的一部分,但是希望告诉接收者消息的余下部分不再发送时,发送本消息。本字段承载要丢弃的消息所在的块流ID | 0 | 2 |
3 | 确认 | 客户端或服务端在接收到数量与窗口大小相等的字节后发送确认(致谢)到对方。窗口大小是在没有接收到接收者发送的确认(致谢)消息之前发送的字节数的最大值。服务端在建立连接之后发送窗口大小。本消息指定序列号。序列号(32位),是到当前时间为止已经接收到的字节数。 | 0 | 2 |
4 | 用户控制消息 | 客户端或服务端发送本消息通知对方用户的控制事件。本消息承载事件类型和事件数据 | 0 | 2 |
5 | 确认窗口大小 | 客户端或服务端发送本消息来通知对方发送确认(致谢)消息的窗口大小。例如,服务端希望每当发送的字节数等于窗口大小时从客户端收到确认(致谢)。服务端在成功处理了客户端的连接请求后向客户端更新窗口大小 | 0 | 2 |
6 | 设置对等端带宽 | 客户端或服务端发送本消息更新对等端的输出带宽。输出带宽值与窗口大小值相同。如果对等端在本消息中收到的值与窗口大小不相同,则发回确认(致谢)窗口大小消息 | 0 | 2 |
命令消息
NetConnection Commands(连接层的命令)
用来管理双端之间的连接状态,同时也提供了异步远程方法调用(RPC)在对端执行某方法。
发送端发送时会带有命令的名字,如connect,TransactionID表示此次命令的标识,Command Object表示相关参数。接受端收到命令后,会返回以下三种消息中的一种:
- _result 消息表示接受该命令,对端可以继续往下执行流程
- _error消息代表拒绝该命令要执行的操作
- method name消息代表要在之前命令的发送端执行的函数名称
这三种回应的消息都要带有收到的命令消息中的TransactionId来表示本次的回应作用于哪个命令。
可以认为发送命令消息的对象有两种,一种是NetConnection,表示双端的上层连接,一种是NetStream,表示流信息的传输通道,控制流信息的状态,如Play播放流,Pause暂停。
connect:用于客户端向服务器发送连接请求,消息的结构如下:
字段 | 类型 | 说明 |
---|---|---|
Command Name(命令名字) | String | 命令的名字,如”connect” |
Transaction ID(事务ID) | Number | 恒为1 |
Command Object(命令包含的参数对象) | Object | 键值对集合表示的命令参数 |
Optional User Arguments(额外的用户参数) | Object | 用户自定义的额外信息 |
第三个字段中的Command Object中会涉及到很多键值对,这里不再一一列出,使用时可以参考协议的官方文档。
消息的回应有两种,_result表示接受连接,_error表示连接失败
Call:用于在对端执行某函数,即常说的RPC:远程进程调用,消息的结构如下:
字段 | 类型 | 说明 |
---|---|---|
Procedure Name(进程名) | String | 要调用的进程名称 |
Transaction ID | Number|如果想要对端响应的话置为非0值,否则置为0 | |
Command Object | Object | 命令参数 |
Optional Arguents | Object | 用户自定义参数 |
如果消息中的TransactionID不为0的话,对端需要对该命令做出响应,响应的消息结构如下:
字段 | 类型 | 说明 |
---|---|---|
Command Name(命令名) | String | 命令的名称 |
TransactionID | Number | 上面接收到的命令消息中的TransactionID |
Command Object | Object | 命令参数 |
Optional Arguments | Object | 用户自定义参数 |
NetConnection-代表服务端和客户端之间连接的更高层的对象。NetStream-代表发送音频流,视频流和其他相关数据的通道的对象。我们也发送像播放,暂停等控制数据流动的命令。
- NetConnection 命令
NetConnection 管理服务端和客户端之间的双路连接。另外,它还支持异步远程方法调用。下列的方法可以通过NetConnection发送。
- 连接:客户端向服务端发送一个连接命令请求连接到一个服务应用实例
- 调用:NetConnection 对象的调用方法在接收端运行远程过程调用。远程方法的名作为调用命令的参数
- 关闭:
- 创建流:客户端发送本命令到服务端创建一个消息通讯的逻辑通道。音频,视频和元数据的发布是由创建流命令建立的流通道承载的。NetConnection本身是默认的流通道,具有流ID 0 。协议和一少部分命令消息,包括创建流,就使用默认的通讯通道。
- NetStream命令
NetStream定义,基于连接客户端和服务端的NetConnection对象的,可以使音频流,视频流和数据消息传输的通道。对于多数据流,一个NetConnection对象可以支持多个NetStreams。
下列的命令可以在netstream上发送。
- 播放:客户端发送本命令到服务端播放一个流
- 播放2:和播放命令不同,播放2命令可以切换到不同的码率,而不用改变已经播放的内容的时间线。服务端对播放2命令可以请求的多个码率维护多个文件
- 删除流:当NetStream对象销毁的时候发送删除流命令
- 关闭流
- 接收音频:NetStream发送接收音频消息通知服务端发送还是不发送音频到客户端
- 接收视频:NetStream 对象发送receiveVideo消息通知服务端是否发送视频到客户端
- 发布:客户端发送一个发布命令,发布一个命名流到服务端。使用这个名字,任何客户端可以播放该流并且接收音频,视频,和数据消息
- 搜索:客户端发送搜寻命令在一个媒体文件中或播放列表中搜寻偏移
- 暂停:客户端发送暂停命令告诉服务端暂停或开始一个命令
ERROR
ERROR: RTMP_Connect0, failed to connect socket. 111 (Connection refused)
没有开启nginx服务
./nginx/sbin/nginx
主要参考文献
- 关于16进制字符串转为单精度浮点数和双精度浮点数的运算
- FLV结构详解,FLV协议详解(泰山鲁 转载加修正)
- Real Time Messaging Chunk Stream Protocol
- RTMP Message Formats
- RTMP Commands Messages
- 带你吃透RTMP