最经公司有一个小项目需要把视频转换成FLASH文件,效果就是像用户注册youku网一样,自己可以视频上传,转换成flash格式播放。
苦于以前没有做过,于是马上搜索了相关的文章,看了http:
现在出现很多的在线视频网站,其实其文件播放的格式都是.FLV格式(开始还以为是swf了)。
首先,新建一个工程,然后我们部署一下文件夹。在工程的目录下新建几个文件夹如下图:
UpFiles文件夹是要保存你上传的文件(未转换的原始视频文件)
PlayFiles文件夹是用于你转换后保存下的文件(这个转完了就是.flv的格式了,用于网上播放)
ImgFile文件夹是保存截取视频文件的图片
至于mencoder和ffmpeg文件夹。则是视频转换必须的工具引擎。没有mencoder+ffmpeg就根本没办法视频转换了.
(ffmpeg最新版本的下载地址:http:
Mencoder新版本的下载地址:http:
测试过了,我就是从这里下的。
下面开始正题。
首先,在配置文件中给这些文件夹进行路径的配置.如下
<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);
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);
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
imgName = saveName +
".jpg"
;
string
playName = saveName +
".flv"
;
string
sqlstr =
"insert into Media(FMediaName,FMediaUpPath,FMediaPlayPath,FMediaImgPath) values(@MName,@MUppath,@MPlaypath,@MImgpath)"
;
SqlDataSource1.InsertCommand = sqlstr;
SqlDataSource1.InsertCommandType = SqlDataSourceCommandType.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)
{
string
ffmpeg = Server.MapPath(PublicMethod.ffmpegtool);
if
((!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(fileName)))
{
return
""
;
}
string
flv_file = System.IO.Path.ChangeExtension(playFile,
".flv"
);
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;
try
{
System.Diagnostics.Process.Start(FilestartInfo);
CatchImg(fileName, imgFile);
}
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)
{
string
ffmpeg = Server.MapPath(PublicMethod.ffmpegtool);
if
((!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(fileName)))
{
return
""
;
}
string
flv_img = System.IO.Path.ChangeExtension(Server.MapPath(imgFile),
".jpg"
);
string
flv_file = System.IO.Path.ChangeExtension(Server.MapPath(playFile),
".flv"
);
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;
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);
if
((!System.IO.File.Exists(tool)) || (!System.IO.File.Exists(vFileName)))
{
return
""
;
}
string
flv_file = System.IO.Path.ChangeExtension(playFile,
".flv"
);
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
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
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法