• 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提供的源码自己编译。
    在这里插入图片描述
    点击“Download”,在跳转的下载页面,点击Win10图标,选择“Windows builds from gyan.dev”(下面一个链接是GitHub对应页面)。
    在这里插入图片描述
    在跳转到页面中,可以下载essential和full版本,essential就是简版,只包含ffmpeg.exe、ffplay.exe、ffprobe.exe, 而full版本就包含了动态库和相关头文件,方便我们在开发中调用。点击“full-release-full-shared.7z”,下载。
    在这里插入图片描述
    解压后目录如下:
    在这里插入图片描述
    将bin目录的全路径添加到环境变量PATH。
    cmd命令行到bin目录下(如已添加到PATH环境变量则无需),输入ffmpeg –version。出现下图则成功。
    在这里插入图片描述
    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。页面如下。
    在这里插入图片描述
    NGINX服务视频推流版地址:http://nginx-win.ecsds.eu/download/。页面如下。
    在这里插入图片描述
    下载其中的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;
       #    }
       #}
    
    }
    
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187

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

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

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

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

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

    浏览器输入:localhost:80,出现以下页面则配置成功。
    在这里插入图片描述

    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
    
    • 1

    推荐模式安装vlc-3.0.17.4-win64.exe,播放器中依次点击“媒体”==>“打开网络串流”,输入RTMP流媒体服务地址:rtmp://127.0.0.1:1935/live/home,点击“播放”。如下图。
    在这里插入图片描述
    则配置成功。

    5 VLC-QT下载编译配置

    5.1 环境准备

    编译环境:

    VS2017旗舰版
    Qt 5.12.11(msvc2017_64)
    CMake 3.15.3(带cmake-gui)
    
    • 1
    • 2
    • 3

    SDK与源码:

    VLC SDK
    VLC-QT源码
    
    • 1
    • 2

    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。
    在这里插入图片描述
    在这里插入图片描述

    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”。
    在这里插入图片描述
    对于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”。如图所示。
      在这里插入图片描述
    4. Add Entry
      为在后面生成库时,使得debug版本名字带“d”,避免生成debug、release版本时同名而相互覆盖。点击“Add Entry”按钮,弹出窗口中配置:
      名称:CMAKE_DEBUG_POSTFIX
      类型:STRING
      价值:d
      说明:可以为空
      如图所示。
      在这里插入图片描述
    5. 再次点击“configure”,完成configure。
    6. 点击“Generate”,完成工程生成。
      在这里插入图片描述

    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代码区的上方。
      从这样:
      在这里插入图片描述
      改成这样:
      在这里插入图片描述
    2. ssize_t问题。
      在这里插入图片描述
      解决方法:在 vlc.h头文件中增加 “typedef __int64 ssize_t;”。
      在这里插入图片描述
      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
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    对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,即可拉流播放。
    在这里插入图片描述

    5.5 其它范例

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

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

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

    6 选型介绍

    对于RTMP拉流开源库选型,Oliver-cs有相关总结:
    在这里插入图片描述
    自己尝试后,不得不对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

  • 相关阅读:
    ACM第三周---周训---题目合集.
    内存模型以及如何判定对象已死问题
    java基础
    Python基础复习【第二弹】【黑马】
    opencv 双目立体视觉
    【framework-5】可能你需要加个if、加了变量
    带返回值宏函数[C语言]
    计算流体力学的基本方法简介(有限差分法、有限元法、有限体积法)
    Git进阶之代码回滚、合并代码、从A分支选择N次提交,合并到B分支【revert、merge、rebase、cherry-pick】
    js 图片路径转换base64格式
  • 原文地址:https://blog.csdn.net/langshuibaren/article/details/126145683