ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)

1 简介

本文旨在在Windows 7系统上实现利用FFmpeg软件推流到部署的带RTMP模块的Nginx流媒体服务器上,在拉流端,基于VLC库的VLC-QT库实现拉流播放。

2 ffmpeg下载安装配置

ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序,可以轻易实现多种视频格式之间的相互转换。作为开源免费软件,通过其官网可以下载。地址:https://ffmpeg.org/。对应GitHub地址:https://github.com/FFmpeg/FFmpeg。本应用中采用下载官方提供的库,无需使用GitHub提供的源码自己编译。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第1张图片
点击“Download”,在跳转的下载页面,点击Win10图标,选择“Windows builds from gyan.dev”(下面一个链接是GitHub对应页面)。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第2张图片
在跳转到页面中,可以下载essential和full版本,essential就是简版,只包含ffmpeg.exe、ffplay.exe、ffprobe.exe, 而full版本就包含了动态库和相关头文件,方便我们在开发中调用。点击“full-release-full-shared.7z”,下载。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第3张图片
解压后目录如下:
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第4张图片
将bin目录的全路径添加到环境变量PATH。
cmd命令行到bin目录下(如已添加到PATH环境变量则无需),输入ffmpeg –version。出现下图则成功。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第5张图片
bin目录下文件:
可执行文件:

  • ffmpeg.exe:音视频转码、转换器;
  • ffplay.exe:简单的音视频播放器;
  • ffprobe.exe:简单的多媒体码流分析器。

SDK动态库:

  • libavcodec:包含音视频编码器和解码器;
  • libavutil:包含多媒体应用常用的简化编程的工具,如随机数生成器、数据结构、数学函数等功能;
  • libavformat:包含多种多媒体容器格式的封装、解封装工具;
  • libavfilter:包含多媒体处理常用的滤镜功能;
  • libavdevice:用于音视频数据采集和渲染等功能的设备相关;
  • libswscale:用于图像缩放和色彩空间和像素格式转换功能;
  • libswresample:用于音频重采样和格式转换等功能。

3 NGINX+RTMP下载安装配置

前提条件:各级目录不能用中文。

3.1 下载NGINX服务视频推流版

Nginx服务默认安装包不带RTMP模块,其地址:http://nginx.org/en/download.html。页面如下。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第6张图片
NGINX服务视频推流版地址:http://nginx-win.ecsds.eu/download/。页面如下。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第7张图片
下载其中的nginx 1.7.11.3 Gryphon.zip。
还需要下载nginx的rtmp模块nginx-rtmp-module,地址:https://github.com/arut/nginx-rtmp-module。[有RTMP配置文件详细配置,建议仔细阅读]。文件:nginx-rtmp-module-master.zip。

3.2 配置

解压nginx 1.7.11.3 Gryphon.zip,解压nginx-rtmp-module-master.zip,并将其剪切到nginx 1.7.11.3 Gryphon目录下。
参考\nginx-rtmp-module-master\test\nginx.conf,改写 nginx 1.7.11.3 Gryphon\conf\nginx-win.conf,作为其启动配置文件(包含RTMP配置)。内容如下:

#user  nobody;
# multiple workers works !
worker_processes  2;			#Nginx进程数,建议设置为等于CPU总核数

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
   worker_connections  8192;	#工作模式与连接数上限
   # max value 32768, nginx recycling connections+registry optimization = 
   #   this.value * 20 = max concurrent connections currently tested with one worker
   #   C1000K should be possible depending there is enough ram/cpu power
   # multi_accept on;
}

#RTMP服务
rtmp {
   server {
       listen 1935;				#推流监听端口,可以更改
       chunk_size 4000;			#传输文件块的大小
       application live { 			#创建名为live的应用
            live on;				#开启live应用
            allow publish 127.0.0.1;#
            allow play all;
       }
   }
}

http {
   #include      /nginx/conf/naxsi_core.rules;
   include       mime.types;
   default_type  application/octet-stream;

   #log_format  main  '$remote_addr:$remote_port - $remote_user [$time_local] "$request" '
   #                  '$status $body_bytes_sent "$http_referer" '
   #                  '"$http_user_agent" "$http_x_forwarded_for"';

   #access_log  logs/access.log  main;

#     # loadbalancing PHP
#     upstream myLoadBalancer {
#         server 127.0.0.1:9001 weight=1 fail_timeout=5;
#         server 127.0.0.1:9002 weight=1 fail_timeout=5;
#         server 127.0.0.1:9003 weight=1 fail_timeout=5;
#         server 127.0.0.1:9004 weight=1 fail_timeout=5;
#         server 127.0.0.1:9005 weight=1 fail_timeout=5;
#         server 127.0.0.1:9006 weight=1 fail_timeout=5;
#         server 127.0.0.1:9007 weight=1 fail_timeout=5;
#         server 127.0.0.1:9008 weight=1 fail_timeout=5;
#         server 127.0.0.1:9009 weight=1 fail_timeout=5;
#         server 127.0.0.1:9010 weight=1 fail_timeout=5;
#         least_conn;
#     }

   sendfile        off;
   #tcp_nopush     on;

   server_names_hash_bucket_size 128;

## Start: Timeouts ##
   client_body_timeout   10;
   client_header_timeout 10;
   keepalive_timeout     30;
   send_timeout          10;
   keepalive_requests    10;
## End: Timeouts ##

   #gzip  on;

   server {
       listen       80;		#启动服务端口
       server_name  localhost;

       #charset koi8-r;

       #access_log  logs/host.access.log  main;

       ## Caching Static Files, put before first location
       #location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
       #    expires 14d;
       #    add_header Vary Accept-Encoding;
       #}

# For Naxsi remove the single # line for learn mode, or the ## lines for full WAF mode
       location / {
           #include    /nginx/conf/mysite.rules; # see also http block naxsi include line
           ##SecRulesEnabled;
       	  ##DeniedUrl "/RequestDenied";
             ##CheckRule "$SQL >= 8" BLOCK;
             ##CheckRule "$RFI >= 8" BLOCK;
             ##CheckRule "$TRAVERSAL >= 4" BLOCK;
             ##CheckRule "$XSS >= 8" BLOCK;
           root   html;
           index  index.html index.htm;
       }

# For Naxsi remove the ## lines for full WAF mode, redirect location block used by naxsi
       ##location /RequestDenied {
       ##    return 412;
       ##}

## Lua examples !
#         location /robots.txt {
#           rewrite_by_lua '
#             if ngx.var.http_host ~= "localhost" then
#               return ngx.exec("/robots_disallow.txt");
#             end
#           ';
#         }

       #error_page  404              /404.html;

       # redirect server error pages to the static page /50x.html
       #
       error_page   500 502 503 504  /50x.html;
       location = /50x.html {
           root   html;
       }

       # proxy the PHP scripts to Apache listening on 127.0.0.1:80
       #
       #location ~ \.php$ {
       #    proxy_pass   http://127.0.0.1;
       #}

       # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
       #
       #location ~ \.php$ {
       #    root           html;
       #    fastcgi_pass   127.0.0.1:9000; # single backend process
       #    fastcgi_pass   myLoadBalancer; # or multiple, see example above
       #    fastcgi_index  index.php;
       #    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       #    include        fastcgi_params;
       #}

       # deny access to .htaccess files, if Apache's document root
       # concurs with nginx's one
       #
       #location ~ /\.ht {
       #    deny  all;
       #}
   }


   # another virtual host using mix of IP-, name-, and port-based configuration
   #
   #server {
   #    listen       8000;
   #    listen       somename:8080;
   #    server_name  somename  alias  another.alias;

   #    location / {
   #        root   html;
   #        index  index.html index.htm;
   #    }
   #}


   # HTTPS server
   #
   #server {
   #    listen       443 ssl spdy;
   #    server_name  localhost;

   #    ssl                  on;
   #    ssl_certificate      cert.pem;
   #    ssl_certificate_key  cert.key;

   #    ssl_session_timeout  5m;

   #    ssl_prefer_server_ciphers On;
   #    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   #    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:ECDH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!eNULL:!MD5:!DSS:!EXP:!ADH:!LOW:!MEDIUM;

   #    location / {
   #        root   html;
   #        index  index.html index.htm;
   #    }
   #}

}

nginx 1.7.11.3 Gryphon目录下cmd命令行启动Nginx:

nginx.exe -c ./conf/nginx-win.conf

start nginx -c ./conf/nginx-win.conf

注意:启动Nginx需要确保防火墙放行,方式1非后台运行,方式2后台运行,由于默认配置文件为nginx.conf,目前使用非默认配置文件,因此需要指定相对路径。
优雅停止Nginx命令:

nginx.exe -s quit -c ./conf/nginx-win.conf

浏览器输入:localhost:80,出现以下页面则配置成功。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第8张图片

4 VLC播放器拉流测试

在VLC-QT拉流前,可以利用VLC播放器拉流测试ffmpeg、Nginx是否配置正确。VLC播放器下载地址:http://download.videolan.org/vlc/3.0.17.4/win64/,选用目前最新版本3.0.17.4,下载vlc-3.0.17.4-win64.exe。
拷贝本地视频文件Wildlife.wmv到ffmpeg-5.0.1-full_build-shared\bin目录下,该目录下cmd执行命令推流:

ffmpeg.exe -re -i Wildlife.wmv -f flv rtmp://127.0.0.1:1935/live/home

推荐模式安装vlc-3.0.17.4-win64.exe,播放器中依次点击“媒体”==>“打开网络串流”,输入RTMP流媒体服务地址:rtmp://127.0.0.1:1935/live/home,点击“播放”。如下图。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第9张图片
则配置成功。

5 VLC-QT下载编译配置

5.1 环境准备

编译环境:

VS2017旗舰版
Qt 5.12.11(msvc2017_64)
CMake 3.15.3(带cmake-gui)

SDK与源码:

VLC SDK
VLC-QT源码

VLC-QT是基于VLC SDK的二次开发(Qt封装)的库,因此需要下载VLC SDK,下载地址:http://download.videolan.org/vlc/3.0.17.4/win64/,下载vlc-3.0.17.4-win64.7z(注意1.按需下载64位版本,2. 该页面下vlc-3.0.17.4-win64.zip中不含SDK目录,切勿使用)。
VLC-QT官网地址:https://vlc-qt.tano.si/,但仅提供指定Qt版本的库(基于VLC 2.2.4和Qt5.6.1的MSVC 2013的32位和64位库),一般需要下载源码编译。源码下载地址:https://github.com/vlc-qt/vlc-qt。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第10张图片
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第11张图片

5.2 CMAKE编译

分别解压缩vlc-3.0.17.4-win64.7z、vlc-qt-master.zip。
新建环境变量VLC_PLUGIN_PATH,值为vlc-3.0.17.4\plugins路径。
在vlc-qt-master同级目录下新建build、install目录,分别作为build、install目录。
打开CMake,分别配置源码目录与构建目录。如下图,点击“Configure”。
弹出窗口中指定VS版本与平台。这里分别选择“Visual Studio 15 2017”和“x64”。点击“Finish”。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第12张图片
对于CMake的configure结果,按照以下方式配置。

  1. GIT
    有无均可。
  2. Make Install的目录
    使用默认路径存在权限和破坏系统环境问题。将“CMAKE_INSTALL_PREFIX”值改为
    在这里插入图片描述
    “ G:\Projects\QT\VLC-QT\VLC-QT\install”。
    在这里插入图片描述
  3. VLC配置:需指定“LIBVLCCORE_LIBRARY”、“LIBVLC_INCLUDE_DIR”、“LIBVLC_LIBRARY”,分别为“G:\Projects\QT\VLC-QT\VLC\vlc-3.0.17.4\sdk\lib\libvlccore.lib”、“G:\Projects\QT\VLC-QT\VLC\vlc-3.0.17.4\sdk\include”、“G:\Projects\QT\VLC-QT\VLC\vlc-3.0.17.4\sdk\lib\libvlc.lib”。如图所示。
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第13张图片
  4. Add Entry
    为在后面生成库时,使得debug版本名字带“d”,避免生成debug、release版本时同名而相互覆盖。点击“Add Entry”按钮,弹出窗口中配置:
    名称:CMAKE_DEBUG_POSTFIX
    类型:STRING
    价值:d
    说明:可以为空
    如图所示。
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第14张图片
  5. 再次点击“configure”,完成configure。
  6. 点击“Generate”,完成工程生成。
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第15张图片

5.3 VS编译

到目录build下,用VS2017打开VLC-Qt.sln。
在debug、release模式下,分别修改Core,PluginQml,Qml,Widgets工程的属性==>链接器==>命令行==>其它选项下填入/SAFESEH:NO。
这是关闭一种警告,如果不设置这项,在生成工程时,会将这类警告看成错误,进而造成项目生成不成功。
设置完成后,在ALL_BUILD工程上右击生成,生成动态库,生成成功后在“INSTALL”工程上右击生成,可将库提取到安装目录里。(debug、release模式下按此顺序各执行一圈)。
错误修复:

  1. poll问题:提示找不到poll标识符。
    解决方案:定位到poll代码区。会看到一个poll的宏定义。需要把这个宏定义剪贴到 poll代码区的上方。
    从这样:
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第16张图片
    改成这样:
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第17张图片
  2. ssize_t问题。
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第18张图片
    解决方法:在 vlc.h头文件中增加 “typedef __int64 ssize_t;”。
    ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第19张图片
    debug、release模式下构建和安装完成后,Install目录下如下所示。即为编译生成的VLC-QT库。
    在这里插入图片描述

5.4 测试

利用https://github.com/vlc-qt/examples下载的examples-master.zip对编译的VLC-QT库进行测试。
利用Qt 5.12.11所带的QtCreator打开examples-master\simple-player下的simple-player.pro。构建设置中,对于“编辑构建配置”,分别选择Debug、Rlease,并去除“Shadow build”勾选。
修改src.pro,如下:

#
# VLC-Qt Simple Player
# Copyright (C) 2015 Tadej Novak 
#

TARGET      = simple-player
TEMPLATE    = app
CONFIG 	   += c++11

QT         += widgets

SOURCES    += main.cpp \
    SimplePlayer.cpp \
    EqualizerDialog.cpp

HEADERS    += SimplePlayer.h \
    EqualizerDialog.h

FORMS      += SimplePlayer.ui \
    EqualizerDialog.ui

#LIBS       += -lVLCQtCore –lVLCQtWidgets		#注释掉

# Edit below for custom library location
#LIBS       += -L/Users/tadej/workspace/tanoprojects/install/vlc-qt/lib -lVLCQtCore –lVLCQtWidgets					#注释掉
#INCLUDEPATH += /Users/tadej/workspace/tanoprojects/install/vlc-qt/include	#注释掉

#添加以下部分
win32:CONFIG(release,debug|release): LIBS += -L$$PWD/../../../install/lib -lVLCQtCore -lVLCQtWidgets
else:win32:CONFIG(debug,debug|release): LIBS += -L$$PWD/../../../install/lib -lVLCQtCored -lVLCQtWidgetsd

INCLUDEPATH += $$PWD/../../../install/include
DEPENDPATH += $$PWD/../../../install/lib

对simple-player工程依次右键:清除=>执行qmake=>构建=>运行(运行前拷贝VLC-QT库目录install下bin目录下所有文件到examples-master\simple-player\src\release、examples-master\simple-player\src\debug中)。
在启动的程序中,点击“open url”按钮,输入地址:rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp,或前面的自建流媒体服务地址:rtmp://127.0.0.1:1935/live/home,即可拉流播放。
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第20张图片

5.5 其它范例

Github有个vlcplayer的范例可以参考,地址:

 https://github.com/KikyoShaw/vlcPlayer/tree/master/vlcPlayer  

注意:其位数为32位,且其不依赖VLC-QT,直接调用VLC库。

6 选型介绍

对于RTMP拉流开源库选型,Oliver-cs有相关总结:
ffmpeg推流+NGINX(RTMP)+VLC-QT拉流(Win7)_第21张图片
自己尝试后,不得不对Qt原生的多媒体库(QMediaPlayer系列)敬而远之。有其优点,但是缺点非常严重。
QMediaPlayer优点:

  1. 无需额外的库,直接可以使用且实现方式简单,例子丰富;
  2. CPU占用率低,主要使用GPU。

QMediaPlayer缺点:

  1. 支持的视频格式少,跟具体运行在哪个操作系统上有关。在Windows上需要安装LAVFilter等解码器才能支持很多的播放格式;
  2. 无法打开非HTTP格式开头的直播流链接。

而OpenCV的缺点也比较突出:

  1. 虽然底层调用的也是ffmpeg的库,但是OpenCV是将收到的直播流转换成了一张一张的图片,然后再一张一张的图片按顺序播放出来的;
  2. 没有使用GPU,只使用了CPU,会造成CPU占用率极高;
  3. 代码编写麻烦。

VLC-QT除了需要编译之外,其支持格式众多,支持打开多种直播流链接,满足RTMP拉流需求。故最后选择VLC-QT。

7 参考资料

【1】 FFmpeg windows下载安装. https://blog.csdn.net/luoyayun361/article/details/120961899
【2】 Windows下下载安装.ffmpeg.https://zhuanlan.zhihu.com/p/141765024
【3】 ffmpeg的下载及安装. https://blog.csdn.net/qq_33697094/article/details/112718101
【4】 Windows nginx + rtmp 流媒体服务器搭建(uniapp可用). https://blog.csdn.net/qq_41820930/article/details/119169265
【5】 nginx搭建rtmp服务器(windows). https://zhuanlan.zhihu.com/p/93525011
【6】 VLC-Qt VS2017编译Mark. https://blog.csdn.net/icebergkevin/article/details/115708404
【7】 VS2015+QT5.9.3+vlc-qt 完全编译. https://blog.csdn.net/octdream/article/details/82079907
【8】 vlc-qt编译VS2017+QT5.9.0. https://blog.csdn.net/HelloEarth_/article/details/103046448
【9】 QT | 聊聊QT与直播流播放——从QMediaPlayer到Qt-AV. https://www.cnblogs.com/QingHuan/p/8830562.html

你可能感兴趣的:(音视频,QT,qt,nginx,windows,实时音视频)