Nginx-rtmp 直播媒体实时流实现

Posted 无脑仔的小明

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx-rtmp 直播媒体实时流实现相关的知识,希望对你有一定的参考价值。

这两篇博客也是跟直播流媒体相关的(2019-11-08)

 

物联网架构成长之路(41)-直播流媒体入门(RTSP篇) https://www.cnblogs.com/wunaozai/p/11772060.html
物联网架构成长之路(42)-直播流媒体入门(RTMP篇) https://www.cnblogs.com/wunaozai/p/11772392.html

 

 

0. 前言

  这段时间在搭建一个IPCamera项目服务器。视频点对点通话,客户端会查看设备端的音视频实时流。为了省流量,是通过P2P进行穿透。但是由于NAT设备的原因和IPV4的枯竭。有些设备是无法进行点对点传输实时流。所以需要进行服务器转发。这里为了快速实现原型,同时参考现在主流的流媒体协议。发现很多使用的是RTMP协议。

  下图是总体设计图,为了整合多平台,会自建RTMP流媒体服务器和使用云厂商SaaS的RTMP流媒体服务。但是由于有时候会传输一些非流媒体数据,需要传输一些二进制文件,所以会需要自定义媒体转发服务。

  以下是我实际项目中,用到的架构实现流程图。

1 1. 客户端A无法进行P2P穿透,请求业务服务器要进行转发。
2 2. 业务服务器根据客户端A,请求类型,返回对应的转发服务器地址和对应的房间号RoomID/Token等信息
3 3. 上述请求类型,可以是请求自建RTMP流媒体服务,购买于云厂商RTMP流媒体服务或者自定义协议媒体转发服务
4 4. 客户端A得到业务服务器返回的媒体服务器地址和RoomID/Token
5 5. 通过信令服务器或者MQTT服务器,把对应的媒体服务器地址和RoomID/Token告诉另一端客户端B
6 6. 客户端A和客户端B同时进入相同房间Room,客户端A进行推流,客户端B进行拉流
7 7. 其他媒体信息,如编解码格式,清晰度,播放,暂停,拍照等命令,通过上述信令或MQTT服务器进行命令控制

1. 编译nginx

  RTMP流媒体服务器,现成的开源方案有很多,有SRS,Red5,wowoza,FMS等,我这里使用的是Nginx的rtmp插件实现实时流转发。

  下载 nginx-rtmp-module  https://github.com/arut/nginx-rtmp-module

  重新编译nginx 

1 --prefix=/opt/nginx --with-stream --with-http_ssl_module --with-stream_ssl_module --with-debug --add-module=../nginx-rtmp-module

  文末提供Windows版本已经编译好的exe下载

2. 配置Nginx.conf

  基本的nginx配置,这里就不进行介绍了,需要了解的可以参考我其他博客,里面有介绍。这里只介绍rtmp段的定义。

 1 rtmp{
 2     server{
 3         listen 8081;
 4         access_log logs/rtmp_access.log;
 5         on_connect http://127.0.0.1:8080/v1/rtmp/on_connect;
 6         application rtmp {
 7             live on;
 8             notify_method get;
 9             on_play http://127.0.0.1:8080/v1/rtmp/on_play;
10             on_publish http://127.0.0.1:8080/v1/rtmp/on_publish;
11             on_done http://127.0.0.1:8080/v1/rtmp/on_done;
12             on_play_done http://127.0.0.1:8080/v1/rtmp/on_play_done;
13             on_publish_done http://127.0.0.1:8080/v1/rtmp/on_publish_done;
14             on_record_done http://127.0.0.1:8080/v1/rtmp/on_record_done;
15             on_update http://127.0.0.1:8080/v1/rtmp/on_update;
16             notify_update_timeout 10s;
17         }
18         application vod {
19             play /opt/openresty/video;
20         }
21     }
22 }

3. HTTP异步通知回调

   Nginx-rtmp-module插件实现了针对RTMP协议的一些命令做了事件通知。这里我通过一个简单的SpringBoot项目,快速搭建一个HTTP服务来接收RTMP的回调。

 1 package com.wunaozai.rtmp.notify.controller;
 2 
 3 import javax.servlet.http.HttpServletRequest;
 4 
 5 import org.springframework.web.bind.annotation.GetMapping;
 6 import org.springframework.web.bind.annotation.RequestMapping;
 7 import org.springframework.web.bind.annotation.RestController;
 8 
 9 @RestController
10 @RequestMapping(value="/v1/rtmp/")
11 public class RTMPNotifyController {
12 
13     @GetMapping(value="/on_connect")
14     public String onConnect(HttpServletRequest request){
15         debug(request, "on_connect");
16         return "on_connect";
17     }
18     @GetMapping(value="/on_play")
19     public String onPlay(HttpServletRequest request){
20         debug(request, "on_play");
21         return "on_play";
22     }
23     @GetMapping(value="/on_publish")
24     public String onPublish(HttpServletRequest request){
25         debug(request, "on_publish");
26         return "on_publish";
27     }
28     @GetMapping(value="/on_done")
29     public String onDone(HttpServletRequest request){
30         debug(request, "on_done");
31         return "on_done";
32     }
33     @GetMapping(value="/on_play_done")
34     public String onPlayDone(HttpServletRequest request){
35         debug(request, "on_play_done");
36         return "on_play_done";
37     }
38     @GetMapping(value="/on_publish_done")
39     public String onPublishDone(HttpServletRequest request){
40         debug(request, "on_publish_done");
41         return "on_publish_done";
42     }
43     @GetMapping(value="/on_record_done")
44     public String onRecordDone(HttpServletRequest request){
45         debug(request, "on_record_done");
46         return "on_record_done";
47     }
48     @GetMapping(value="/on_update")
49     public String onUpdate(HttpServletRequest request){
50         debug(request, "on_update");
51         return "on_update";
52     }
53     
54     private String debug(HttpServletRequest request, String action){
55         String str = action + ": " + request.getRequestURI() + " " + request.getQueryString();
56         System.out.println(str);
57         return str;
58     }
59 }

4. 运行效果

  (1) 启动nginx和SpringBoot

  (2) 以下是SpringBoot打印信息(各位可以简单分析一下这些日志的)

 1 on_connect: /v1/rtmp/on_connect app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&epoch=178269841&call=connect
 2 on_publish: /v1/rtmp/on_publish app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=541&call=publish&name=room&type=live
 3 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=541&call=update_publish&time=10&timestamp=3999&name=room
 4 on_done: /v1/rtmp/on_done app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=541&call=done&name=room
 5 on_publish_done: /v1/rtmp/on_publish_done app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=541&call=publish_done&name=room
 6 on_connect: /v1/rtmp/on_connect app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&epoch=178305623&call=connect
 7 on_publish: /v1/rtmp/on_publish app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=publish&name=room&type=live
 8 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=10&timestamp=7296&name=room
 9 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=20&timestamp=17248&name=room
10 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=30&timestamp=27328&name=room
11 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=40&timestamp=37280&name=room
12 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=50&timestamp=47296&name=room
13 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=60&timestamp=57312&name=room
14 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=70&timestamp=67264&name=room
15 on_connect: /v1/rtmp/on_connect app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&epoch=178380351&call=connect
16 on_play: /v1/rtmp/on_play app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=557&call=play&name=room&start=4294966296&duration=0&reset=0&pass=12345
17 on_play_done: /v1/rtmp/on_play_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=557&call=play_done&name=room&pass=12345
18 on_done: /v1/rtmp/on_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=557&call=done&name=room&pass=12345
19 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=80&timestamp=77344&name=room
20 on_connect: /v1/rtmp/on_connect app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&epoch=178388202&call=connect
21 on_play: /v1/rtmp/on_play app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=563&call=play&name=room&start=4294966296&duration=0&reset=0&pass=12345
22 on_done: /v1/rtmp/on_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=563&call=done&name=room&pass=12345
23 on_play_done: /v1/rtmp/on_play_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=563&call=play_done&name=room&pass=12345
24 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=90&timestamp=87360&name=room
25 on_connect: /v1/rtmp/on_connect app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&epoch=178396146&call=connect
26 on_play: /v1/rtmp/on_play app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=569&call=play&name=room&start=4294966296&duration=0&reset=0&pass=12345
27 on_done: /v1/rtmp/on_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=569&call=done&name=room&pass=12345
28 on_play_done: /v1/rtmp/on_play_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=569&call=play_done&name=room&pass=12345
29 on_connect: /v1/rtmp/on_connect app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&epoch=178403666&call=connect
30 on_play: /v1/rtmp/on_play app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=574&call=play&name=room&start=4294966296&duration=0&reset=0&pass=12345
31 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=100&timestamp=97311&name=room
32 on_update: /v1/rtmp/on_update app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=574&call=update_play&time=10&timestamp=105504&name=room&pass=12345
33 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=110&timestamp=107199&name=room
34 on_done: /v1/rtmp/on_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=574&call=done&name=room&pass=12345
35 on_play_done: /v1/rtmp/on_play_done app=rtmp&flashver=&swfurl=&tcurl=rtmp://rtmp.wunaozai.com:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=574&call=play_done&name=room&pass=12345
36 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=120&timestamp=117344&name=room
37 on_update: /v1/rtmp/on_update app=rtmp&flashver=FMLE/3.0%20(compatible%3B%20FMSc/1.0)&swfurl=&tcurl=rtmp://120.24.210.62:8081/rtmp&pageurl=&addr=113.74.127.195&clientid=547&call=update_publish&time=130&timestamp=122815&name=room

  (3) 客户端进行推流,这里的推流软件,我是使用这个 http://www.iavcast.com/html/ruanjian/iavcast.html 

  (4) 移动端,我使用微信小程序里的 腾讯视频云  这个小程序里面有RTMP测试

  (5) nginx-rtmp 日志

 1 113.74.127.195 [05/Aug/2018:16:18:08 +0800] PUBLISH "rtmp" "room" "" - 2646572 687 "" "FMLE/3.0 (compatible; FMSc/1.0)" (1m 46s)
 2 113.74.127.195 [05/Aug/2018:16:19:49 +0800] PLAY "rtmp" "room" "pass=12345" - 413 542 "" "" (4s)
 3 113.74.127.195 [05/Aug/2018:16:19:57 +0800] PLAY "rtmp" "room" "pass=12345" - 413 542 "" "" (4s)
 4 113.74.127.195 [05/Aug/2018:16:20:05 +0800] PLAY "rtmp" "room" "pass=12345" - 413 542 "" "" (4s)
 5 113.74.127.195 [05/Aug/2018:16:20:13 +0800] PLAY "rtmp" "room" "pass=12345" - 413 542 "" "" (4s)
 6 113.74.127.195 [05/Aug/2018:16:30:39 +0800] PLAY "rtmp" "room" "pass=12345" - 413 871 "" "" (4s)
 7 113.74.127.195 [05/Aug/2018:16:30:54 +0800] PLAY "rtmp" "room" "pass=12345" - 413 647163 "" "" (12s)
 8 113.74.127.195 [05/Aug/2018:16:31:08 +0800] PUBLISH "rtmp" "room" "" - 4961955 409 "" "FMLE/3.0 (compatible; FMSc/1.0)" (1m 30s)
 9 113.74.127.195 [05/Aug/2018:23:06:47 +0800] PUBLISH "rtmp" "room" "" - 425763 529 "" "FMLE/3.0 (compatible; FMSc/1.0)" (13s)
10 113.74.127.195 [05/Aug/2018:23:08:29 +0800] PLAY "rtmp" "room" "pass=12345" - 413 871 "" "" (4s)
11 113.74.127.195 [05/Aug/2018:23:08:37 +0800] PLAY "rtmp" "room" "pass=12345" - 413 871 "" "" (4s)
12 113.74.127.195 [05/Aug/2018:23:08:45 +0800] PLAY "rtmp" "room" "pass=12345" - 413 871 "" "" (4s)
13 113.74.127.195 [05/Aug/2018:23:09:05 +0800] PLAY "rtmp" "room" "pass=12345" - 413 926026 "" "" (17s)
14 113.74.127.195 [05/Aug/2018:23:09:30 +0800] PUBLISH "rtmp" "room" "" - 7061016 409 "" "FMLE/3.0 (compatible; FMSc/1.0)" (2m 20s)

5. RTMP鉴权方式

   一般商用的话,为了防止被其他人使用和安全性考虑,所以需要对RTMP进行鉴权处理。鉴权如果有特殊性的,可以通过修改nginx-rtmp-module的源代码,然后进行修改,其实就是增加个auth函数,这个函数可以查询数据库之类的,然后决定返回0成功还是-1表示失败。

  除了上面说到的方式,还可以通过简单的方式,就是上面提到的HTTP回调。如果HTTP回调返回的HTTP状态码是2xx的,表示成功。如果是返回5xx的状态码,那么表示失败。那样的话,服务器就是断开RTMP连接。

  就是在rtmp://rtmp.wunaozai.com/rtmp_live/room?username=username&password=password

  至于实现,这里暂时还没有,其实就是在SpringBoot项目中对每个请求,判断一下参数即可。如果后面有机会就详细写一下,关联Redis数据库,实现房间号功能。但是可能不会写了,因为实际上不难。就是整个流程跑通还是比较多代码要写的,在博客里贴太多代码有点不好。博客最主要的还是提供思路。实际实现就应该在项目中实现了。

6. 其他

  这里是一些配置说明和示例

  1 Application 创建一个RTMP应用,这里有点区别于http的location
  2 Timeout 60s 
  3 stocket超时,可以配合keepalive和ping值来实现不让服务器端长期处于监听连接客户端状态,实现快速关掉socket
  4 Ping 3m
  5 ping_timeout 30s
  6 RTMP ping用于检查活动连接的协议。发送一个特殊的包远程连接,在ping_timeout指定时间内期待一个回复,如果没有收到回复,连接断开
  7 max_streams 32
  8 设置RTMP流的最大数目,单一流数据最大限制,一般默认的32就可以了
  9 ack_window 5000000
 10 设置RTMP窗口的大小
 11 chunk_size 4096
 12 数据块大小 设置值越大CPU负载就越小
 13 max_queue
 14 最大队列数,一般默认即可
 15 max_message 1M
 16 输入数据消息的最大大小。所有输入数据消息都会保存在内存中,等待完成流媒体转发。在理论上传入的消息可以是非常大,对服务器稳定性影响较大,所以一般默认即可。
 17 out_queue
 18 out_cork
 19 Buflen 5s
 20 设置默认缓冲区长度。通常客户端发送播放前RTMP set_buflen命令并重置该设置
 21 
 22 访问控制
 23 Access
 24 Allow/deny
 25 允许来自指定地址或者所有地址发布/播放
 26 Allow public 127.0.0.1
 27 Deny publish all;
 28 Allow play 192.168.0.0/24
 29 Deny play all;
 30 
 31 Exec命令
 32 Exce 
 33 exec_options on;
 34 启动一些exec指令选项,通过一些exec事件来干预整个RTMP流
 35 可以仔细一些外部编解码功能
 36 Exec ffmpeg -i rtmp://localhost?src/$name -vcodec libx264 -vprofile baseline -g 10 -s 300x200 -acodec libfaac -ar 44100 -ac 1 -f flv rtmp://localhost/hls/$name 2>> /var/log/ffmpeg-$name.log;
 37 Exce_statc 
 38 类似exce,属于静态命令,不支持传递上下文参数
 39 Exec_kill_signal term;
 40 Exec_kill_signal user1;
 41 Exec_kill_signal 3;
 42 Exec_pull 
 43 Exec_push
 44 Exec_publish
 45 指定与参数外部命令要在发布事件执行。
 46 Exec_play
 47 指定与要在打开事件执行外部命令
 48 Exec_play_done
 49 指定要在打开完成事件执行外部命令
 50 Exec_publish_done
 51 Exec_record_done
 52 例子
 53 exec_play bash -c “echo $addr $pageurl >> /tmp/clients”
 54 Exec_publish base -c “echo $addr $flashver >> /tmp/publishers”
 55 转录
 56 Exec_record_done ffmpeg -y -i $path -acodec libmp31ame -ar 44100 -ac 1 -vcodec libx264 $dirname/$basename.mp4
 57 
 58 Live 模式
 59 Live on
 60 切换直播模式,即一对多广播
 61 Meta on/copy/off
 62 奇幻发送元数据到客户端 默认on
 63 Interleave on/off
 64 切换交叉模式。在该模式下,音视频会在同一个RTMPchunk流中传输。默认为off
 65 wait_key on|off
 66 使视频流从一个关键帧开始,默认为off
 67 wait_video on|off
 68 在一个视频帧发送前禁用音频。默认off
 69 通过wait_key/wait_video进行组合以使客户端可以收到具有所有其他数据的视频关键帧。但这样会增加连接延迟。不过可以通过编解码器中调整关键帧间隔来减少延迟。
 70 Publish_notify on
 71 发送NetStream.Publish.Start和NetStream.Publish.Stop给用户,默认off
 72 Drop_idle_publisher 10s
 73 终止指定时间内闲置(没有音频、视频)的发布连接,默认为off。注意这个仅仅对于发布模式的连接起作用(发送publish命令之后)
 74 Sync 10ms
 75 同步音视频流。如果用户带宽不足以接收发布率,服务器会丢弃一些帧。这将导致同步问题。当时间戳差超过sync指定值,将会发送一个绝对帧来解决这个问题,默认为300ms
 76 Play_restart off
 77 使nginx-rtmp能够在发布启动或者停止时发送NetStream.Play.Start 和 NetStrem.Play.Stop到每个用户。如果关闭的话,那么每个用户就只能在回放的开始结束时收到该通知了。默认为on
 78 
以上是关于Nginx-rtmp 直播媒体实时流实现的主要内容,如果未能解决你的问题,请参考以下文章

简易视频直播系统的搭建实践

Azure 媒体服务实时直播

Nginx-rtmp直播之业务流程分析

Android/iOS:通过流混合改善实时流媒体体验

Android/iOS:通过流混合改善实时流媒体体验

将 FMS RTMP 直播流转换为 BlackBerry 的 RTSP