Introduction

In my previous blog here you can see implementation of a asp.net handler for uploading file using valums ajax upload and I am using this file upload handler for uploading video and audio files. As I flv is best format for website so video file is converted to flv format after upload.

Using this application you can upload video in any format (.mov, .avi, .wav, flv). If you do not upload video file in flv format then this will be converted to flv file using ffmpeg for progressive streaming. ASP.NET handler is used for pseudo-streaming and flowplayer is used to show flv files. . You can also play MPEG-4 H.264 (.mp4) formatted file using flawplayer . I will discuss about progressive streaming of .mp4 also here. 


Implementation  

Uploading Video File And Convert to Flash Video (flv) Format

In my previous article I have shown how can I upload image file using valum's ajax upload using ASP.NET handler.I am using the same valum’s upload control for uploading video/ audio file. This supports multiple upload by default but you can set params to upload single files only by setting paramter multiple:false. Also I have given restriction in allowed extensions.  

   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
                        }
                    });
                }
            });


In the above code snippet valum’s upload options are changed to  support single upload and only video files. I have also changed template of upload button. I will discuss OnComplete code later.

As user is watching progressive stream of flv files so when user is uploading a flv file then only thumbnail is created from that file . But when user uploads other formatted file like .mov, avi, mpeg or .wav then video file is converted to flv format. FFMPEG is a very lovely tool for converting video file. Using this tool you  can extract audio from video and also can generate thumbnail from video file specific frame.

I am not familiar with ffmpeg command arguments so I used standard options for Flash Video (flv). The format I have got from WinFF is


"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" 

Using this code snippet I have converted my 25MB .wav file to 1.4M flv file. You will not able to run ffmpeg command using asp.net basic authentication. So for running “ffmpeg.exe” you need to  impersonate to specific user account. Here http://support.microsoft.com/kb/306158 you can see how to impersonate a specific user in code. 

  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"); 

Here you can see command for converting video file into flash video (flv) format. When you will use my code you have to set ffmpegPhysicalPath  field variable with the physical path of  ffmpeg.exe file.   

You can send the flv file path to client when flv conversion is completed and flowplayer will ask ASP.NET handler for streaming the video. But  I also want to show a thumbnail splash image so that user can understand that video is uploaded. And on clicking splash image ASP.NET handler will be called and user can see video using flawplayer.

Generating thumbnail image from video file is very easy using ffmpeg . In flawplayer forum you can see the details about generating thumbnail from video http://flowplayer.org/tutorials/generating-thumbs.html.

After completing these steps I have sent a JSON response to containing flv location and image location.

  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) + "\"}");

Uploading Large File

You might be failed to upload large as by default IIS supported content length is 30000000 Byte.

contentlenght.png

You also need to set maxRequestLength in webconfig otherwise you will get exception while fetching large file. Suppose that I support maximum 2G size file in my site. My web.config settings are : 

 <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> 

Here maxRequestLength is in KB and maxAllowedContentLength in Byte format. Now you can upload maximum 2G file using Valums upload control.

Watching Progressive Streaming Video using ASP.NET Handler

Flowplayer forum http://flowplayer.org/forum/5/14702#post-14702 discussed steps to implement progressive streaming using ASP.NET handler very well so for IIS settings you can read there. I have just made copy paste and used same code in my handler. So when flowplayer request to server to get flv file then FLVStreaming handler will be called which will provide flv file progressively. 

You can download flowplayer swf file from FlowPlayer site. As tumbnail of video and flv locaiton is send after uploading using valums control. So code here OnComplete function is

 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
                        }
                    });
                }
            });

You can see here thumbnail image is set as background and a play image displayed in middle. after clicking on the image flowplayer script will be called and request for flv file to server and then FLVStreaming handler will be called.

videoplayer.png

Streaming MP4 Video

FlowPlayer also support H.264 mp4 video format. You can also use JW Player.

Converting video file into mp4 formatted video file

ffmpeg command for converting video file into h264 mp4 formatted video file is 

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"));

              

The implementation of handler for mp4 can be found here http://www.mediasoftpro.com/articles/asp.net-progressive-mp4-streaming.html. You can see there client type is different for mp4. You can also use JW Player. But I do not want to mix here two implementation so I did not provide mp4 handler here.

Streaming MP3 Audio

Then handler for MP3 audio is same as flv player but just content- type is different.

   context.Response.AppendHeader("Content-Type", "audio/mp3");
   context.Response.AppendHeader("Content-Length", fs.Length.ToString()); 

Flowplayer is also support mp3 file. We can change configuration of FlowPlayer using the following script.

 

  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();
                            }
                        }

                    });
                }
            }); 

After upload is complete the flowplayer will be displayed like this. And clicking on play button it will call MP3Streaming handler and run mp3 in progressing manner.

mp3player.JPG

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"