阿不都克里木·玉素甫,王亮亮
(1.新疆师范高等专科学校(新疆教育学院)现代教育技术中心,新疆 乌鲁木齐 830043;2.新疆教育云技术与资源实验室,新疆 乌鲁木齐 830043)
近年来随着计算机多媒体技术的不断发展,先后出现多种视频格式,如:AVI、DV-AVI、MPEG、WMV、ASF、DivX、DAT(VCD)、VOB(DVD)、MOV、MKV等。由于这些视频格式是由不同技术公司所制定或发明的,比如:AVI由微软公司制定,MOV由Apple公司制定[1],因此视频格式的技术标准或者说是视频编码[2]也有所不同,需要相应的解码器才可以播放。一般为了将这些不同视频源发布至Web中,首先需要将视频源转换为FLV或MP4等格式后上传至服务器,再通过相应的Web嵌入播放器来播放视频。视频发布工作如果按照传统的方法进行操作,需要3个步骤来完成:首先转换视频文件,然后上传视频,最后填写相应的信息后发布视频。这种传统方法的过程还是非常繁琐并且耗时的。
FFMPEG是一个免费、开源、跨平台的软件,且FFMPEG的开源项目已经走过了十几个年头[1],有很多使用场景。其中较为典型的有播放器、媒体编辑器、转码器等,对音视频编码处理有着较好的支持,因此目前视频处理相关的大部分研究[3-5]都是采用FFMPEG。本文研究与实现一种基于自主可控平台技术的FFMPEG在线视频转换系统。本系统也采用FFMPEG对视频进行转换及压缩等操作,但是程序中的调用方式有所不同,即直接以命令行的方式通过Java接口调用FFMPEG程序,并与上传模块、Socket服务模块、注入关键帧模块和视频播放模块有效地结合,实现各个模块协同工作机制,达到一个步骤完成视频文件的上传、转换、压缩、注入关键帧等一系列操作的目的,为视频转换提供便利的同时减少了一定的工作量。
在线视频转换系统基于B/S架构设计,即客户端通过Web浏览器向服务器端传输视频文件,与此同时服务器端接收上传文件并做一系列相应的操作后,将转换完成的目标视频文件存储至服务器。服务器端根据处理内容主要分为3个部分:Tomcat服务器、Socket服务和Nginx服务器。其中Tomcat服务器负责视频传输、存储以及向Socket服务发送指令,Socket[6-8]服务主要处理视频的转换、压缩以及注入关键帧等操作,而Nginx[9-12]服务器提供负载均衡功能和视频资源的在线播放功能。系统总体框架如图1所示。
图1 系统框架图
根据系统框架图中服务器端的处理内容,具体操作如下:
1)Tomcat服务器。
客户端用户通过Web浏览器上传视频源文件至服务器,这时服务器开始对用户所传输的视频文件进行处理。首先Tomcat服务器上传模块开始将视频文件存储至指定的文件路径,与此同时向客户端返回进度数据并显示上传进度。客户端上传进度显示为100%时,上传模块结束文件的上传操作,并向Socket服务发送指令。
2)Socket服务。
系统将启用Socket服务对视频文件进行不同指令操作。Socket服务采用多线程技术[13-16],可以将多个文件根据上传完成时间逐一放入消息队列依次处理。这样用户就避免等待视频转换完毕后才上传下一个视频文件,也就是说客户端用户只需要下达指令,Socket服务将自动地进行线程处理,将视频文件逐一放入消息队列并转换为目标视频文件。具体操作是Socket服务接收上传完毕指令后,根据用户填写的视频信息启动FFMPEG程序开始对文件进行转换和压缩操作。此时客户端也会显示视频目前处理的状态,如:正在转换视频文件等。视频转换完毕后,Socket服务将启动流媒体关键帧注入程序Yamdi,对视频文件注入metadata信息。主要包括创建者、关键帧、视频相关信息等。而其中最为有效的是关键帧,即注入完成后视频可支持进度条的随意拖动播放。整个视频文件的转换、压缩以及注入关键帧操作完毕后,Socket服务将视频文件存储至指定的Nginx服务器视频文件播放路径,随后删除对应的原始视频文件,并将视频转换状态写入数据库。如果用户上传了多个文件,Socket服务将对线程中下一个视频文件进行处理。处理完成后客户端浏览器会显示视频转换状态为已转换完毕。
3)Nginx服务器。
客户端可以通过Web嵌入播放器对已转换完毕的视频进行播放。视频播放采用Nginx服务器的负载均衡技术[17-21]且视频文件已注入关键帧,因此可以在Web嵌入播放器中随意拖动进度条到缓冲还未加载的位置进行播放。
服务器操作系统:CentOS 6.6。
使用编程语言:Java,JavaScript,ActionScript。
使用视频编码工具:FFMPEG,Yamdi。
使用开发工具:Eclipse,Adobe Flash Builder。
系统框架:主要采用B/S架构。
视频上传模块分为客户端模块和服务器端模块这2个子模块。客户端模块主要功能是上传视频文件以及显示进度条等,主要基于RIA技术[22]开发并支持动态数据显示,客户端上传模块的实现界面如图2所示。
图2 视频上传客户端模块
服务器端模块的主要功能是视频文件数据的接收以及返回进度数据。当通过客户端Web浏览器将视频文件上传至服务器时会启用FileUploadServlet监听类,并开始对视频进行上传操作。即首先读取配置文件和获取客户端相关参数,包括:路径、文件名、文件数据等信息,再对文件进行传输操作。与此同时通过ServletFileUpload类的setProgressListener方法将上传进度数据实时返回至客户端,传输完毕后将信息写入数据库。服务器端上传模块核心代码如下:
try {uploadedItems= upload.parseRequest(request);
Iterator i=uploadedItems.iterator();
while(i.hasNext())
{fileItem=(FileItem) i.next();
if(fileItem.isFormField()==false){
if(fileItem.getSize()>0){
File uploadedFile=null;
String myFullFileName=fileItem.getName();
slashType=(myFullFileName.lastIndexOf("\")>0)?"
\":"/";
int startIndex=myFullFileName.lastIndexOf(slashType);
myFileName=myFullFileName.substring(startIndex+1,
myFullFileName.length());//获取文件名
uploadedFile=new File(filePath,myFileName);
System.out.println(filePath+"/"+myFileName;
fileItem.write(uploadedFile);//文件写入
insert_database(myFileName,filePath,name1,name2);
//写入数据库}
}}} catch (FileUploadException e){
e.printStackTrace();}
Socket服务负责视频的转换、压缩和注入关键帧等操作。主要采用Java Socket技术和多线程技术,实现了队列管理和防阻塞机制,以此避免系统资源消耗过高出现异常等问题。Socket服务模块主要操作包括:启动多线程、调用FFMPEG进行视频转换和压缩、注入关键帧、存储转换文件、删除源文件、数据库写入等。
3.3.1 FFMPEG
FFMPEG[23-24]是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它提供了录制、转换以及流化音视频的完整解决方案,包含了先进的音频、视频编解码库libavcodec,并且可以支持多种视频格式的相互编码转换,主要有:AVI、MPEG、MOV、3GP、M4A、RMVB、RM、MP4等。除了视频转换功能以外还可支持视频压缩、视频抓图和对视频进行加水印操作等。因此本文主要采用FFMEPEG对视频进行转换、压缩以及抓图等操作。
3.3.2 FFMPEG安装
为通过FFMPEG程序对视频进行转换和压缩操作,在CentOS中安装了FFMPEG以及一些相关视频音频解码插件[25-26]。FFMPEG在转换或者播放的过程中也需要调用相关解码插件才可进行操作。已安装解码器包括:libfdk_aac、libfreetype、libmp3lame、libopus、libvorbis、libvpx、libx264、libx265等。
具体FFMPEG安装方法如下:
sudo rpm --import RPM-GPG-KEY-nux.ro
sudo rpm -Uvh nux-dextop-release-0-5.el7.nux
sudo yum install ffmpegffmpeg-devel -y
3.3.3 调用FFMPEG
Socket服务将通过调用FFMPEG程序对视频进行转换和压缩操作。但本文没有调用FFMPEG的C语言类库,而是直接通过Java的Process类调用预装好的FFMPEG程序,此方法方便简单并且可通过Java的多线程实时监听转换进度。具体调用代码如下:
Runtimert=Runtime.getRuntime();
Processproc=rt.exec("ffmpeg -y -i"+ filename+VideoCode_Parameter+upload_path+addpath+"/"+flvname1+"."+FileFormat); //转换命令
InputStream stderr=proc.getErrorStream();
InputStreamReader isr=new InputStreamReader(stderr);
BufferedReader br=new BufferedReader(isr);
String line1=null;
while((line1=br.readLine())!=null)
{System.out.println(line1);}//显示转换进度
intexitVal=proc.waitFor();
System.out.println("exitVal"+exitVal);
yamdi(upload_path+addpath+"/"+flvname1,flvname2,addpath,ID,filename);//注入关键帧
转换进度如图3所示。
图3 FFMPEG视频转换以及压缩
视频播放模块为一个独立的模块,主要采用专用Web嵌入视频播放器,并结合Nginx服务器的负载均衡技术,实现视频的在线播放和进度条的随意拖动。
为了测试并了解在线视频转换系统功能和性能,本文做了一个实验,即对系统核心模块进行单元测试,具体单元测试内容和结果如表1所示。
表1 系统单元测试
功能模块测试内容测试结果视频上传模块是否支持批量上传支持批量上传是否支持大容量文件上传系统支持在线上传4 GB以下视频文件上传用时测试经过测试上传用时合理Socket服务模块是否开启多线程开启多线程是否调用FFMPEG进行转换调用FFMPEG进行转换是否调用Yamdi对视频注入关键帧调用Yamdi对视频注入关键帧视频转换模块是否支持不同格式视频文件的转换支持AVI、MPEG、MOV、3GP、M4A、RMVB、RM、MP4、AVI、MKV、WMV等是否支持大容量文件转换支持大容量文件的转换转换用时测试多文件转换时用时较长视频播放模块是否支持在线播放支持在线播放是否支持进度条的随意拖动播放支持进度条的随意拖动播放
作为自主可控平台技术研究的一部分,为嵌入式平台提供在线视频格式转换服务和视频编码处理环境,本文研究与实现了一种基于自主可控平台的FFMPEG在线视频转换系统。首先介绍了系统设计所采用的框架以及开发环境等;然后介绍了在线视频转换系统核心模块的实现,主要包括:视频上传模块,Socket服务模块,视频转换、压缩、注入关键帧模块和视频播放模块等;最后做了系统单元测试,对系统核心功能模块和性能进行了测试。结果表明该系统支持批量上传、转换、压缩大容量视频文件,可支持不同视频文件格式的转换,并且客户端支持视频进度条的随意拖动播放。性能方面系统采用Socket队列管理和多线程防阻塞技术,因此在经过多次反复测试过程中CPU、内存占用率合理,没有出现系统异常。但对于多个文件转换、压缩用时较长等问题,主要取决于视频文件总时长,因此在后续的研究中将通过多台服务器做一个整体的负载均衡,将文件上传至不同服务器并通过Socket消息队列中的任务进行转换和压缩操作。通过这种技术方案就可以解决测试中遇到的多个文件转换用时较长等问题。