Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

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

4.76/5 (50 votes)
1 Aug 2013CPOL5 min read 188.2K   9.3K  
Upload video/audio file and convert video to Flash video (flv) and do progressive streaming using an ASP.NET handler.

Introduction 

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

Implementation

In my previous blog here, you can see the implementation of an ASP.NET handler for uploading a file using valums AJAX upload and I am using this file upload handler for uploading video and audio files. As flv is the best format for websites, the video file is converted to flv format after upload.

Uploading Video File and Converting to Flash Video (flv) Format

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

C#
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 the template of the upload button. I will discuss the OnComplete code later.

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

I am not familiar with the 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 an 1.4M flv file. You will not be able to run the ffmpeg command using ASP.NET basic authentication. So for running ffmpeg.exe, you need to impersonate a specific user account. Here, you can see how to impersonate a specific user in code.

C#
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 the command for converting a video file into Flash video (flv) format. When you use my code, you have to set the ffmpegPhysicalPath field variable with the physical path of the ffmpeg.exe file.

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

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

After completing these steps, I send a JSON response to contain the flv location and image location.

C#
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 a Large File

You might fail to upload large files as by default IIS supports content length up to 30000000 bytes.

FlashVideoStreaming/contentlenght.png

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

XML
<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 is in byte format. Now you can upload a maximum 2G file using Valum's upload control.

Watching Progressive Streaming Video using ASP.NET Handler

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

You can download flowplayer SWF file from the FlowPlayer site. A thumbnail of the video and flv location is sent after uploading using Valum's control. So here OnComplete function code is:

JavaScript
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 the thumbnail image is set as the background and a play image is displayed in the middle. After clicking on the image, the flowplayer script will be called and a request for the flv file is send to the server and then the FLVStreaming handler will be called.

FlashVideoStreaming/videoplayer.png

Streaming MP4 Video

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

Converting Video File into MP4 Formatted Video File

The ffmpeg command for converting a video file into a h264 MP4 formatted video file is:

C#
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 the andler for MP4 can be found here. You can see that the client type is different for MP4. You can also use the JW Player. But I do not want to mix two implementations here, so I did not provide the MP4 handler here.

Streaming an MP3 Audio

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

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

Flowplayer also supports MP3 files. We can change the configuration of FlowPlayer using the following script:

JavaScript
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 the upload is complete, flowplayer will be displayed like this. And clicking on the Play button, it will call the MP3 streaming handler and run the MP3 in a progressing manner.

FlashVideoStreaming/mp3player.JPG

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)