Nginx搭建flv视频点播服务器

前一段时间使用Nginx搭建的多媒体服务器只能在缓冲过的时间区域内拖放, 而不能拖放到未缓冲的地方. 这就带来了一个问题: 如果视频限速的速率很小, 那么客户端观看视频时肯定不流畅, 而且用户不能向前拖放, 用户体验很不好. 如果视频限速的速率很大或者不限速, 服务器是承受不了的, 特别是在某个热门视频高并发访问的情况下, 而且客户端浏览器也在快速的从服务器接收数据, 同样会造成客户端视频播放不流畅的问题, 对服务器的性能和网络带宽都是很大的挑战. 所以很有必要将实现视频服务器的点播功能, 这样既可以对视频进行限速, 避免大量不必要数据在网上的传送, 又可以改善用户体验.

本文主要参考了 [1] 的实现, 期间会遇到各种意想不到问题, 然后从网上搜索到了解决方法. 本次搭建使用的Nginx版本是1.4.1, jwplayer的版本是6.6.

资料:

HTTP Live Streaming(缩写是 HLS)是一个由苹果公司提出的基于HTTP的流媒体 网络传输协议。
HLS只请求基本的HTTP报文,与实时传输协议(RTP)不同,HLS可以穿过任何允许HTTP数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。

一 准备

搭建点播服务器需要如下几个模块:

  • nginx_mod_h264_streaming: 使nginx支持h264编码的视频
  • http_flv_module: 支持flv
  • http_mp4_module: 支持mp4
  • nginx-rtmp-module: 支持rtmp协议

其中http_flv_module和http_mp4_module两个模块是nginx自带的, 可以在编译的时候加上相应的选项.

nginx_mod_h264_streaming的下载地址: http://h264.code-shop.com/trac/wiki/Mod-H264-Streaming-Nginx-Version2

nginx-rtmp-module托管在GitHub上: https://github.com/arut/nginx-rtmp-module

注意在GitHub的"Build"部分有这样一句话:

Several versions of nginx (1.3.14 - 1.5.0) require http_ssl_module to be added as well:

1
./configure --add-module=<path-to-nginx-rtmp-module> --with-http_ssl_module

我用的nginx版本是1.4.1, 所以在configure的时候需要加上"--with-http_ssl_module"选项, 否则会出现错误:

1
2
3
4
5
src/http/ngx_http_request.c: 在函数‘ngx_http_set_virtual_server’中:
src/http/ngx_http_request.c:1992:9: 错误: 未知的类型名‘ngx_http_ssl_srv_conf_t’
src/http/ngx_http_request.c:1999:16: 错误: ‘ngx_http_ssl_module’未声明(在此函数内第一次使用)
src/http/ngx_http_request.c:1999:16: 附注: 每个未声明的标识符在其出现的函数内只报告一次
src/http/ngx_http_request.c:2001:17: 错误: 在非结构或联合中请求成员‘verify’

ssl的安装可以参考网上教程, 也可以参考 [1] . 注意Ubuntu环境下SSL库是libssl-dev:

sudo apt-get install libssl-dev

关于ffmpeg及其依赖库的安装, 请参考我的上一篇文章:http://www.cnblogs.com/wanghetao/p/3386311.html, 在此不再赘述.

二 安装Nginx及其相关模块

(Nginx使用的是Perl正则表达式, 所以需要首先安装PCRE, 读者能够从网上找到PCRE的安装过程, 在此不赘述. )

# mkdir nginx

# cd nginx

# cp ../nginx-1.4.1.tar.gz ../nginx_mod_h264_streaming-2.2.7.tar.gz ../nginx-rtmp-module-master.zip ./

#  tar -zxvf nginx-1.4.1.tar.gz                                   (同样地将其余两个包解压缩)

# cd nginx-1.4.1

# ./configure --prefix=/usr/local/nginx --add-module=../nginx_mod_h264_streaming-2.2.7 --add-module=../nginx-rtmp-module-master/ --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_stub_status_module --with-cc-opt="-I/usr/local/ffmpeg2/include" --with-ld-opt="-L/usr/local/ffmpeg2/lib"

# make

这个时候出现了错误:

1
2
3
4
5
6
7
8
9
10
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c: 在函数‘esds_read’中:
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c:377:16: 错误: 变量‘stream_priority’被设定但未被使用 [-Werror=unused-but-set-variable]
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c:376:12: 错误: 变量‘stream_id’被设定但未被使用 [-Werror=unused-but-set-variable]
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c: 在函数‘stsd_parse_vide’中:
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c:529:22: 错误: 变量‘level_indication’被设定但未被使用 [-Werror=unused-but-set-variable]
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c:528:22: 错误: 变量‘profile_compatibility’被设定但未被使用 [-Werror=unused-but-set-variable]
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c:527:22: 错误: 变量‘profile_indication’被设定但未被使用 [-Werror=unused-but-set-variable]
../nginx_mod_h264_streaming-2.2.7/src/mp4_reader.c:526:22: 错误: 变量‘configuration_version’被设定但未被使用 [-Werror=unused-but-set-variable]
cc1: all warnings being treated as errors
make[1]: *** [objs/addon/src/mp4_reader.o] 错误 1

# vim objs/Makefile (修改objs/Makefile文件, 去掉其中的"-Werror"), 然后就能够正常编译了.

# make

# make install

至此nginx安装成功了.

三 修改nginx配置文件nginx.conf, 配置虚拟主机

这一部分请参考 [1] , 其中比较传神的地方是限速功能的实现. 使用一个端口提供视频文件视频文件的访问以及并发访问量和限速功能(比如8081), 然后从另一个端口配置虚拟主机, 在网页中使用http协议对8081的视频文件进行访问.

四 flv文件转码和元数据的注入

使用ffmpeg转码后的flv文件需要注入元数据(metadata)之后才能实现拖放, metadata中主要是关键帧. 我使用yamdi实现元数据的注入. yamdi为flv文件增加了很多metadata信息,比如创建者、是否有关键帧、是否有视频、是否有音频,视频高度和宽度等等。而yamdi加入的meta数据中,最有效的要数关键帧。被注入了关键帧的flv可以实现像土豆网、优酷网等大型视频网站一样的“拖进度”,提前拖到缓冲还未加载到的位置开始播放。另一个可用的工具是flvtool2, 网上一个文章提供了两者的用法和比较: http://blog.csdn.net/zhangxh1013/article/details/5896482.

yamdi的安装也很简单:

(1) 下载: http://yamdi.sourceforge.net/

(2) # tar -zxvf yamdi-1.9.tar.gz

(3) # cd yamdi-1.9

(4) # make & make install

元数据注入:

1
yamdi -i input.flv -o output.flv

输出的文件使用ffmpeg查看, 可以看到这样的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Metadata:
   creator         : m_8efd9a8eb9c1c7434e76fc0e27052f91_md Tudou, Inc.
   metadatacreator : Tudou Metadata Injector for FLV - Version 1.0
   hasKeyframes    : true
   hasVideo        : true
   hasAudio        : true
   hasMetadata     : true
   canSeekToEnd    : false
   datasize        : 14485828
   videosize       : 13399710
   audiosize       : 1041346
   lasttimestamp   : 251
   lastkeyframetimestamp: 245
   lastkeyframelocation: 14458306
   encoder         : Lavf55.12.100

这说明元数据注入成功, 并且输出文件中含有关键帧.

当然, 在ffmpeg转码的同时也可以向flv文件中加入关键帧, 只需加入 "-keyint_min" 参数. ffmpeg文档中对此的解释是:

1
2
3
‘keyint_min integer (encoding,video)’
    Set minimum interval between IDR-frames.      (设定IDR帧之间的最小间隔)

但是用ffmpeg转码的方法添加元数据仍然不能对视频随意拖放, 用ffmpeg可以看到转码后的视频的元数据信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ffmpeg -i output.flv
......
 Metadata:
    creator         : m_8efd9a8eb9c1c7434e76fc0e27052f91_md Tudou, Inc.
    metadatacreator : Tudou Metadata Injector for FLV - Version 1.0
    hasKeyframes    : true
    hasVideo        : true
    hasAudio        : true
    hasMetadata     : true
    canSeekToEnd    : false
    datasize        : 14485828
    videosize       : 13399710
    audiosize       : 1041346
    lasttimestamp   : 251
    lastkeyframetimestamp: 245
    lastkeyframelocation: 14458306
    encoder         : Lavf55.12.100

它与使用yamdi方法产生的结果的位于区别是"canSeekToEnd"为false, 为什么这样的flv视频不能拖放还有待于以后研究.

五 jwplayer播放器的设定

通过以上四个步骤, flv视频点播服务器已经基本搭建成功了. 下面要使用jwplayer播放视频, 检验以上的设置是否成功. 编写以下PHP文档并在浏览器中打开:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE heml>
<html>
    <head>
        <script type="text/javascript" src="jwplayer/jwplayer.js"></script>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    </head>
     
    <body>       
        <div id="myElement">Loading the page...</div>
        <script type="text/javascript">
            var file_name = "<?php echo  $_GET['id']; ?>";
            jwplayer("myElement").setup({
                file: "http://localhost:82/" + file_name,
                // image: "data/myposter.jpg",
                title: file_name,
            });
        </script>
    </body>
</html>

  

浏览器中输入URL:

1
http://localhost/videoplayer/?id=output.flv

满怀激动地心情, 结果还是失望了: 视频仍然不能拖放!!! 为什么会这样呢? 原因是jwplayer的设定不正确. 需要向jwplayer中添加SEEK功能, 告诉它要对文件进行seek, 这是通过"starttime"参数实现的. 可以参考: http://www.longtailvideo.com/support/jw-player/28855/pseudo-streaming-in-flash. 对于不同编码和不同视频格式的文件, "starttime"的值各不相同. 对于h264编码的flv格式文件, "starttiem"设为"start".

修改完成后, 在浏览器中再次输入URL, 尝试拖动进度条, 成功了!!! 真的很高兴..来个高清大图给乃们瞧瞧.

参考文献:

[1] http://5iqiong.blog.51cto.com/2999926/1132639

分类: ffmpeg与multimedia

Nginx搭建flv视频点播服务器相关推荐

  1. 使用nginx搭建音视频点播服务——基于DASH协议

    文章目录 1 DASH流媒体协议 2 搭建点播服务 2.1 nginx代理 2.2 nginx-vod-module模块 2.3 配置nginx下的DASH点播服务 2.3.1 常规配置 2.3.2 ...

  2. 网易视频云:用Nginx搭建flv,mp4,hls流媒体服务

    网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,提供稳定流畅.低时延.高并发的视频直播.录制.存储.转码及点播等音视频的PAAS服务,在线教育.远程医疗.娱乐秀场.在线 ...

  3. Nginx搭建部署Web服务器并与NFS结合搭建负载均衡服务器

    Nginx搭建部署Web服务器并与NFS结合搭建负载均衡服务器 一.搭建NginxWeb服务器     此种方式是用yum安装Nginx,为保证安装成功需在安装之前提前安装epel扩展源.     用 ...

  4. 使用 NGINX 搭建 RTMP 流媒体服务器实现直播功能

    使用 NGINX 搭建 RTMP 流媒体服务器实现直播功能 本文介绍了如何使用 Nginx 搭建 RTMP 流媒体服务器,并提供配置文件和前端示例,实现直播功能. 环境 操作系统: Ubuntu 18 ...

  5. keepalive+nginx搭建主从负载服务器

    keepalive+nginx搭建主从负载服务器 keepalive配置文件 从: ! Configuration File for keepalived global_defs { notifica ...

  6. nginx搭建静态文件服务器,利用nginx搭建静态资源服务器的方法步骤

    以windows为例,linux其实一样: 搭建静态资源服务器 我电脑上的work文件夹下面有很多图片,我想通过nginx搭建静态资源服务器,通过在地址栏输入ip+port的方式完成目录的映射 找到n ...

  7. 前后端分离项目nginx搭建静态页面服务器cors做后台跨域接收前台请求

    自己在闲暇时间里,无聊的我试着做了一个前后台分离的入门demo.在编写代码前通过查询百度,csdn,博学谷等做了一些准备工作,具体还只是做到前台发送的请求能顺利的发送到后端,时间仓促做的也有不足之处, ...

  8. 使用nginx搭建音视频点播服务——基于HLS协议

    文章目录 1 音视频技术 1.1 流媒体 1.2 点播与直播 1.3 HLS流媒体协议 1.4 CDN 2 搭建点播服务(音视频同理) 2.1 nginx服务器 2.2 nginx-vod-modul ...

  9. Windows基于Nginx搭建RTMP流媒体服务器(附带所有组件下载地址及验证方法)

    RTMP服务时常用于直播时提供拉流推流传输数据的一种服务.前段时间由于朋友想搭建一套直播时提供稳定数据传输的服务器,所以就研究了一下如何搭建及使用. 1.下载nginx 首先我们要知道一般nginx不 ...

最新文章

  1. C++与MATLAB数组的存储结构
  2. 水来了,数据中心如何做好防汛防洪措施?
  3. 利用percona-toolkit工具检查MySQL数据库主从复制数据的一致性,以及修复。
  4. Go(4 [Map])
  5. oracle 复制数据 insert into、as select
  6. 14. Magento路由分发过程解析(二):Standard路由对象
  7. js html方法的区别吗,jquery append()方法与html()方法的区别及使用介绍
  8. Python骚操作,生成WiFi二维码,扫描一键联网
  9. java生成api文档工具_api文档自动生成工具
  10. 死链对网站的影响、产生过程、解决办法汇总
  11. 计算机组成原理与体系结构 —— 南桥与北桥
  12. windows保护无法启动修复服务器,win10系统使用“sfc /scannow”修复系统提示Windows资源保护无法启动修复服务怎么办...
  13. 股指指数平稳性检验和随机性检验
  14. 小说里的编程 【连载之十六】元宇宙里月亮弯弯
  15. Jetpack Compose - Switch
  16. 仿微信视频通话大小视图切换(SurfaceView实现)
  17. 第6章第1节:基本设计理论:幻灯片设计过程中的七个常见技巧 [PowerPoint精美幻灯片实战教程]
  18. IDU-指令译码单元
  19. 这个母亲节的礼物,我为你们准备好了!(内含福利)
  20. echarts.js刻度标签实现富文本实现中文+图片的效果解决方法

热门文章

  1. [转载] 全本张广泰——第十七回 夫人诱广泰 血溅洪洞县
  2. 配置静态路由使用出站接口和下一跳IP的差别
  3. javaScript 之 蚁人微任务
  4. 2018年GPS定位器会发生什么样变化?
  5. Solr 建立多对多对象索引,检索时只显示了第一条
  6. DOM4J_Xpath的XML操作总结
  7. Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析
  8. c++builder Delphi 直接使用剪贴板 Clipboard
  9. SCOM2012部署系列之九:部署审核收集报告(ACSReporting)
  10. 针对web服务器容灾自动切换方案