“RTMP study notes”的版本间的差异
free6d1823(讨论 | 贡献) |
free6d1823(讨论 | 贡献) (→examples) |
||
(未显示1个用户的15个中间版本) | |||
第184行: | 第184行: | ||
= examples = | = examples = | ||
Use nginx as server and ffmpeg as clients | Use nginx as server and ffmpeg as clients | ||
+ | Ref: cnblogs.com/liangblog/p/11122237.html | ||
+ | |||
*source download: | *source download: | ||
nginx: | nginx: | ||
http://nginx.org/download/nginx-1.16.1.tar.gz | http://nginx.org/download/nginx-1.16.1.tar.gz | ||
− | + | wget https://github.com/arut/nginx-rtmp-module/archive/master.zip | |
− | + | ||
+ | openssl: | ||
+ | openssl-1.1.1 | ||
+ | openssl-3.0.2 | ||
rtmpdump: | rtmpdump: | ||
git clone https://git.ffmpeg.org/rtmpdump | git clone https://git.ffmpeg.org/rtmpdump | ||
+ | |||
+ | ffmpeg: | ||
+ | git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg | ||
*build | *build | ||
nginx: | nginx: | ||
− | ./configure | + | ./configure --add-module=nginx-rtmp-module |
make | make | ||
sudo make install | sudo make install | ||
+ | <source lang="C"> | ||
+ | nginx path prefix: "/usr/local/nginx" | ||
+ | nginx binary file: "/usr/local/nginx/sbin/nginx" | ||
+ | nginx modules path: "/usr/local/nginx/modules" | ||
+ | nginx configuration prefix: "/usr/local/nginx/conf" | ||
+ | nginx configuration file: "/usr/local/nginx/conf/nginx.conf" | ||
+ | nginx pid file: "/usr/local/nginx/logs/nginx.pid" | ||
+ | nginx error log file: "/usr/local/nginx/logs/error.log" | ||
+ | nginx http access log file: "/usr/local/nginx/logs/access.log" | ||
+ | nginx http client request body temporary files: "client_body_temp" | ||
+ | nginx http proxy temporary files: "proxy_temp" | ||
+ | nginx http fastcgi temporary files: "fastcgi_temp" | ||
+ | nginx http uwsgi temporary files: "uwsgi_temp" | ||
+ | nginx http scgi temporary files: "scgi_temp" | ||
+ | </source> | ||
+ | |||
+ | Nginx会被安装在/usr/local/nginx目录下 | ||
+ | vi /usr/local/nginx/conf/nginx.conf | ||
+ | <source lang="c"> | ||
+ | events { | ||
+ | //events模块来用指定nginx的工作模式和工作模式及连接数上限 | ||
+ | } | ||
+ | http { | ||
+ | //负责HTTP服务器相关属性的配置 | ||
+ | } | ||
+ | rtmp { | ||
+ | server { | ||
+ | listen 1935; | ||
+ | buflen 10s; | ||
+ | application myapp { | ||
+ | live on; | ||
+ | max_connections 1024; | ||
+ | } | ||
+ | application mgclient { | ||
+ | live on; | ||
+ | hls on; | ||
+ | hls_fragment_naming sequential; | ||
+ | hls_playlist_length 30s; | ||
+ | hls_continuous on; | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | rtmpdump: | ||
+ | make sys=posix | ||
+ | sudo make install | ||
+ | |||
ffmpeg: | ffmpeg: | ||
+ | prerequirements: sudo apt install pkg-config | ||
./configure --enable-librtmp | ./configure --enable-librtmp | ||
make | make | ||
sudo make install | sudo make install | ||
− | + | ||
− | + | ||
− | + | ||
*start the server | *start the server | ||
+ | 启动 :/usr/local/nginx/sbin/nginx | ||
+ | 检查配置文件:/usr/local/nginx/sbin/nginx -t | ||
+ | 重载配置文件:/usr/local/nginx/sbin/nginx -s reload | ||
+ | 重启 : /usr/local/nginx/sbin/nginx -s reopen | ||
+ | 停止 :/usr/local/nginx/sbin/nginx -s stop | ||
*push a mp4 file | *push a mp4 file | ||
− | + | ffmpeg -re -i ${HOME}/test.mp4 -vcodec copy -codec copy -f flv rtmp://localhost/myapp/test1 | |
+ | [[文件:push.jpg]] | ||
*play a mp4 | *play a mp4 | ||
+ | ffplay rtmp://localhost/myapp/test1 | ||
+ | [[文件:pull.jpg]] | ||
[[*libRTMP study]] | [[*libRTMP study]] | ||
+ | |||
+ | =Trouble shootings= | ||
+ | 1. prerequirements: | ||
+ | openssl library: apt install libssl-dev && sudo apt install OpenSSL | ||
+ | PCRE library: no | ||
+ | zlib: sudo apt install zlib1g-dev | ||
+ | nginx configure: | ||
+ | ./configure --prefix=/usr/local/nginx --add-module=./nginx-rtmp-module --with-http_ssl_module --without-http_rewrite_module | ||
+ | 2. openssl 3.x compiling error | ||
+ | vi nginx/objs/Makefile => CFLAGS += -Wno-warning -Wno-deprecated-declarations | ||
+ | |||
+ | 3. fix librtmp compiling errors: | ||
+ | librtmp/dh.h | ||
+ | <source lang="c"> | ||
+ | typedef struct dh_st { | ||
+ | MP_t p; | ||
+ | MP_t g; | ||
+ | MP_t pub_key; | ||
+ | MP_t priv_key; | ||
+ | long length; | ||
+ | } MDH; | ||
+ | </source> | ||
+ | librtmp/handshake.h, | ||
+ | <source lang="c"> | ||
+ | #define HMAC_setup(ctx, key, len) { ctx=HMAC_CTX_new(); HMAC_Init_ex(ctx, key, len, EVP_sha256(), 0);} | ||
+ | #define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, buf, len) | ||
+ | #define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, dig, &dlen); HMAC_CTX_free(ctx) | ||
+ | |||
+ | static void HMACsha256(const uint8_t *message, size_t messageLen, ...) | ||
+ | static void InitRC4Encryption() { | ||
+ | HMAC_CTX* ctx; | ||
+ | HMAC_setup(ctx, secretKey, 128); | ||
+ | HMAC_crunch(ctx, message, messageLen); | ||
+ | HMAC_finish(ctx, digest, digestLen); | ||
+ | |||
+ | } | ||
+ | |||
+ | </source> | ||
+ | librtmp/hashswf.c | ||
+ | <source lang="c"> | ||
+ | struct info | ||
+ | { | ||
+ | z_stream *zs; | ||
+ | HMAC_CTX* ctx; | ||
+ | int first; | ||
+ | int zlib; | ||
+ | int size; | ||
+ | }; | ||
+ | |||
+ | #else /* USE_OPENSSL */ | ||
+ | #include <openssl/ssl.h> | ||
+ | #include <openssl/sha.h> | ||
+ | #include <openssl/hmac.h> | ||
+ | #include <openssl/rc4.h> | ||
+ | #define HMAC_setup(ctx, key, len) { ctx=HMAC_CTX_new(); HMAC_Init_ex(ctx, (unsigned char *)key, len, EVP_sha256(), 0);} | ||
+ | #define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, (unsigned char *)buf, len) | ||
+ | #define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, (unsigned char *)dig, &dlen); | ||
+ | #define HMAC_close(ctx) HMAC_CTX_free(ctx) | ||
+ | #endif | ||
+ | |||
+ | </source> | ||
+ | |||
+ | 4. For new OS, you will need | ||
+ | - X11: sudo apt install xorg-dev | ||
+ | - ALSA: sudo apt install libpulse-dev | ||
+ | - SDL: ./configure --enable-video-x11 --enable-x11-shared --enable-video-x11-vm --enable-alsa |
2022年5月4日 (三) 13:19的最后版本
Ref: https://www.adobe.com/devnet/rtmp.html
Handshaking Sequence
uninitialized ----
C0 -->
C1 -->
<-- S0 必须在 C0或C1 之后
<-- S1 必须在 C0或C1 之后
version sent -----
C2 -->
C2 必须在 S1之后
Ack sent -----
<-- s2 必须在C1之后
Handshake Done ----
data -->
data必须在S2之后
<-- data 必须在c2 之后
C0-> RTMP version 8 bits (=3)
<- S0 RTMP version 8 bit (=3)
C1,S1 1536 bytes
time[4]: stream 的参考基准时间 zero[4]:0 random bytes[1528] 乱数token
C2,S2 1536 bytes
time[4]: C2: S1 的时间; S2: C1 的时间 time2[4]: 读取S1/C1的时间 random bytes[1528]: C1/S1的乱数token
Chunk:
| Basic Header | Message Header | Extended Timestamp | Chunk Data |
+--------------+----------------+--------------------+--------------+
Basic Header: 1~3 bytes, Chunk Stream ID + chunk type
Message Header:0,3,7, or 11 bytes,message的type
Extended Timestamp: 0 or 4 bytes
Chunk header = Basic Header + Message Header + Extended Timestamp
Chunk data: variable size.
Chunk Stream ID: 3~65599,
0n = 64+n (64~319) 1mn = 64+m + n*256 (64~65599) n (n !=0,1,2 one byte) (3~63) 2 is reserved for level control
chunk type 高2位:format of Message header
Type 0: 11 byte 用于stream 开头 timestamp[3]: 发送时间, 0xffffff 使用Extended Timestamp [32bits] message length[3] message type id[1] message stream id[4] Type 1: 7 bytes timestamp delta[3] message length[3] message type id[1] Type 2: 3 bytes ID 与长度跟前个chunk 同 timestamp delta[3] Type 3: no message header. timestamp , ID 与长度跟前个chunk 同
message type id
1,2,3,5,6 for protocol control message 8: audio 9: video
Protocol Control Messages
message stream ID 0: control stream
chunk stream ID 2: used in control stream
message type id
ID | Name | Fields | size | Meaning |
---|---|---|---|---|
1 | Set Chunk Size | maximum chunk size | 32 bits | Set maximum chunk size (1~0x7FFFFFFF) |
2 | Abort Message | chunk stream ID | 32 bits | chunk stream ID message to be discard |
3 | Acknowledgement | sequnce number | 32 bits | This field holds the number of bytes
received so far. |
5 | Window Acknowledgement Size | window size | 32 bits | inform the peer of the
window size to use between sending acknowledgments |
6 | Set Peer Bandwidth | Acknowledgement Window size+Limit Type | 32+8 | sends this message to limit the output |
4 | User Control Message | Event Type*+Event Data | 16+variable | contain information used by the RTMP streaming layer |
Message Type:
ID | Name | Description |
---|---|---|
17(AMF3),20(AMF0) | Command Message** | These messages are sent to perform some operations like
connect, createStream, publish, play, pause on the peer. Command
|
18(AMF0),15(AMF3) | Data Message | metadata or user data |
19(AMF0),16(AMF3) | Share Object Message | Flash object: Shared object Name+Current version+Flags+Event Type+Event data length+Event data |
8 | Audio Message | audio data |
9 | Video Message | video data |
22 | Aggregate Message | contains a series of RTMP sub-message
|
- Limit type
0 - Hard: The peer SHOULD limit its output bandwidth to the indicated window size.
1 - Soft: The peer SHOULD limit its output bandwidth to the the window indicated in this message or the limit already in effect, whichever is smaller.
2 - Dynamic: If the previous Limit Type was Hard, treat this message as though it was marked Hard, otherwise ignore this message.
- RTMP Message Format
Message Header: big-endian format
Message Type[1] Payload length[3] Timestamp[4] Stream ID [3]
Message payload: actual data
- User Control Message - Event Type
ID | Event | Event data | Description |
---|---|---|---|
0 | Stream Begin | stream ID[4] | The server sends this event to notify the client that a stream has become functional |
1 | Stream EOF | stream ID[4] | server: playback of data is over |
2 | StreamDry | stream ID[4] | server: no more data on this stream |
3 | SetBufferLenth | stream ID[4]+bufferLength_in_ms[4] | client:inform server the buffer size in miliseconds |
4 | StreamIsRecorded | stream ID[4] | Server: stream is recorded stream |
6 | PingRequest | timestamp[4] | Server: test whether client is reachable |
7 | Ping Response | timestamp[4] | Client: responseserver with 6's timestamp |
- Types of command
1. NetConnection
command | description | fields |
---|---|---|
connect | client: request connect | command_name+Transaction ID+commans object+user argument |
call | remote procedure calls | procedureName + Tr. ID+commans object+ argument |
createStream | client: request server to create a logical channel for message | procedureName + Tr. ID+commans object |
Note:
Audio supported: SUPPORT_SND_ADPCM, MP3, NELLY8, NELLY, G711A, G711U, NELLY16,AAC, SPEEX
Video supported: SUPPORT_VID_SORENSON, HOMEBREW, VP6, VP6ALPHA, HOMEBREWV2, H264
AMF0: AMF0 object encoding supported by Flash 6 and later
AMF3: AMF3 encoding from Flash 9 (AS3)
2. NetStream
1. NetConnection
command | description | fields |
---|---|---|
play | client: | command_name+Transaction ID+commans object+user argument |
deleteStream | client: | |
closeStream | client: | |
receiveAudio | client: | |
reveiveVideo | client: | |
publish | client: | |
seek | client: | |
pause | client: | The client sends the pause command to tell the server to pause or
start playing |
onStatus | server: status update |
examples
Use nginx as server and ffmpeg as clients
Ref: cnblogs.com/liangblog/p/11122237.html
- source download:
nginx:
http://nginx.org/download/nginx-1.16.1.tar.gz wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
openssl:
openssl-1.1.1 openssl-3.0.2
rtmpdump:
git clone https://git.ffmpeg.org/rtmpdump
ffmpeg:
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
- build
nginx:
./configure --add-module=nginx-rtmp-module make sudo make install
nginx path prefix: "/usr/local/nginx" nginx binary file: "/usr/local/nginx/sbin/nginx" nginx modules path: "/usr/local/nginx/modules" nginx configuration prefix: "/usr/local/nginx/conf" nginx configuration file: "/usr/local/nginx/conf/nginx.conf" nginx pid file: "/usr/local/nginx/logs/nginx.pid" nginx error log file: "/usr/local/nginx/logs/error.log" nginx http access log file: "/usr/local/nginx/logs/access.log" nginx http client request body temporary files: "client_body_temp" nginx http proxy temporary files: "proxy_temp" nginx http fastcgi temporary files: "fastcgi_temp" nginx http uwsgi temporary files: "uwsgi_temp" nginx http scgi temporary files: "scgi_temp"
Nginx会被安装在/usr/local/nginx目录下
vi /usr/local/nginx/conf/nginx.conf
events { //events模块来用指定nginx的工作模式和工作模式及连接数上限 } http { //负责HTTP服务器相关属性的配置 } rtmp { server { listen 1935; buflen 10s; application myapp { live on; max_connections 1024; } application mgclient { live on; hls on; hls_fragment_naming sequential; hls_playlist_length 30s; hls_continuous on; } } }
rtmpdump:
make sys=posix sudo make install
ffmpeg:
prerequirements: sudo apt install pkg-config ./configure --enable-librtmp make sudo make install
- start the server
启动 :/usr/local/nginx/sbin/nginx 检查配置文件:/usr/local/nginx/sbin/nginx -t 重载配置文件:/usr/local/nginx/sbin/nginx -s reload 重启 : /usr/local/nginx/sbin/nginx -s reopen 停止 :/usr/local/nginx/sbin/nginx -s stop
- push a mp4 file
ffmpeg -re -i ${HOME}/test.mp4 -vcodec copy -codec copy -f flv rtmp://localhost/myapp/test1
- play a mp4
ffplay rtmp://localhost/myapp/test1
Trouble shootings
1. prerequirements:
openssl library: apt install libssl-dev && sudo apt install OpenSSL PCRE library: no zlib: sudo apt install zlib1g-dev nginx configure: ./configure --prefix=/usr/local/nginx --add-module=./nginx-rtmp-module --with-http_ssl_module --without-http_rewrite_module
2. openssl 3.x compiling error
vi nginx/objs/Makefile => CFLAGS += -Wno-warning -Wno-deprecated-declarations
3. fix librtmp compiling errors:
librtmp/dh.h
typedef struct dh_st { MP_t p; MP_t g; MP_t pub_key; MP_t priv_key; long length; } MDH;
librtmp/handshake.h,
#define HMAC_setup(ctx, key, len) { ctx=HMAC_CTX_new(); HMAC_Init_ex(ctx, key, len, EVP_sha256(), 0);} #define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, buf, len) #define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, dig, &dlen); HMAC_CTX_free(ctx) static void HMACsha256(const uint8_t *message, size_t messageLen, ...) static void InitRC4Encryption() { HMAC_CTX* ctx; HMAC_setup(ctx, secretKey, 128); HMAC_crunch(ctx, message, messageLen); HMAC_finish(ctx, digest, digestLen); }
librtmp/hashswf.c
struct info { z_stream *zs; HMAC_CTX* ctx; int first; int zlib; int size; }; #else /* USE_OPENSSL */ #include <openssl/ssl.h> #include <openssl/sha.h> #include <openssl/hmac.h> #include <openssl/rc4.h> #define HMAC_setup(ctx, key, len) { ctx=HMAC_CTX_new(); HMAC_Init_ex(ctx, (unsigned char *)key, len, EVP_sha256(), 0);} #define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, (unsigned char *)buf, len) #define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, (unsigned char *)dig, &dlen); #define HMAC_close(ctx) HMAC_CTX_free(ctx) #endif
4. For new OS, you will need
- X11: sudo apt install xorg-dev - ALSA: sudo apt install libpulse-dev - SDL: ./configure --enable-video-x11 --enable-x11-shared --enable-video-x11-vm --enable-alsa