本来在一心折腾基于Hexo的自建博客,恰好室友提出这样一个需求:在自己的作品集里放一个二维码,扫一下就可以转到一个网页播放自己的视频,但是又要求不能有广告,因此商业性质的视频网站都不能使用。手头刚好有一个AWS的服务器,于是决心尝试一下这类还没碰过的技术。
Web视频流媒体服务器主要应该满足以下几个功能:
提供http服务 具备传输视频流的能力 可以在浏览器中播放视频 一般来说,会将视频传输和视频播放放置在两个服务器上 ,因为视频的解码、传输本身就要消耗大量资源。但现在资源有限,因此先拿一个服务器将就一下。
技术选型 查阅资料发现,Nginx本身就提供了视频流传输和播放功能,对于mp4格式,只需要借用现成插件即可。
Nginx: nginx-1.15.9 mp4: nginx_mod_h264_streaming-2.2.7 另外,在尝试使用Nginx自带播放器播放,发现加载速度极慢难以忍受后,选择使用JW Player
安装nginx 需要手动编译,以包含一些需要的附加功能(如mp4等)
nginx_mod_h264_streaming的下载地址: http://h264.code-shop.com/trac/wiki/Mod-H264-Streaming-Nginx-Version2
nginx-rtmp-module下载地址: https://github.com/arut/nginx-rtmp-module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ sudo apt update $ sudo apt install libpcre3 libpcre3-dev $ sudo apt install libssl-dev $ sudo apt-get install zlib1g-dev $ wget http://nginx.org/download/nginx-1.15.9.tar.gz $ wget http://h264.code-shop.com/download/ngi7.tar.gz $ git clone https://github.com/arut/nginx-rtmp-module $ tar -zxvf nginx-1.15.9.tar.gz $ tar -zxvf nginx_mod_h264_streaming-2.2.7.tar.gz $ cd nginx-1.15.9/ $ ./configure --prefix=/usr/local/nginx --add-module=../nginx_mod_h264_streaming-2.2.7 \ --add-module=../nginx-rtmp-module --with-http_flv_module --with-http_mp4_module \ --with-http_gzip_static_module --with-http_stub_status_module
此时如果执行make
会报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 In file included from ../nginx_mod_h264_streaming-2.2.7/src/ngx_http_h: ../nginx_mod_h264_streaming-2.2.7/src/ngx_http_streaming_module.c: In ndler’: ../nginx_mod_h264_streaming-2.2.7/src/ngx_http_streaming_module.c:158:st_t {aka struct ngx_http_request_s}’ has no member named ‘zero_in_uriri’? if (r->zero_in_uri) ^~~~~~~~~~~ plus_in_uri objs/Makefile:1262: recipe for target 'objs/addon/src/ngx_http_h264_st make[1]: *** [objs/addon/src/ngx_http_h264_streaming_module.o] Error 1 make[1]: Leaving directory ' /home/username/downloads/nginx-1.15.9' Makefile:11: recipe for target ' install' failed make: *** [install] Error 2
编辑objs/Makefile
,去掉编译选项的-Werror
1 2 3 $ sudo make install $ sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx $ sudo nginx
此时通过浏览器访问服务器,若看到默认欢迎页面,说明nginx安装成功。
配置nginx 在若干次尝试中借鉴了多篇文章,最终的配置如下:
/usr/local/nginx/conf/nginx.conf 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 #user nobody; worker_processes 4; error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; pid logs/nginx.pid; events { use epoll; worker_connections 65535; } rtmp { server { listen 1935; application vod { play /home/username/web_service/rtmp; } } } http { include mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; server_names_hash_bucket_size 128; client_header_buffer_size 32k; large_client_header_buffers 4 32k; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; output_buffers 1 32k; postpone_output 1460; client_header_timeout 3m; client_body_timeout 3m; send_timeout 3m; tcp_nopush on; tcp_nodelay on; open_file_cache max=64 inactive=30d; open_file_cache_min_uses 1; open_file_cache_valid 3m; server { listen 8081; server_name x.x.x.x; charset utf-8; location ~ \.mp4$ { root /home/username/web_service/mp4/; } location ~ \.m4v$ { root /home/username/web_service/m4v/; } location ~ \.flv$ { root /home/username/web_service/flv/; } location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl root /home/username/downloads/nginx-rtmp-module; } #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; } } server { listen 80; server_name x.x.x.x; charset utf-8; location / { root /home/username/web_service/html/; index index.html index.htm; } # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
主要思路是,在8081端口提供视频文件的HTTP服务,在80端口提供视频播放的页面以供访问。
本来试图通过rtmp推流,但不知道为什么,ffmpeg可以正常读取原视频,写流时也未报错,但无法正常推流,最终作罢。
通过这样的设置,重启nginx:
访问http://x.x.x.x:8081/xxx.mp4
即可播放mp4格式的视频。但由于使用了nginx自带的播放器,所以卡顿非常明显,体验不好,考虑使用专用播放器。
播放 播放器选择了JW Player,似乎以前是开源的,但现在变为免费试用六个月。只需要在官网注册,即可获得专用代码,复制到html中即可。
编辑/home/username/web_service/html/index.html
如下
index.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!DOCTYPE heml > <html > <head > <script type ="text/javascript" src ="https://cdn.jwplayer.com/libraries/xxxx.js" > </script > <script type ="text/javascript" src ="getParam.js" > </script > <meta http-equiv ="Content-Type" content ="text/html;charset=utf-8" /> </head > <body bgcolor ="#000000" > <div id ="myElement" > Loading the page...</div > <script type ="text/javascript" > var file_name=getParam ('id' ); console .log (file_name); jwplayer ("myElement" ).setup ({ file : "http://x.x.x.x:8081/" + file_name, title : file_name, }); </script > </body > </html >
方便起见,编写了一个js函数用来获取GET请求参数,从而指定播放文件
getParam.js 1 2 3 4 5 6 7 8 function getParam (paramName ) { paramValue = "" , isFound = !1 ; if (this .location .search .indexOf ("?" ) == 0 && this .location .search .indexOf ("=" ) > 1 ) { arrSource = unescape (this .location .search ).substring (1 , this .location .search .length ).split ("&" ), i = 0 ; while (i < arrSource.length && !isFound) arrSource[i].indexOf ("=" ) > 0 && arrSource[i].split ("=" )[0 ].toLowerCase () == paramName.toLowerCase () && (paramValue = arrSource[i].split ("=" )[1 ], isFound = !0 ), i++; } return paramValue == "" && (paramValue = null ), paramValue; }
那么通过http://x.x.x.x/?id=xxx.mp4
就可以直接用JW Player播放目标视频了。效果如下:
生成二维码 最后也是最简单的一步,我直接使用了Chrome的插件 "Quick QR Code Generator!",打开目标页面,即可直接生成二维码。
结果 一开始在校园网测试发现还是有卡顿,但室友用4G表示非常流畅……所以还是校园网太垃圾了。室友很满意,承诺要请我吃饭😀
References 核心部分 利用该文安装了支持mp4的Nginx:
nginx搭建flv、mp4流媒体服务
利用这两篇文章完成了Nginx配置和JW Player的使用:
利用nginx搭建http和rtmp协议的流媒体服务器 Nginx搭建flv视频点播服务器 (以前文为基础)
Nginx Ubuntu18.04安装Nginx Nginx的启动、停止与重启 Nginx Open File Cache
视频流 Linux nginx+rtmp服务器配置实现直播点播 (应该是最成熟的方案,但我最终没有使用rtmp) 理解RTMP、HttpFlv和HLS的正确姿势
页面实现 PHP如何与js交互数据 (但没有用到) 开源网页播放器JWplayer使用 js获取url传递参数,js获取url?号后面的参数 JS-获取URL请求参数