Android RTMP直播(续)

/

软硬件环境

  • ubuntu 16.04
  • Android Studio 2.1.3
  • OTT BOx with android 5.1.1
  • nginx 1.11.3
  • nginx-rtmp-module
  • VLC

前言

之前的一篇博文http://www.xugaoxiang.com/blog/index.php/archives/66/已经简单的介绍了如何利用nginx、nginx-rtmp-module和ffmpeg实现基于rtmp协议的直播.今天这篇继续直播这个话题,聊聊hls的应用.

HLS

HLS(Http Live Streaming)是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。

m3u8文件
  1. #EXTM3U
  2. #EXT-X-VERSION:3
  3. #EXT-X-MEDIA-SEQUENCE:6119
  4. #EXT-X-TARGETDURATION:14
  5. #EXTINF:10.625,
  6. 6119.ts
  7. #EXTINF:13.667,
  8. 6120.ts
  9. #EXTINF:10.000,
  10. 6121.ts

如上,m3u8文件是一个描述文件,必须以#EXTM3U开头,之后是切片TS文件的序列.对于直播来讲,m3u8文件需要进行实时的更新,只保留若干个TS切片序列,防止本地存储撑爆硬盘.

多码率支持

针对应用网络多变及不稳定的情况,多数直播都会提供多码率支持,播放器会根据用户当前的网络状况,自动切换到对应的码率上,大大提升用户体验.在服务器端.为了提供多码率的支持,就需要多级m3u8文件.在主m3u8文件不再有TS序列,而是二级m3u8文件,如下所示

  1. #EXTM3U
  2. #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000
  3. low.m3u8
  4. #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000
  5. mid.m3u8
  6. #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000
  7. hi.m3u8

nginx-rtmp对HLS的支持

nginx-rtmp-module本身对rtmp和hls都有很好的支持,只需要在nginx.conf配置下就ok了

  1. #user nobody;
  2. worker_processes auto;
  3. rtmp_auto_push on;
  4. error_log logs/error.log;
  5. error_log logs/error.log notice;
  6. error_log logs/error.log info;
  7. #pid logs/nginx.pid;
  8. events {
  9. worker_connections 1024;
  10. }
  11. rtmp {
  12. server {
  13. listen 1935;
  14. chunk_size 4000;
  15. # TV mode: one publisher, many subscribers
  16. #application mytv {
  17. # enable live streaming
  18. #live on;
  19. # record first 1K of stream
  20. #record all;
  21. #record_path /tmp/av;
  22. #record_max_size 1K;
  23. # append current timestamp to each flv
  24. #record_unique on;
  25. # publish only from localhost
  26. #allow publish 127.0.0.1;
  27. #deny publish all;
  28. #allow play all;
  29. #}
  30. # Transcoding (ffmpeg needed)
  31. #application big {
  32. # live on;
  33. # On every pusblished stream run this command (ffmpeg)
  34. # with substitutions: $app/${app}, $name/${name} for application & stream name.
  35. #
  36. # This ffmpeg call receives stream from this application &
  37. # reduces the resolution down to 32x32. The stream is the published to
  38. # 'small' application (see below) under the same name.
  39. #
  40. # ffmpeg can do anything with the stream like video/audio
  41. # transcoding, resizing, altering container/codec params etc
  42. #
  43. # Multiple exec lines can be specified.
  44. # exec ffmpeg -re -i rtmp://localhost:1935/$app/$name -vcodec flv -acodec copy -s 32x32
  45. #-f flv rtmp://localhost:1935/small/${name};
  46. #}
  47. #application small {
  48. # live on;
  49. # # Video with reduced resolution comes here from ffmpeg
  50. #}
  51. #application webcam {
  52. # live on;
  53. # Stream from local webcam
  54. # exec_static ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an
  55. #-f flv rtmp://localhost:1935/webcam/mystream;
  56. #}
  57. # application mypush {
  58. # live on;
  59. # Every stream published here
  60. # is automatically pushed to
  61. # these two machines
  62. #push rtmp1.example.com;
  63. #push rtmp2.example.com:1934;
  64. # }
  65. # application mypull {
  66. # live on;
  67. # Pull all streams from remote machine
  68. # and play locally
  69. #pull rtmp://rtmp3.example.com pageUrl=www.example.com/index.html;
  70. # }
  71. # application mystaticpull {
  72. # live on;
  73. # Static pull is started at nginx start
  74. #pull rtmp://rtmp4.example.com pageUrl=www.example.com/index.html name=mystream static;
  75. # }
  76. # video on demand
  77. # application vod {
  78. # play /opt/www/vod;
  79. # }
  80. # application vod2 {
  81. # play /var/mp4s;
  82. # }
  83. # Many publishers, many subscribers
  84. # no checks, no recording
  85. #application videochat {
  86. # live on;
  87. # The following notifications receive all
  88. # the session variables as well as
  89. # particular call arguments in HTTP POST
  90. # request
  91. # Make HTTP request & use HTTP retcode
  92. # to decide whether to allow publishing
  93. # from this connection or not
  94. # on_publish http://localhost:8080/publish;
  95. # Same with playing
  96. # on_play http://localhost:8080/play;
  97. # Publish/play end (repeats on disconnect)
  98. # on_done http://localhost:8080/done;
  99. # All above mentioned notifications receive
  100. # standard connect() arguments as well as
  101. # play/publish ones. If any arguments are sent
  102. # with GET-style syntax to play & publish
  103. # these are also included.
  104. # Example URL:
  105. # rtmp://localhost/myapp/mystream?a=b&c=d
  106. # record 10 video keyframes (no audio) every 2 minutes
  107. # record keyframes;
  108. # record_path /tmp/vc;
  109. # record_max_frames 10;
  110. # record_interval 2m;
  111. # Async notify about an flv recorded
  112. # on_record_done http://localhost:8080/record_done;
  113. #}
  114. # HLS
  115. # For HLS to work please create a directory in tmpfs (/tmp/hls here)
  116. # for the fragments. The directory contents is served via HTTP (see
  117. # http{} section in config)
  118. #
  119. # Incoming stream must be in H264/AAC. For iPhones use baseline H264
  120. # profile (see ffmpeg example).
  121. # This example creates RTMP stream from movie ready for HLS:
  122. #
  123. # ffmpeg -loglevel verbose -re -i movie.avi -vcodec libx264
  124. # -vprofile baseline -acodec libmp3lame -ar 44100 -ac 1
  125. # -f flv rtmp://localhost:1935/hls/movie
  126. #
  127. # If you need to transcode live stream use 'exec' feature.
  128. #
  129. application hls {
  130. live on;
  131. hls on;
  132. hls_path /opt/www/live;
  133. }
  134. # MPEG-DASH is similar to HLS
  135. #application dash {
  136. # live on;
  137. # dash on;
  138. # dash_path /tmp/dash;
  139. #}
  140. }
  141. }
  142. # HTTP can be used for accessing RTMP stats
  143. http {
  144. server {
  145. listen 8081;
  146. location / {
  147. root /opt/www/;
  148. }
  149. # This URL provides RTMP statistics in XML
  150. location /stat {
  151. rtmp_stat all;
  152. # Use this stylesheet to view XML as web page
  153. # in browser
  154. rtmp_stat_stylesheet stat.xsl;
  155. }
  156. location /stat.xsl {
  157. # XML stylesheet to view RTMP stats.
  158. # Copy stat.xsl wherever you want
  159. # and put the full directory path here
  160. root /home/djstava/Workshop/Web/nginx-rtmp-module/;
  161. }
  162. location /hls {
  163. # Serve HLS fragments
  164. types {
  165. application/vnd.apple.mpegurl m3u8;
  166. video/mp2t ts;
  167. }
  168. root /opt/www/;
  169. add_header Cache-Control no-cache;
  170. }
  171. #location /dash {
  172. # Serve DASH fragments
  173. # root /tmp;
  174. # add_header Cache-Control no-cache;
  175. #}
  176. }
  177. }

在rtmp标签下,指定hls application的根路径/opt/www/live,所有的TS切片文件都存放在这里

ffmpeg推流

推送本地文件
  1. ffmpeg -re -i /opt/www/vod/dhxy1.mp4 -vcodec copy -acodec copy -f flv -y rtmp://192.168.1.88/hls/livestream1

推送成功后,你可以通过如下2个url播放对应的模拟实时流,请确保nginx服务已启动.

  1. rtmp://192.168.1.88/hls/livestream1
  2. http://192.168.1.88:8081/live/livestream1.m3u8

另外http://192.168.1.88:8081/stat页面可以显示当前服务的一些信息,如接入的客户端数量,音频 视频的信息等等,见下图

nginx_stat

推送UDP组播数据
  1. ffmpeg -i udp://@224.0.0.2:9000 -vcodec libx264 -acodec aac -strict -2 -f flv -s 1280x720 -q 10 -ac 1 -ar 44100 rtmp://192.168.1.88/hls/livestream

nginx_udp

在以UDP数据为输入源时,ffmpeg会报如下图中的错误信息

nginx_udp_error

这时只需要重新修改下ffmpeg的推流命令就可以,如下

  1. ffmpeg -i 'udp://@224.0.0.2:9000?fifo_size=2000000&overrun_nonfatal=1' -vcodec libx264 -acodec aac -strict -2 -f flv -s 1280x720 -q 10 -ac 1 -ar 44100 rtmp://192.168.1.88/hls/livestream

fifo_size的单位是字节,自己酌情增减.

参考文献

1 https://developer.apple.com/streaming/

2 https://github.com/arut/nginx-rtmp-module

转载请注明作者和出处,并添加本页链接。
原文链接:http://xugaoxiang.com/post/95

给我留言