一、背景作者想把自己收藏的一些电影放在网站上随时播放,但是遇到了一个问题,就是如果MP4文件是直接放在网站目录中,移动端必须下载整个视频才能播放,如果跨外网传输,这实在是不现实。为了解决这个问题,我想到了做一个流媒体服务,让手机边看边下载。查了一些资料得知,视频需要分成小块进行传输,比如MP4转M3U8格式。查询相关转码方式,比较主流的方式是使用开源工具ffmpeg二、操作概述1、安装Ffmpeg2。服务搭建3.功能测试3.构建ffmpeg视频转码的工具可能有很多,但是开源和使用人数最多的工具是ffmpeg,具体功能我这里不做详细说明;这个工具的安装方式有很多种,比如apt安装、源码安装、docker安装等等,但是docker是跨平台的,所以这里我就以docker的方式安装为例3.1图片下载首先,笔者需要下载对应的docker镜像。参考命令如下。在执行dockerpulljrottenberg/ffmpeg命令的过程中,会远程下载镜像。这个时间是由当前的网络带宽决定的。Afterthedownloadiscompleted,可以看到如下参考信息Usingdefaulttag:latestlatest:Pullingfromjrottenberg/ffmpegb234f539f7a1:Pullcomplete55172d420b43:Pullcomplete5ba5bbeb6b91:Pullcomplete43ae2841ad7a:Pullcompletef6c9c6de4190:Pullcomplete2a0ef76bfa54:Pullcomplete40ddf796a4bb:Pullcomplete32ba137d2764:PullcompleteDigest:sha256:bcf65375f593518de7e450fd6b775d16a047d3ded00957c2e794e2fe8f7e1590Status:Downloadednewerimageforjrottenberg/ffmpeg:latest3.2containerrunning容器下载完成后,可以使用一些命令验证是否可以正常运行。下面参考命令dockerrunjrottenberg/ffmpeg命令执行后会返回如下结果HyperfastAudioandVideoencodeusage:ffmpeg[options][[infileoptions]-iinfile]...{[outfileoptions]outfile}...获取帮助:.....省略音频选项:-aframesnumber设置要输出的音频帧数-aqquality设置音频质量(codec-specific)-arrate设置音频采样率(以Hz为单位)-acchannels设置音频通道数-andisableaudio-acodeccodecforceaudiocodec('copy'tocopystream)-volvolumechangeaudiovolume(256=正常)-affilter_graph设置音频过滤器字幕选项:-ssize设置帧大小(WxH或缩写)-sn禁用字幕-scodeccodec强制字幕编解码器(“复制”到复制流)-stagfourcc/tag强制字幕标签/fourcc-fix_sub_durationfixsubtitlesduration-canvas_sizesizesetcanvassize(WxHorabbreviation)-sprepreset设置字幕选项为指定的preset3.3检查支持的协议FFmpeg支持很多输入输出协议,比如可以选择文件协议为source,使用hls协议作为输出结果。具体支持的协议可以通过如下命令docker查看执行命令runjrottenberg/ffmpeg-protocols后,参考结果如下ffmpegversion3.4.2Copyright(c)2000-2018theFFmpegdevelopersbuiltwithgcc5.4.0(Ubuntu5.4.0-6ubuntu1~16.04.9)20160609配置:--disable-debug--disable-doc--disable-ffplay--enable-shared--enable-avresample--enable-libopencore-amrnb--enable-libopencore-amrwb--enable-gpl--enable-libass--enable-libfreetype--enable-libvidstab--enable-libmp3lame--enable-libopenjpeg--enable-libopus--enable-libtheora--enable-libvorbis.....省略支持的文件协议:输入:异步cacheconcatcryptodata.....OmitOutput:cryptofile.....Omittlsudp3.4conversiontest现在我用FFmpeg转码视频。命令非常简单。首先需要将视频所在目录挂载到容器中,然后使用-i选项在容器中找到对应的视频文件;然后可以在编码上进行一些选项,比如-hls_time10是每10秒输出一个ts文件,-hls_list_size0是在m3u8文件中记录所有的ts文件(默认记录最后五个ts文件),并在参数末尾填写文件输出路径。具体参考命令如下:dockerrun-v/Users/song/video:/root/downloadjrottenberg/ffmpeg:latest-i/root/download/1.mp4-hls_time10-hls_list_size0-fhls/root/download/index.m3u8命令执行过程中会显示转换进度。参考返回的元数据如下:major_brand:mp42minor_version:0compatible_brands:mp42mp41encoder:Lavf57.83.100Stream#0:0(eng):Video:h264(libx264),yuv420p(progressive),1920x1080,q=-1--1,30fps,90ktbn,30tbc(default)Metadata:creation_time:2018-08-21T15:09:24.000000Zhandler_name:AliasDataHandlerencoder:Lavc57.107.100libx264Sidedata:cpb:bitratemax/min/avg:0/0/0缓冲区大小:0vbv_delay:-1流#0:1(eng):音频:aac、48000Hz、立体声、fltp、128kb/s(默认)元数据:creation_time:2018-08-21T15:09:24.000000Zhandler_name:AliasDataHandlerencoder:Lavc57.107.100aacframe=82fps=12q=29.0size=N/Atime=00:00:02.62bitrate=N/Aspeed=0.381xAt至此,可以在刚才的挂载点查看ts文件,如下图下面我将刚才的ts文件全部删除,下面使用自动化来完成4、服务搭建在上一步中,笔者已经成功使用FFmpeg通过终端对视频进行了转码。接下来笔者将结合PHP代码,将这些操作完全自动化,从而实现通过手机访问网站,服务器自动完成转码播放。这个过程包括三个部分:创建虚拟主机、编写显示视频列表、自动解码视频。4.1创建虚拟主机首先,我需要使用nginx来构建一个web服务。这时候需要修改配置文件,但是不记得nginx的配置文件了。存放位置,此时可以使用如下命令sudonginx-t得到结果如下,在结果中可以看到nginx配置文件nginx的存放位置:配置文件/usr/local/etc/nginx/nginx.conf语法为oknginx:配置文件/usr/local/etc/nginx/nginx.conf测试成功使用vim编辑器直接编辑nginx配置文件vim/usr/local/etc/nginx/nginx.conf在配置文件信息server中加入如下参考配置{listen8089;服务器名称本地主机;root/Users/song/mycode/work/test/video;location/{indexindex.htmlindex.htmindex.php;}location~\.php${fastcgi_pass127.0.0.1:9000;fastcgi_indexindex.php;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;包括fastcgi_params;}}4.2获取视频列表nginx配置完成后,需要编写PHP代码,可以通过PHP获取目录的视频列表,然后添加输出到网页,参考代码如下$val){if(!in_array(pathinfo($val,PATHINFO_EXTENSION),['mp4','rmvb','wmv'])){继续;}?>=$val?>
代码中,首先通过scandir读取文件夹中的所有文件,然后通过foreach循环判断是否为视频文件后缀名。如果是视频文件,输出一个链接地址供用户选择4.3进行视频转码上面代码列出视频列表后,当用户点击链接时,需要使用FFmpeg进行转码。参考代码如下>./code.log&";system($cmd);//延时执行跳转returnUrl($fileName);functiongetFileName($filename){$houzhui=substr(strrchr($filename,'.'),1);$result=basename($filename,".".$houzhui);返回$result;}functionreturnUrl($fileName){echo"处理中...点击跳转
";die;}上面代码中,考虑文件是否已经转码,如果已经转码,直接返回播放地址,否则创建一个文件夹存放TS文件,然后转码,FFmpeg转码时使用nohup命令即可异步执行,然后PHP返回播放地址转码是否正常,转码后的视频是否可以播放5.1视频列表首先通过浏览器打开网址http://localhost:8089/加载后,可以看到下面的视频列表,如果读者在界面上运行上面的代码会有细微的差别,因为作者为了节省文章的篇幅,没有把样式代码放在文章里面。如果你想要一个好的接口,可以自己写样式代码。5.2视频转码点击视频列表中的一个链接后,后台PHP程序会执行转码任务,然后返回一个链接地址,如下图,说明FFmpeg已经在后台运行,你可以通过以下命令查看FFmpeg容器的运行状态,参考命令如下。dockerps返回的参考结果如下。从返回结果可以看出当前有一个任务正在运行。此时打开视频输出目录,会看到多个ts格式的视频文件。这些文件只是PHP自动执行生成的,如下图表示当你看到如上图所示的转码后的视频文件时,可以通过浏览器访问。不支持m3u8的解析。如需使用其他浏览器播放,需安装插件;苹果默认支持不需要笔者通过Safari浏览器再次打开页面,然后再次选择1.mp4视频,然后直接跳转到播放页面,如下图,可以看到流媒体是基本完成。如果需要播放更多的视频,只需要将视频文件存放在指定的视频目录下,网页会自动读取出来。可能过于简化了,读者可以根据自己的需要对html页面进行美化。6.新书推荐如果您对作者的实用文章更感兴趣,可以关注作者的新书《PHP Web安全开发实战》,现已在各大平台发售。封面如下图作者:唐青松微信:songboy8888日期:2018-10-28
