Tuesday, August 16, 2011

Upload and Convert Video/Audio File to Flash Video (flv) and Progressive Streaming using ASP.NET handler

In my previous blog here I implemented a asp.net handler for uploading file using ajax upload and I am using this file upload for uploading video and audio files. FLV is best format for website use.

But your can upload video in any format (.mov, .avi, .wav, flv). But user can see video from site in flv format best for website. ASP.NET handler is used for pseudo-streaming and flowplayer is used to show flv files. So using this application you can upload video file and after uploading video file will be converted to flv format. User can also play the uploaded FLV formatted video file using flawplayer. You can also play MPEG-4 H.264 (.mp4) formatted file using flawplayer . I will discuss about progressive streaming of .mp4 also.

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

I am using the same valum’s upload control here for uploading video/ audio file. This support multiple upload by default but I need single file upload here. 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', 'mgp', 'wmv'],
debug: true,
onComplete: function (id, fileName, responseJSON) {
………….

});
}
});





Here you can see I have changed valum’s upload options for supporting single upload and only video files. I have also changed template of upload button. I will discuss OnComplete code later.



Now suppose that user upload flv file so I do not need to convert flv format as I am displaying flv file only. But if user upload other formatted file like .mov, avi, mpeg or .wav then I want to convert into my flv format to display video from my site. FFMPEG is a very lovely tool for converting video file. This tool not only convert video in other format but also we can extract audio from video and also can generate thumbnail from video file 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"



This converted my 25MB .wav file to 1.4M flv file. I want to run this command after uploading user avi file in server but how can I run .exe file using asp.net basic authentication account. So for running “ffmpeg.exe” I have impersonate to specific user account. Here http://support.microsoft.com/kb/306158 you can see how to impersonate a specific user in code. After converting video file into flv format I have undo impersonate from that account.



 



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

ProcessStartInfo process = new ProcessStartInfo(ffmpegPhysicalPath, argument);
Process proc = new Process();
proc.StartInfo = process;
proc.Start();
proc.WaitForExit();
AuthenticationHelper.UndoImpersonation();
return Path.ChangeExtension(phyicalFilePath, "flv");
}

return string.Empty;




Here you can see command for converting video file into flash video (flv) format.  You need to set ffmpegPhysicalPath to the location of ffmpeg.exe file.



After converting video file into flv format path of flv file is sent to user. 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.



image



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 webconfig 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>
</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 well steps to implement progressive streaming using ASP.NET handler. I have 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 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



 var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader-demo1'),
……


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




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.



image



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


Playing MP3 using flowplayer



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.



image



Source Code



http://dl.dropbox.com/u/20275838/FileUploaderSol.rar