65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (49投票s)

2011年8月16日

CPOL

5分钟阅读

viewsIcon

190179

downloadIcon

9333

上传视频/音频文件,并使用 ASP.NET handler 将视频转换为 Flash Video (flv) 并实现渐进式流。

介绍 

使用此应用程序,您可以上传任何格式的视频(.mov.avi.wavflv)。如果您上传的不是 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 文件时,只会从该文件中创建一个缩略图。但当用户上传其他格式的文件,如 .movavimpeg.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 字节。

FlashVideoStreaming/contentlenght.png

您还需要在 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。

FlashVideoStreaming/videoplayer.png

流式传输 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。

FlashVideoStreaming/mp3player.JPG

© . All rights reserved.