文章目录
Nginx-rtmp配合FFmpeg实现HLS服务
一、前言
-
环境说明
操作系统:Windows 7 Ultimate
FFmpeg 版本:ffmpeg20200809
Nginx 版本: 1.14.1
Nginx-Rtmp-Module 版本: 1.2.1
-
组件简介
- nginx-rtmp: 指带有 rtmp 模块的 nginx
- FFmpeg: 用于记录,转换和流传输音频和视频
- rtmp 协议: RTMP(Real Time Messaging Protocol)实时消息传送协议是 Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输 开发的开放协议
- HLS: Apple的动态码率自适应技术。主要用于PC和Apple终端的音视频服务。包括一个m3u(8)的索引文件,TS媒体分片文件和key加密串文件
- m3u8 文件格式: Unicode 版本的M3U,用 UTF-8 编码。"M3U"和"M3U8"文件都是苹果公司使用的 HTTP Live Streaming 格式的基础,这种格式可以在 iPhone 和 Macbook等设备播放
- OBS: 免费且开源的用于视频录制以及直播串流的软件
- PotPlayer: 多种格式的强大媒体播放器
nginx-rtmp-win32 下载:https://github.com/illuspas/nginx-rtmp-win32/tree/master
FFmpeg 官网:https://ffmpeg.org/
nginx 官网:http://nginx.org/
nginx-rtmp-module:https://github.com/arut/nginx-rtmp-module
HLS:https://baike.baidu.com/item/HLS/8328931?fr=aladdin
西瓜播放器:https://v2.h5player.bytedance.com/gettingStarted/
PotPlayer:https://potplayer.en.softonic.com/
OBS:https://obsproject.com/zh-cn/download
rtmp 维基百科:https://zh.wikipedia.org/wiki/%E5%AE%9E%E6%97%B6%E6%B6%88%E6%81%AF%E5%8D%8F%E8%AE%AE
M3U 维基百科:https://zh.wikipedia.org/wiki/M3U
java + FFmpeg:https://blog.csdn.net/u011424614/article/details/108006131
二、正文
场景说明
- 从右到左,FFmpeg 将 rtmp 服务和本地文件推流到 nginx-rtmp 进行代理 ;将 rtmp 服务转换为 HLS 服务
- 为什么转换?因为 rtmp 服务需要 Flash Player 才能播放,一般的浏览器已经不再支持 Flash,所以无法对 rtmp 的服务进行播放。而苹果公司的设备从很久之前就不支持 Flash 了,并提出了 HLS 服务进行中转
nginx-rtmp 配置
-
下载已添加好 rtmp 模块的 nginx :https://github.com/illuspas/nginx-rtmp-win32/tree/master
-
修改配置后,启动 nginx
-
nginx.conf
worker_processes auto;
events {
worker_connections 1024;
}
# RTMP configuration
rtmp {
server {
listen 1935; # Listen on standard RTMP port
chunk_size 4000;
application livetv {
live on;
# Turn on HLS
hls on;
hls_path C://m3u8//live;
hls_fragment 3;
hls_playlist_length 60;
# disable consuming the stream from nginx as rtmp
deny play all;
}
application file {
live on;
# Turn on HLS
hls on;
hls_path C://m3u8//show;
hls_fragment 3;
hls_playlist_length 60;
# disable consuming the stream from nginx as rtmp
deny play all;
}
}
}
http {
sendfile off;
tcp_nopush on;
# aio on;
directio 512;
default_type application/octet-stream;
server {
listen 8080;
location /live {
# Disable cache
add_header Cache-Control no-cache;
# CORS setup
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
# allow CORS preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root E://m3u8;
}
location /show {
# Disable cache
add_header Cache-Control no-cache;
# CORS setup
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
# allow CORS preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root E://m3u8;
}
}
}
-
说明:请先创建文件夹
C://m3u8//live
和C://m3u8//show
,文件夹可位置自行修改-
配置文件中 分为 rtmp 段和 http 段
-
rtmp 段提供给 FFmpeg 进行推流,端口是 1935,地址分为
livetv
和file
,视频缓存地址是C://m3u8//live
和C://m3u8//show
URL:
rtmp://127.0.0.1:1935/livetv/[文件名]
和rtmp://127.0.0.1:1935/file/[文件名]
-
http 段提供给播放器连接,端口是 8080,地址分为
live
和show
,文件根目录指向C://m3u8
URL:
http://192.168.10.171:3004/live/[文件名].m3u8
和http://192.168.10.171:3004/show/[文件名].m3u8
,其中 live 和 show 对应 rtmp 段的 live 文件夹和 show 文件夹
-
FFmepg 推流
-
官网下载 FFmepg 最新版,解压
-
将 bin 目录配置到环境变量 path 中,方便执行命令(Windows 环境)
-
将 rtmp 服务推流到 nginx- rtmp
> ffmpeg -re -i rtmp://58.200.131.2:1935/livetv/hunantv -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -f flv rtmp://127.0.0.1:1935/livetv/stream
- 将本地视频推流到 nginx- rtmp
> ffmpeg -re -i C://show.flv -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -f flv rtmp://127.0.0.1:1935/file/stream
备注:视频缓存文件(.ts)会自动删除;如果需要保存,FFmpeg 支持录制功能
前端 web 播放器
- 西瓜播放器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui">
<meta name="referrer" content="no-referrer">
<title>xgplayer</title>
<style type="text/css">
html, body {width:100%;height:100%;margin:auto;overflow: hidden;}
</style>
</head>
<body>
<div id="mse"></div>
<script src="//cdn.jsdelivr.net/npm/xgplayer@1.1.4/browser/index.js" charset="utf-8"></script>
<script src="//cdn.jsdelivr.net/npm/xgplayer-hls.js/browser/index.js" charset="utf-8"></script><script>
let player = new HlsJsPlayer({
"id": "mse",
"url": "http://127.0.0.1:8080/live/stream.m3u8",
"playsinline": true,
"whitelist": [
""
],
"autoplay": true
});
</script>
</body>
</html>
- video.js
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>直播</title>
<link href="https://cdn.bootcss.com/video.js/7.6.5/alt/video-js-cdn.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/video.js/6.6.2/video.js"></script>
<script src="https://cdn.bootcss.com/videojs-contrib-hls/5.15.0/videojs-contrib-hls.min.js"></script>
</head>
<body>
<video id="liveVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="500" height="300" data-setup='{}'>
<source id="source" src="http://127.0.0.1:8080/live/stream.m3u8" type="application/x-mpegURL">
</video>
</body>
<script>
var liveVideo = videojs('liveVideo',{
bigPlayButton : true,
textTrackDisplay : false,
posterImage: false,
errorDisplay : false,
})
</script>
</html>
三、其它
1.直播服务
- 可通过 PotPlayer 播放器进行播放
PotPlayer 下载:https://potplayer.en.softonic.com/
名称 | 服务网址 |
---|---|
湖南卫视 | rtmp://58.200.131.2:1935/livetv/hunantv |
CCTV1 高清 | http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8 |
CCTV5 高清(体育) | http://ivi.bupt.edu.cn/hls/cctv5hd.m3u8 |
CCTV6 高清(电影) | http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8 |
2.检测网络状态脚本
- 运行 FFmpeg 推流脚本( live_streaming_startup_v2.bat
使用 ANSI 编码
)
@echo off
:: 最小化窗口
%1(start /min cmd.exe /c %0 :& exit )
:: 设置标题
title live_streaming_v2
:: 启动推流服务
ffmpeg -re -i "rtmp://58.200.131.2:1935/livetv/hunantv" -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -f flv rtmp://127.0.0.1:1935/show/stream
:: 自动关闭窗口
exit
- 检测网络并检测文件 ( check_network_v2.bat
使用 ANSI 编码
)
window_title
值 与live_streaming_startup_v2.bat
里的title
值要一致
file_path
值为 nginx-rtmp 配置的文件路径
@echo off
:: 最小化窗口
:: %1(start /min cmd.exe /c %0 :& exit )
::==========================================
::======= 网络设置 =========================
::==========================================
:: ping 地址
set ping_address=www.baidu.com
:: 频率:1秒钟一次
set test_frequency=30
:: 启动的服务
set service_name=live_streaming_startup_v2.bat
:: 推流窗口标题
set window_title=live_streaming_v2
::==========================================
::======= 文件设置 =========================
::==========================================
:: 文件路径
set file_path=C:/m3u8//live
:: 文件数阀值
set m3u8_file_threshold=1
set ts_file_threshold=5
::【网络检测】
:check
ping -n 2 %ping_address%
:: 网络连接失败,循环检测
IF ERRORLEVEL 1 goto check
:: 网络连接成功,开始检查文件
IF ERRORLEVEL 0 goto checkFile
pause > nul
:: 【检查文件】
:checkFile
echo file checking...
:: 检测前,初始化文件数
set m3u8_index=0
set ts_index=0
:: 循环指定后缀的文件
for %%i in (%file_path%\*.m3u8) do (
:: 输出全路径
:: echo %%i
set /a m3u8_index=m3u8_index+1
)
:: 循环指定后缀的文件
for %%i in (%file_path%\*.ts) do (
:: 输出全路径
:: echo %%i
set /a ts_index=ts_index+1
)
:: 判断 m3u8 是否到达阀值
if %m3u8_index% lss %m3u8_file_threshold% (
:: echo %m3u8_file_threshold%
echo camera live streaming startup [m3u8] ...
:: 小于阀值,启动推流服务
:: 关闭之前的窗口
start taskkill /f /t /fi "imagename eq cmd.exe" /fi "windowtitle eq 管理员: %window_title%"
:: 启动服务
start %service_name%
) else (
echo The number of m3u8 is: %m3u8_index%
:: :: 判断 ts 是否到达阀值
if %ts_index% lss %ts_file_threshold% (
:: echo %ts_file_threshold%
echo camera live streaming startup [ts] ...
:: 小于阀值,启动推流服务
:: 关闭之前的窗口
start taskkill /f /t /fi "imagename eq cmd.exe" /fi "windowtitle eq 管理员: %window_title%"
:: 启动服务
start %service_name%
) else (
echo The number of ts is: %ts_index%
)
)
goto continuousTesting
pause > nul
::【持续检测文件】
:continuousTesting
ping -n %test_frequency% %ping_address%
IF ERRORLEVEL 1 goto check
IF ERRORLEVEL 0 goto checkFile
pause > nul
- 【旧版】检测网络状态 ( check_network_v1.bat )
@echo off
:: 测试连接的目标网站
set ping_address=www.baidu.com
:: 持续测试网络的次数,会影响日志输出频率
set test_frequency=10
:: 启动的服务
set service_name=live_streaming_startup_v2.bat
:: 日志文件
set log_file_path=C:\check_network_log.txt
:: 最小化窗口
:: %1(start /min cmd.exe /c %0 :& exit )
::【网络检测】
:check
ping -n 2 %ping_address%
IF ERRORLEVEL 1 goto check
IF ERRORLEVEL 0 goto startUp
pause > nul
::【网络正常,启动服务】
:startUp
echo camera live streaming startup...
:: 启动推流服务
start %service_name%
:: 继续网络检测
goto continuousTesting
pause>nul
::【持续检测网络,并输入日志】
:continuousTesting
ping -n %test_frequency% %ping_address%
IF ERRORLEVEL 1 (echo %date% %time% network anomaly >> %log_file_path%) && goto check
IF ERRORLEVEL 0 (echo %date% %time% network normal >> %log_file_path%) && goto continuousTesting
pause>nul
4.分段录制
- 将 rtmp 协议的直播流视频,按 600 秒一个视频分段输出
ffmpeg -i rtmp://58.200.131.2:1935/livetv/hunantv -c copy -f segment -segment_time 600 -reset_timestamps 1 C:\output\hunantv_%08d.flv
5.另一种本地视频推流
- 使用 OBS 软件进行推流
OBS 官网:https://obsproject.com/zh-cn
6.CPU占用率过高
注意输出的 FPS 数值,会影响画质和流畅度
- 解决方法一:ffmpeg 设置解码线程数和编码线程数
ffmpeg -threads 2 -re -i "rtmp://58.200.131.2:1935/livetv/hunantv" -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -threads 1 -f flv rtmp://127.0.0.1:1935/show/stream
- 解决方法二:Windows 操作系统控制
start 命令说明:https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/start
start /WAIT /affinity 0x1 ffmpeg -threads 2 -re -i "rtmp://58.200.131.2:1935/livetv/hunantv" -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -threads 1 -f flv rtmp://127.0.0.1:1935/show/stream
- 对应 4 核CPU
命令行 | 说明 |
---|---|
start /WAIT /affinity 0x1 ffmpeg | 只使用第一个CPU |
start /WAIT /affinity 0x2 ffmpeg | 只使用第二个CPU |
start /WAIT /affinity 0x4 ffmpeg | 只使用第三个CPU |
start /WAIT /affinity 0x8 ffmpeg | 只使用第四个CPU |
start /WAIT /affinity 0x3 ffmpeg | 只使用第1,2个CPU |
start /WAIT /affinity 0x7 ffmpeg | 只使用第1,2,3个CPU |
tart /WAIT /affinity 0xf ffmpeg | 只使用第1,2,3,4个CPU |
7.待解决问题
nginx-rtmp 的 nginx.conf 未测试成功的参数
-
pull:直接写入 rtmp rul
-
exec:直接执行 ffmpeg 命令