Nginx-rtmp配合FFmpeg实现HLS服务

Nginx-rtmp配合FFmpeg实现HLS服务

一、前言

  1. 环境说明

    操作系统:Windows 7 Ultimate

    FFmpeg 版本:ffmpeg20200809

    Nginx 版本: 1.14.1

    Nginx-Rtmp-Module 版本: 1.2.1

  2. 组件简介

  • 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 配置

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//liveC://m3u8//show ,文件夹可位置自行修改

    1. 配置文件中 分为 rtmp 段和 http 段

    2. rtmp 段提供给 FFmpeg 进行推流,端口是 1935,地址分为 livetvfile ,视频缓存地址是 C://m3u8//liveC://m3u8//show

      URL:rtmp://127.0.0.1:1935/livetv/[文件名]rtmp://127.0.0.1:1935/file/[文件名]

    3. http 段提供给播放器连接,端口是 8080,地址分为 liveshow ,文件根目录指向 C://m3u8

      URL:http://192.168.10.171:3004/live/[文件名].m3u8http://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 播放器

  • 西瓜播放器

代码生成:https://v2.h5player.bytedance.com/generate/

<!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 命令

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趴着喝可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值