算一算,自从上次发表一篇
asp.net中用VML画数据统计图的文章后差不多有一两个月没有来博客了,今天中秋,没事做发现自己已经很久没有来博客园了.正好前几天有小做一个视频转换的Demo,现在出现很的网上在线视频其文件格式都是.FLV格式,那些视频网站大概也有一个视频转换软件,所我在也试着去做了一个demo拿出来和大家共享一下,由于自己的技术有限,做的不怎么样,愿有高人看完给
在下指点一二.呵.... 费话不多说了,下面来分解一下这个Demo.
首先,我们部署一下文件夹.在工程的目录下新建几个文件夹如下图:
UpFiles文件夹是要保存你上传的文件,PlayFiles文件夹是用于你转换后保存的文件(用于网上播放)
ImgFile文件夹是保存截取视频文件的图片,然后那两个mencoder和ffmpeg文件夹是视频转换工具.此视频转换也
可叫做mencoder+ffmpeg视频转换.
首先,在配置文件中给这些文件夹进行路径的配置.如下
<
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的源文件可以
点击这里下载.
还有其视频转换工具,由于比较大有十多MB博客上传不了.所以还需大家另外去下载.