开发视频网站,asp.net视频文件转换.flv格式

最经公司有一个小项目需要把视频转换成FLASH文件,效果就是像用户注册youku网一样,自己可以视频上传,转换成flash格式播放。
苦于以前没有做过,于是马上搜索了相关的文章,看了 http://www.cnblogs.com/xiucai/http://www.cnblogs.com/seebook/关于这方面的文章,对我帮助很大。今天第一天开博,我就记录下它们。

现在出现很多的在线视频网站,其实其文件播放的格式都是.FLV格式(开始还以为是swf了)。

首先,新建一个工程,然后我们部署一下文件夹。在工程的目录下新建几个文件夹如下图:
开发视频网站,asp.net视频文件转换.flv格式
UpFiles文件夹是要保存你上传的文件(未转换的原始视频文件)
PlayFiles文件夹是用于你转换后保存下的文件(这个转完了就是.flv的格式了,用于网上播放)
ImgFile文件夹是保存截取视频文件的图片
至于mencoder和ffmpeg文件夹。则是视频转换必须的工具引擎。没有mencoder+ffmpeg就根本没办法视频转换了.
(ffmpeg最新版本的下载地址: http://ffdshow.faireal.net/mirror/ffmpeg/
Mencoder新版本的下载地址: http://www5.mplayerhq.hu/MPlayer/releases/win32/
测试过了,我就是从这里下的。

下面开始正题。
首先,在配置文件中给这些文件夹进行路径的配置.如下
     < appSettings >
        
<!-- 工具文件夹 -->
        
< add  key ="ffmpeg"  value ="ffmpeg/ffmpeg.exe" />
    
< add  key ="mencoder"  value ="mencoder/mencoder.exe" />
    
< add  key ="mplayer"  value ="mencoder/mplayer.exe" />
        
<!-- 上传文件的路径 -->
        
< add  key ="upfile"  value ="UpFiles" />
        
<!-- 上专文件图片路径 -->
        
< add  key ="imgfile"  value ="ImgFile" />
        
<!-- 上传文件图片大小 -->
        
< add  key ="CatchFlvImgSize"  value ="240x180" />
    
< add  key ="widthSize"  value ="400" />
    
< add  key ="heightSize"  value ="350" />
        
<!-- 转换后文件路径 -->
        
< add  key ="playfile"  value ="PlayFiles" />
    
</ appSettings >
在上传.ASPX页面中

        标题:
< asp:TextBox  ID ="txtTitle"  runat ="server"  Width ="358px" ></ asp:TextBox >
        
< asp:RequiredFieldValidator  ID ="RequiredFieldValidator2"  runat ="server"  ControlToValidate ="txtTitle"
            ErrorMessage
="标题不为空" ></ asp:RequiredFieldValidator >
       
< br  />
        
< asp:FileUpload  ID ="FileUpload1"  runat ="server"  Width ="339px"   />
        
< asp:Button  ID ="btnUpload"  runat ="server"  OnClick ="btnUpload_Click"  Text ="上传视频"  Width ="70px"   />
        文件类型
< span  style ="color:Red;" > (.asf|.flv|.avi|.mpg|.3gp|.mov|.wmv|.rm|.rmvb) </ span >
            
< asp:RegularExpressionValidator  ID ="imagePathValidator"  runat ="server"  ErrorMessage ="文件类型不正确"
            ValidationGroup
="vgValidation"  Display ="Dynamic"  ValidationExpression ="^[a-zA-Z]:(\\.+)(.asf|.flv|.avi|.mpg|.3gp|.mov|.wmv|.rm|.rmvb)$"
            ControlToValidate
="FileUpload1" >
            
</ asp:RegularExpressionValidator >
        
< asp:RequiredFieldValidator  ID ="RequiredFieldValidator1"  runat ="server"  ControlToValidate ="FileUpload1"
            ErrorMessage
="文件不为空" ></ asp:RequiredFieldValidator ></ div >
        
< div  style =" height:0px; border-top:solid 1px red; font-size:0px;" ></ div >
        
< div > 上传列表. </ div >
程序工作的原理是:视频先上传上去,然后跟着就是开始转换.
所以.在CS 文件中有

这里为了方便我是用sqlDatasource数据控件做数据的操作.
using  System;
using  System.Data;
using  System.Configuration;
using  System.Web;
using  System.Web.Security;
using  System.Web.UI;
using  System.Web.UI.WebControls;
using  System.Web.UI.WebControls.WebParts;
using  System.Web.UI.HtmlControls;

public  partial  class  _Default : System.Web.UI.Page 
{
    
//  扩展名定义
     string [] strArrFfmpeg  =   new   string [] { " asf " , " avi " , " mpg " , " 3gp " , " mov "  };
    
string [] strArrMencoder  =   new   string [] { " wmv " , " rm " , " rmvb "  };
    
protected   void  Page_Load( object  sender, EventArgs e)
    {

    }
    
//
     protected   void  btnUpload_Click( object  sender, EventArgs e)
    {
        
        
string  upFileName  =   "" ;
        
if  ( this .FileUpload1.HasFile)
        {
            
string  fileName  =  PublicMethod.GetFileName( this .FileUpload1.FileName); //  GetFileName();
             if  (( string )Session[ " file " ==  fileName)
            {
                
return ;
            }
            upFileName 
=  Server.MapPath(PublicMethod.upFile  +  fileName);
            
this .FileUpload1.SaveAs(upFileName);
            
string  saveName  =  DateTime.Now.ToString( " yyyyMMddHHmmssffff " ) ;
            
string  playFile  =  Server.MapPath(PublicMethod.playFile  +  saveName);
            
string  imgFile  =  Server.MapPath(PublicMethod.imgFile  +  saveName);
            
// System.IO.File.Copy(Server.MapPath(PublicMethod.playFile + "00000002.jpg"), Server.MapPath(PublicMethod.imgFile+"aa.jpg"));
            PublicMethod pm  =   new  PublicMethod();
            
string  m_strExtension  =  PublicMethod.GetExtension( this .FileUpload1.PostedFile.FileName).ToLower();
            
if  (m_strExtension  ==   " flv " )
            {
// 直接拷贝到播放文件夹下
                System.IO.File.Copy(upFileName, playFile + " .flv " );
                pm.CatchImg(upFileName, imgFile);
            }
            
string  Extension  =  CheckExtension(m_strExtension);
            
if  (Extension  ==   " ffmpeg " )
            {
                pm.ChangeFilePhy(upFileName, playFile, imgFile);
            }
            
else   if  (Extension  ==   " mencoder " )
            {
                 pm.MChangeFilePhy(upFileName, playFile, imgFile);
            }
            InsertData(
this .txtTitle.Text, fileName,saveName);
            Session[
" file " =  fileName;
        }
        
    }
 

    
//
     private   string  CheckExtension( string  extension)
    {
        
string  m_strReturn  =   "" ;
        
foreach  ( string  var  in   this .strArrFfmpeg)
        {
            
if  (var  ==  extension)
            {
                m_strReturn 
=   " ffmpeg " break ;
            }
        }
        
if  (m_strReturn  ==   "" )
        {
            
foreach  ( string  var  in  strArrMencoder)
            {
                
if  (var  ==  extension)
                {
                    m_strReturn 
=   " mencoder " break ;
                }
            }
        }
        
return  m_strReturn;
    }
    
#region  插入数据到数据库中
    
private   void  InsertData( string  MediaName, string  fileName, string  saveName)
    {
        
// string name=fileName.Substring(0, fileName.LastIndexOf('.'));
         string  imgName  =  saveName  +   " .jpg " ; // 图片文件名;
         string  playName  =  saveName  +   " .flv " ;
        
string  sqlstr  =   " insert into Media(FMediaName,FMediaUpPath,FMediaPlayPath,FMediaImgPath) values(@MName,@MUppath,@MPlaypath,@MImgpath) " ;
        
// string constr = ConfigurationManager.ConnectionStrings["sqlcon"].ToString();
        SqlDataSource1.InsertCommand  =  sqlstr;
        SqlDataSource1.InsertCommandType 
=  SqlDataSourceCommandType.Text; //  CommandType.Text;
        SqlDataSource1.InsertParameters.Add( " MName " ,MediaName);
        SqlDataSource1.InsertParameters.Add(
" MUppath " ,PublicMethod.upFile + fileName);
        SqlDataSource1.InsertParameters.Add(
" MPlaypath " ,PublicMethod.playFile + playName);
        SqlDataSource1.InsertParameters.Add(
" MImgpath " ,PublicMethod.imgFile + imgName);
        SqlDataSource1.Insert();
    }
    
#endregion
 

}
PublicMethod类如下:
在这个类里面主要是做文件转换和保存,在转换文件的时候CPU的利用率可以达100%.

它的主要原理是另起一个进程在转换的时候你会发现你的进程里多了一个.
using  System;
using  System.Configuration;

///   <summary>
///  Summary description for PublicMethod
///   </summary>
public   class  PublicMethod:System.Web.UI.Page
{
    
public  PublicMethod()
    {
         
    }
    
// 文件路径
     public   static   string  ffmpegtool  =  ConfigurationManager.AppSettings[ " ffmpeg " ];
    
public   static   string  mencodertool  =  ConfigurationManager.AppSettings[ " mencoder " ];
    
public   static   string  mplayertool  =  ConfigurationManager.AppSettings[ " mplayer " ];
    
public   static   string  upFile  =  ConfigurationManager.AppSettings[ " upfile " +   " / " ;
    
public   static   string  imgFile  =  ConfigurationManager.AppSettings[ " imgfile " +   " / " ;
    
public   static   string  playFile  =  ConfigurationManager.AppSettings[ " playfile " +   " / " ;
    
// 文件图片大小
     public   static   string  sizeOfImg  =  ConfigurationManager.AppSettings[ " CatchFlvImgSize " ];
    
// 文件大小
     public   static   string  widthOfFile  =  ConfigurationManager.AppSettings[ " widthSize " ];
    
public   static   string  heightOfFile  =  ConfigurationManager.AppSettings[ " heightSize " ];
    
//     //   // 获取文件的名字
     public   static   string  GetFileName( string  fileName)
    {
        
int  i  =  fileName.LastIndexOf( " \\ " +   1 ;
        
string  Name  =  fileName.Substring(i);
        
return  Name;
    }
    
// 获取文件扩展名
     public   static   string  GetExtension( string  fileName)
    {
        
int  i  =  fileName.LastIndexOf( " . " ) + 1 ;
        
string  Name  =  fileName.Substring(i);
        
return  Name;
    }
    
//
     #region   // 运行FFMpeg的视频解码,(这里是绝对路径)
    
///   <summary>
    
///  转换文件并保存在指定文件夹下面(这里是绝对路径)
    
///   </summary>
    
///   <param name="fileName"> 上传视频文件的路径(原文件) </param>
    
///   <param name="playFile"> 转换后的文件的路径(网络播放文件) </param>
    
///   <param name="imgFile"> 从视频文件中抓取的图片路径 </param>
    
///   <returns> 成功:返回图片虚拟地址;   失败:返回空字符串 </returns>
     public    string  ChangeFilePhy( string  fileName,  string  playFile,  string  imgFile)
    {
        
// 取得ffmpeg.exe的路径,路径配置在Web.Config中,如:<add   key="ffmpeg"   value="E:\51aspx\ffmpeg.exe"   />   
         string  ffmpeg  =  Server.MapPath(PublicMethod.ffmpegtool);
        
if  (( ! System.IO.File.Exists(ffmpeg))  ||  ( ! System.IO.File.Exists(fileName)))
        {
            
return   "" ;
        }

        
// 获得图片和(.flv)文件相对路径/最后存储到数据库的路径,如:/Web/User1/00001.jpg   
       
        
string  flv_file  =  System.IO.Path.ChangeExtension(playFile,  " .flv " );


        
// 截图的尺寸大小,配置在Web.Config中,如:<add   key="CatchFlvImgSize"   value="240x180"   />   
         string  FlvImgSize  =  PublicMethod.sizeOfImg;

        System.Diagnostics.ProcessStartInfo FilestartInfo 
=   new  System.Diagnostics.ProcessStartInfo(ffmpeg);

        FilestartInfo.WindowStyle 
=  System.Diagnostics.ProcessWindowStyle.Hidden;

        FilestartInfo.Arguments 
=   "  -i  "   +  fileName  +   "  -ab 56 -ar 22050 -b 500 -r 15 -s  "   +  widthOfFile  +   " x "   +  heightOfFile  +   "   "   +  flv_file;
        
// ImgstartInfo.Arguments = "   -i   " + fileName + "   -y   -f   image2   -t   0.05   -s   " + FlvImgSize + "   " + flv_img;

        
try
        {
            
// 转换
            System.Diagnostics.Process.Start(FilestartInfo);
            
// 截图
            CatchImg(fileName, imgFile);
            
// System.Diagnostics.Process.Start(ImgstartInfo);
        }
        
catch
        {
            
return   "" ;
        }
        
//
         return   "" ;
    }
    
//
     public   string  CatchImg( string  fileName, string  imgFile)
    {
        
//
         string  ffmpeg  =  Server.MapPath(PublicMethod.ffmpegtool);
        
//
         string  flv_img  = imgFile + " .jpg " ;
        
//
         string  FlvImgSize  =  PublicMethod.sizeOfImg;
        
//
        System.Diagnostics.ProcessStartInfo ImgstartInfo  =   new  System.Diagnostics.ProcessStartInfo(ffmpeg);
        ImgstartInfo.WindowStyle 
=  System.Diagnostics.ProcessWindowStyle.Hidden;
        
//
        ImgstartInfo.Arguments  =   "    -i    "   +  fileName  +   "   -y  -f  image2   -ss 2 -vframes 1  -s    "   +  FlvImgSize  +   "     "   +  flv_img;
        
try
        {
            System.Diagnostics.Process.Start(ImgstartInfo);
        }
        
catch
        {
            
return   "" ;
        }
        
//
         if  (System.IO.File.Exists(flv_img))
        {
            
return  flv_img;
        }

        
return   "" ;
    }
    
#endregion
    
//
     #region   // 运行FFMpeg的视频解码,(这里是(虚拟)相对路径)
    
///   <summary>
    
///  转换文件并保存在指定文件夹下面(这里是相对路径)
    
///   </summary>
    
///   <param name="fileName"> 上传视频文件的路径(原文件) </param>
    
///   <param name="playFile"> 转换后的文件的路径(网络播放文件) </param>
    
///   <param name="imgFile"> 从视频文件中抓取的图片路径 </param>
    
///   <returns> 成功:返回图片虚拟地址;   失败:返回空字符串 </returns>
     public    string  ChangeFileVir( string  fileName,  string  playFile,  string  imgFile)
    {
        
// 取得ffmpeg.exe的路径,路径配置在Web.Config中,如:<add   key="ffmpeg"   value="E:\51aspx\ffmpeg.exe"   />   
         string  ffmpeg  =  Server.MapPath(PublicMethod.ffmpegtool);
        
if  (( ! System.IO.File.Exists(ffmpeg))  ||  ( ! System.IO.File.Exists(fileName)))
        {
            
return   "" ;
        }

        
// 获得图片和(.flv)文件相对路径/最后存储到数据库的路径,如:/Web/User1/00001.jpg   
         string  flv_img  =  System.IO.Path.ChangeExtension(Server.MapPath(imgFile),  " .jpg " );
        
string  flv_file  =  System.IO.Path.ChangeExtension(Server.MapPath(playFile),  " .flv " );


        
// 截图的尺寸大小,配置在Web.Config中,如:<add   key="CatchFlvImgSize"   value="240x180"   />   
         string  FlvImgSize  =  PublicMethod.sizeOfImg;

        System.Diagnostics.ProcessStartInfo FilestartInfo 
=   new  System.Diagnostics.ProcessStartInfo(ffmpeg);
        System.Diagnostics.ProcessStartInfo ImgstartInfo 
=   new  System.Diagnostics.ProcessStartInfo(ffmpeg);

        FilestartInfo.WindowStyle 
=  System.Diagnostics.ProcessWindowStyle.Hidden;
        ImgstartInfo.WindowStyle 
=  System.Diagnostics.ProcessWindowStyle.Hidden;
        
// 此处组合成ffmpeg.exe文件需要的参数即可,此处命令在ffmpeg   0.4.9调试通过 
        
// ffmpeg -i F:\01.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\test.flv
        FilestartInfo.Arguments  =   "  -i  "   +  fileName  +   "  -ab 56 -ar 22050 -b 500 -r 15 -s  "   +  widthOfFile  +   " x "   +  heightOfFile  +   "   "   +  flv_file;
        ImgstartInfo.Arguments 
=   "    -i    "   +  fileName  +   "    -y   -f   image2   -t   0.001   -s    "   +  FlvImgSize  +   "     "   +  flv_img;

        
try
        {
            System.Diagnostics.Process.Start(FilestartInfo);
            System.Diagnostics.Process.Start(ImgstartInfo);
        }
        
catch
        {
            
return   "" ;
        }

        
/**/
        
/// 注意:图片截取成功后,数据由内存缓存写到磁盘需要时间较长,大概在3,4秒甚至更长;   
        
/// 这儿需要延时后再检测,我服务器延时8秒,即如果超过8秒图片仍不存在,认为截图失败;   
        
/// 此处略去延时代码.如有那位知道如何捕捉ffmpeg.exe截图失败消息,请告知,先谢过!   
         if  (System.IO.File.Exists(flv_img))
        {
            
return  flv_img;
        }

        
return   "" ;
    }
    
#endregion

    
#region   // 运行mencoder的视频解码器转换(这里是(绝对路径))
    
public   string  MChangeFilePhy( string  vFileName,  string  playFile,  string  imgFile)
    {
        
string  tool  =  Server.MapPath(PublicMethod.mencodertool);
        
// string mplaytool = Server.MapPath(PublicMethod.ffmpegtool);
        
        
if  (( ! System.IO.File.Exists(tool))  ||  ( ! System.IO.File.Exists(vFileName)))
        {
            
return   "" ;
        }

        
string  flv_file  =  System.IO.Path.ChangeExtension(playFile,  " .flv " );


        
// 截图的尺寸大小,配置在Web.Config中,如:<add   key="CatchFlvImgSize"   value="240x180"   />   
         string  FlvImgSize  =  PublicMethod.sizeOfImg;

        System.Diagnostics.ProcessStartInfo FilestartInfo 
=   new  System.Diagnostics.ProcessStartInfo(tool);
       
        FilestartInfo.WindowStyle 
=  System.Diagnostics.ProcessWindowStyle.Hidden;
        FilestartInfo.Arguments 
=   "   "   +  vFileName  +   "  -o  "   +  flv_file  +   "  -of lavf -lavfopts
   i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc
-lavcopts vcodec=flv:vbitrate=200:mbd=2:mv0:trell:v4mv:cbp:last_pred=1:dia=-1:cmp=0:vb_strategy=1
-vf scale=
"   +  widthOfFile  +   " : "   + heightOfFile  +   "  -ofps 12 -srate 22050 " ;
        
try
        {
            System.Diagnostics.Process.Start(FilestartInfo);
            CatchImg(flv_file, imgFile);
        }
        
catch
        {
            
return   "" ;
        } 
        
//
         return   "" ;
    }
    
#endregion
}

全文的主要内容就在这里了

此DEMO的源文件可以 点击这里下载.


数据库

先创建 数据库 test
USE [test]
GO
/****** 对象:  Table [dbo].[Media]    脚本日期: 12/22/2007 10:16:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Media](
 [FMediaName] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
 [FMediaUpPath] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
 [FMediaPlayPath] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
 [FMediaImgPath] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
 [FID] [int] IDENTITY(1,1) NOT NULL,
 [FPostDate] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
 [FContent] [varchar](500) COLLATE Chinese_PRC_CI_AS NULL,
 CONSTRAINT [PK_Media] PRIMARY KEY CLUSTERED
(
 [FID] ASC
) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF




你可能感兴趣的:(asp.net)