使用 ASP.NET Handler 上传和转换视频文件为 Flash Video (flv) 和渐进式流






4.76/5 (49投票s)
上传视频/音频文件,并使用 ASP.NET handler 将视频转换为 Flash Video (flv) 并实现渐进式流。
介绍
使用此应用程序,您可以上传任何格式的视频(.mov、.avi、.wav、flv)。如果您上传的不是 flv 格式的视频文件,它将使用 ffmpeg 转换为 flv 文件以实现渐进式流。ASP.NET handler 用于伪流式传输,flowplayer 用于显示 flv 文件。您还可以使用 flawplayer 播放 MPEG-4 H.264 (.mp4) 格式的文件。我也会在这里讨论 .mp4 的渐进式流。
实现
在我之前的博客 这里,您可以看到使用 valums AJAX upload 实现 ASP.NET handler 的文件上传,我将此文件上传 handler 用于上传视频和音频文件。由于 flv 是网站的最佳格式,因此上传后视频文件会被转换为 flv 格式。
上传视频文件并转换为 Flash Video (flv) 格式
在我之前的文章中,我展示了如何使用 valum 的 AJAX upload 和 ASP.NET handler 上传图片文件。我正在使用相同的 valum 上传控件来上传视频/音频文件。默认情况下,它支持多文件上传,但您可以通过设置参数 multiple:false
来仅上传单个文件。我还设置了允许扩展名的限制。
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader-demo1'),
action: 'FileUpload.ashx',
template: '<div class="qq-uploader">' +
'<div class="qq-upload-drop-area"><span>Drop files here to upload
</span></div>' +
'<div class="qq-upload-button">Upload a video</div>' +
'<ul class="qq-upload-list"></ul>' +
'</div>',
multiple: false,
allowedExtensions: ['flv', 'mov', 'mp4', 'avi', '3gp', 'mgp', 'wmv'],
debug: true,
onComplete: function (id, fileName, responseJSON) {
if (responseJSON.success)
$("#videoContainer").append("<div class='player'
style='display:block;width:400px;height:400px;
background-image:url(" + responseJSON.image + ");
' href='" + responseJSON.path + "'>
<img src='images/play_large.png' alt='Play this video' />
</div>");
flowplayer("div.player", "Scripts/flowplayer/flowplayer-3.2.7.swf", {
clip: {
autoPlay: false,
autoBuffering: true
}
});
}
});
在上面的代码片段中,valum 的上传选项已更改为支持单文件上传和仅限视频文件。我还更改了上传按钮的模板。稍后我将讨论 OnComplete
代码。
当用户观看 flv 文件的渐进式流时,当用户上传 flv 文件时,只会从该文件中创建一个缩略图。但当用户上传其他格式的文件,如 .mov、avi、mpeg 或 .wav 时,视频文件将被转换为 flv 格式。 FFMPEG 是一个非常出色的视频文件转换工具。使用此工具,您可以从视频中提取音频,还可以从视频文件的特定帧生成缩略图。
我不熟悉 ffmpeg 的命令参数,所以我使用了 Flash Video (flv) 的标准选项。我从 WinFF 获得的格式是
"ffmpeg.exe" -i "sample.avi" -vcodec flv -f flv -r 29.97
-s 320x240 -aspect 4:3 -b 300k -g 160 -cmp dct -subcmp dct
-mbd 2 -flags +aic+cbp+mv0+mv4 -trellis 1 -ac 1 -ar 22050 -ab 56k "sample.flv"
使用此代码片段,我将我的 25MB .wav 文件转换为 1.4M 的 flv 文件。您将无法使用 ASP.NET 基本身份验证运行 ffmpeg 命令。因此,要运行 ffmpeg.exe,您需要模拟一个特定的用户帐户。 在这里,您可以看到如何在代码中模拟特定用户。
if (Path.GetExtension(phyicalFilePath).Equals(".flv")) return phyicalFilePath;
if (AuthenticationHelper.ImpersonateValidUser("user", ".", "*******"))
{
var argument = string.Format("-i {0} -vcodec flv -f flv -r 29.97
-s 320x240 -aspect 4:3 -b 300k -g 160 -cmp dct -subcmp dct
-mbd 2 -flags +aic+cbp+mv0+mv4 -trellis 1 -ac 1 -ar 22050
-ab 56k {1}", phyicalFilePath,
Path.ChangeExtension(phyicalFilePath, "flv"));
// var argument = string.Format("-i {0} -crf 35.0
-vcodec libx264 -acodec libfaac -ar 48000 -ab 128k
-coder 1 -flags +loop -cmp +chroma -partitions
+parti4x4+partp8x8+partb8x8 -me_method hex -subq 6 -me_range 16
-g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71
-b_strategy 1 -threads 0 {1}", phyicalFilePath,
Path.ChangeExtension(phyicalFilePath, "mp4"));
ProcessStartInfo process = new ProcessStartInfo(ffmpegPhysicalPath, argument);
Process proc = new Process();
proc.StartInfo = process;
proc.Start();
proc.WaitForExit();
AuthenticationHelper.UndoImpersonation();
return Path.ChangeExtension(phyicalFilePath, "flv");
在这里,您可以看到将视频文件转换为 Flash Video (flv) 格式的命令。当您使用我的代码时,您需要将 ffmpegPhysicalPath
字段变量设置为 ffmpeg.exe 文件的物理路径。
当 flv 转换完成后,您可以将 flv 文件路径发送到客户端,然后 flowplayer 将请求 ASP.NET handler 来流式传输视频。但我也想显示一个缩略图作为启动图像,以便用户了解视频已上传。点击启动图像后,将调用 ASP.NET handler,用户可以使用 flawplayer 查看视频。
使用 ffmpeg 从视频文件中生成缩略图非常容易。在 flawplayer 论坛中,您可以找到有关从视频生成缩略图的详细信息:http://flowplayer.org/tutorials/generating-thumbs.html。
完成这些步骤后,我发送一个 JSON 响应来包含 flv 位置和图像位置。
var flvpath = ConvertToFLV(phyicalFilePath);
var tumbnail = CreateThumbnail(phyicalFilePath);
context.Response.Write("{success:true, name:\"" +
filename + "\", path:\"" + path + "/" +
Path.GetFileName(flvpath) + "\", image:\"" +
path + "/" + Path.GetFileName(tumbnail) + "\"}");
上传大文件
您可能会因为上传大文件而失败,因为默认情况下 IIS 支持的内容长度最多为 30000000 字节。
您还需要在 web.config 中设置 maxRequestLength
,否则在获取大文件时会收到异常。假设我的网站支持最大 2 GB 的文件。我的 web.config 设置是
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime maxRequestLength="4124672" requestValidationMode="2.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4223664128"></requestLimits>
</requestFiltering>
</security>
<handlers>
<add name="MP3Streaming" path="*.mp3" verb="*" type="MP3Streaming"
resourceType="Unspecified" preCondition="integratedMode" />
<add name="flvStreaming" path="*.flv" verb="*" type="FLVStreaming"
resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>
此处 maxRequestLength
的单位是 KB,maxAllowedContentLength
的单位是字节。现在您可以使用 Valum 的上传控件上传最大 2G 的文件。
使用 ASP.NET Handler 观看渐进式流视频
Flowplayer 论坛 http://flowplayer.org/forum/5/14702#post-14702 很好地讨论了使用 ASP.NET handler 实现渐进式流的步骤,因此对于 IIS 设置,您可以阅读那里的信息。我只是复制粘贴并使用了我的 handler 中的相同代码。所以当 flowplayer 请求服务器获取 flv 文件时,FLVStreaming
handler 将被调用,它将渐进式地提供 flv 文件。
您可以从 FlowPlayer 网站下载 flowplayer SWF 文件。上传完成后,会使用 Valum 的控件发送视频缩略图和 flv 位置。所以这里的 OnComplete
函数代码是
onComplete: function (id, fileName, responseJSON) {
if (responseJSON.success)
$("#videoContainer").append("<div class='player'
style='display:block;width:400px;height:400px;
background-image:url(" + responseJSON.image + ");
' href='" + responseJSON.path + "'>
<img src='images/play_large.png' alt='Play this video' />
</div>");
flowplayer("div.player",
"Scripts/flowplayer/flowplayer-3.2.7.swf", {
clip: {
autoPlay: false,
autoBuffering: true
}
});
}
});
您可以在这里看到缩略图被设置为背景,并且中间显示了一个播放图像。点击图像后,将调用 flowplayer 脚本,并将 flv 文件的请求发送到服务器,然后将调用 FLVStreaming
handler。
流式传输 MP4 视频
FlowPlayer 还支持 H.264 mp4 视频格式。您也可以使用 JW Player。
将视频文件转换为 MP4 格式视频文件
将视频文件转换为 h264 MP4 格式视频文件的 ffmpeg 命令是
var argument = string.Format("-i {0} -crf 35.0 -vcodec libx264
-acodec libfaac -ar 48000 -ab 128k -coder 1 -flags +loop
-cmp +chroma -partitions +parti4x4+partp8x8+partb8x8
-me_method hex -subq 6 -me_range 16 -g 250 -keyint_min 25
-sc_threshold 40 -i_qfactor 0.71 -b_strategy 1 -threads 0 {1}",
phyicalFilePath, Path.ChangeExtension(phyicalFilePath, "mp4"));
MP4 handler 的实现可以在 这里找到。您可以看到 MP4 的客户端类型不同。您也可以使用 JW Player。但我想避免在此处混合两种实现,因此我没有在此处提供 MP4 handler。
流式传输 MP3 音频
MP3 音频的 handler 与 flv 播放器相同,只是 content-type
不同。
context.Response.AppendHeader("Content-Type", "audio/mp3");
context.Response.AppendHeader("Content-Length", fs.Length.ToString());
Flowplayer 也支持 MP3 文件。我们可以使用以下脚本更改 FlowPlayer
的配置
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader-demo2'),
action: 'AudioUpload.ashx',
multiple: false,
template: '<div class="qq-uploader">' +
'<div class="qq-upload-drop-area"><span>Drop files here to upload
</span></div>' +
'<div class="qq-upload-button">Upload a mp3</div>' +
'<ul style="display:none" class="qq-upload-list"></ul>' +
'</div>',
allowedExtensions: ['mp3'],
debug: true,
onComplete: function (id, fileName, responseJSON) {
if (responseJSON.success)
$("#audioContainer").append("<a id='audioPlayer'
style='display:block;height:30px;' href='" + responseJSON.path + "'/>");
$f("audioPlayer", "Scripts/flowplayer/flowplayer-3.2.7.swf", {
// fullscreen button not needed here
plugins: {
controls: {
fullscreen: false,
height: 30,
autoHide: false
}
},
clip: {
autoPlay: false,
// optional: when playback starts close the first
// audio playback
onBeforeBegin: function () {
$f("player").close();
}
}
});
}
});
上传完成后,flowplayer 将显示如下。点击播放按钮,它将调用 MP3 流式传输 handler 并以渐进的方式播放 MP3。