这是两种常用的音视频推流协议,这里简单比较一下两种协议应用场景(本文适合Java、Android开发者)。
参考:
一、RTMP
Real Time Messaging Protocol(实时消息传输协议)是 Adobe 的私有协议,设计用来进行实时数据通信的网络协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。
基本架构:采集端rtmp-client
-> web服务器rtmp-server
-> 播放端rtmp-client
特点:
RTMP特性
- 延迟较大
- 传输效率相对较低
- 底层采用TCP,网络环境较差下,采用RTMP保证了视频的传输质量
- 浏览器支持
- 一般需要一个流服务器中转
应用场景
- 网络直播(如斗鱼等平台)
二、RTSP
Real Time Streaming Protocol(实时流媒体协议)在网络环境比较稳定的情况下,传输效率是比较高,虽然实时性比较好,用在互联网上可能会丢包。网络摄像头常采用RTSP协议,比如海康的摄像头。
RTSP只是一个实时流媒体协议(应用层文本协议,类HTTP),RTSP只负责会话,如建立连接、播放暂停控制等。而RTP协议(实时传输协议)负载传输音视频数据,RTP又分为 rtp over tcp
和 rtp over udp
,【RFC3984中文版】、【RTP/RTCP协议与RTSP协议】。
一般的cs架构如下:
- 直播:
采集端rtps-client
->web服务器rtsp-server
->播放端rtsp-client
- 点播:
web服务器rtsp-server
->播放端rtsp-client
- 监控:
采集端rtsp-server
->播放端rtsp-client
RTSP特性
通常说的RTSP包括RTSP协议、RTP协议、RTCP协议
- RTSP协议:负责服务器与客户端之间的请求与响应
- RTP协议:负责传输媒体数据
- RTCP协议:在RTP传输过程中提供传输信息
来自RTSP协议讲解
特点:
- 实时性比较好
- 传输效率是比较高
- 底层采用RTP传输,RTP大多数采用UDP(也可以TCP),网络复杂环境下容易丢包
- 浏览器不支持
应用场景
- 网络摄像头、安防监控(如海康摄像头)
- IPTV
三、开源软件
Ⅰ、推流端
- 【rtmp-rtsp-stream-client-java】
纯Java编写的RTSP和RTMP推流Client(推荐学习其源码),直接封装Android的Camera层,非常容易使用,支持Camera1和Camera2 API。 - 【yasea】 Android RTMP 推流 Client,它将摄像头YUV和麦克风PCM数据编码到H.264/AAC中,封装在FLV中。 依赖C库:libx264、libyuv、libenc
- 【JavaCV推流】
JavaCV这个项目底层调用的ffmpeg,所以RTMP和RTSP都支持。 - OBS
PC桌面RTMP推流开源软件,现在网红主播用的主流软件(跨平台)。
Ⅱ、服务端
- 【nginx-rtmp-module】
国人写的项目,仅支持rtmp,目前(20200708) start 9.7K ,它nginx的一个插件,需要自己编译一次nginx。 - 【srs】
国人写的这是C++项目,目前(20200708) start 8.9K ,项目介绍 ,支持RTMP/HLS/WebRTC/SRT/GB28181。新版本貌似RTSP也支持了? - EasyDarwin
国内公司写的Go项目,目前(20200708) start 4.1K ,高性能开源RTSP流媒体服务器,RTSP推模式转发、RTSP拉模式转发、录像、检索、回放、关键帧缓存、秒开画面、RESTful接口、WEB后台管理、分布式负载均衡。 - 【AndroidShow】
国人写的Android App项目,通过MediaProjectionManager采集Android屏幕视频流,手机采集端做rtsp server
,通过rtp over udp
传输视频流,但还没有实现音频,具体看作者的博客:【Android录屏直播】注:传输用的【spydroid-ipcamera】代码
- 【spydroid-ipcamera】
这是法国人写的Android App项目,很久远的项目了,第一次提交是2013年,它可以将您手机变成网络摄像头(提供RTSP Server),项目不再维护,但是作者将这个项目独立为一个Java库:【libstreaming】。 - 【libstreaming】
从【spydroid-ipcamera】独立出来的 Android Java库,目前(20200708) start 2.9K 。 - live555
c++编写的项目,RTSP点播服务器,不支持推/拉流转发。【Live555 搭建流媒体服务器】 - 【RTSP-Client-Server】
国外的Java Swing项目,目前(20200708) start 376 ,源码很少和简单(项目没有用IDE创建,用命令行编译),可读性强,运行效果是client点播server的Mjpeg文件,不依赖第三方。 - 【rtsp-netty-server 】
国人写的Java项目(Elicpse),目前(20200708) start 1 。 RTP数据部分依赖【libjitsi】的RawPacket类。注:【libjitsi】 实时音频/视频通信的高级Java媒体库,没有在mvnrepository发布,编译很麻烦,jitsi是做视频会议全套软件的。
- 【monibuca】国内公司写的Go项目,目前(20200721) start 209 ,Monibuca 引擎 + 插件 = 定制化流媒体服务器。官网,这是一个新的项目,看commit记录,是2020年提交的项目。
Ⅲ、播放端和拉流
- VLC
- ffplay
- ijkplayer
- JavaCV库拉流(底层调用的ffmpeg)
- 【code.google.com/p/rtsplib-java】这是一个纯Java实现的 RTSPClient 远古时代的库(Eclipse),只实现了RTSP部分的协议(PLAY等方法),可以基于它实现扩展其他方法。
- 【srysduedu123/rtsp-h264-client】 基于
rtsplib-java
,加了解析RTP和H264 。 - 【htwahzs/Rtsp-Android-Client】 不依赖其他库,纯java实现RTSP、RTP、RTCP和硬解码渲染,经测试能正常播放,出图速度比ijkpaler快 。但本身这个仓库只有纯Java类(完整),不是一个完整的Android项目,我fork了此项目,做成一个Demo【kevinvane/Rtsp-Android-Client】。
四、利用开源软件搭建一套直播测试平台
- rtsp-client推流: ffmpeg 推流 或者 rtmp-rtsp-stream-client-java (Android,集成到自己项目中推荐使用)
- rtsp-server:ffmpeg的ffserver 或者 EasyDarwin (EasyDarwin rtsp端口554,web管理后台端口10008)
- rtsp-play: ffmpeg的ffplay 、VCL或者 ijkplayer(移动端,集成到自己项目中推荐使用)
注:EasyDarwin有提供各个平台的软件,除了服务端好用,其他觉得有点难用,不推荐。
五、流视频录制并存储方案
JavaCV从流服务器拉取音视频录制
底层是调用的是ffmpeg拉流存储EasyDarwin的方案
EasyDarwin自带录制功能,对外提供 RESTFUL API 详细文章 -> 【EasyDarwinGo录像功能发布】
底层也是调用的是ffmpeg拉流存储的方案,这是它默认配置文件: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[rtsp]
port=554
; rtsp 超时时间,包括RTSP建立连接与数据收发。
timeout=28800
; 是否使能gop cache。如果使能,服务器会缓存最后一个I帧以及其后的非I帧,以提高播放速度。但是可能在高并发的情况下带来内存压力。
gop_cache_enable=1
; 是否使能向服务器推流或者从服务器播放时验证用户名密码. [注意] 因为服务器端并不保存明文密码,所以推送或者播放时,客户端应该输入密码的md5后的值。
; password should be the hex of md5(original password)
authorization_enable=0
; 是否使能推送的同事进行本地存储,使能后则可以进行录像查询与回放。
save_stream_to_local=0
;easydarwin使用ffmpeg工具来进行存储。这里表示ffmpeg的可执行程序的路径
ffmpeg_path=/Users/ze/Downloads/ffmpeg-20180719-9cb3d8f-macos64-shared/bin/ffmpeg
;本地存储所将要保存的根目录。如果不存在,程序会尝试创建该目录。
m3u8_dir_path=/Users/ze/Downloads/EasyDarwinGoM3u8
;切片文件时长。本地存储时,将以该时间段为标准来生成ts文件(该时间+一个I帧间隔),单位秒。
;如果需要直播,这个值设小点,但是这样会产生很多ts文件;如果不需要直播,只要存储的话,可设大些。
ts_duration_second=6
;key为拉流时的自定义路径,value为ffmpeg转码格式,比如可设置为-c:v copy -c:a copy,表示copy源格式;default表示使用ffmpeg内置的输出格式,会进行转码。