Asynchronously streaming video with ASP.NET Web API

Strath

January 3rd, 2013

Asynchronously streaming video with ASP.NET Web API

Because HTTP programming model is really powerful

A lot of people think that ASP.NET Web API is basically a fancy framework for building APIs – which couldn’t be further from the truth. Web API is mainly about the new .NET HTTP programming model it brings to the table – embracing HTTP to perform a whole magnitude of web related tasks; and APIs are just a small portion of that. Hopefully if you follow this blog, you have seen examples of that already, as we often wander in the unkown areas of ASP.NET Web API, beyond building “traditional” APIs.

Today, let’s go back to the HTTP programming model and use Web API to asynchronously stream videos.

More after the jump.

The concept of asynchronous streaming

To perform the async streaming task, we will revert to the class we already previously used on this blog – and that is PushStreamContent. It allows the developer to progressively push packets of data down to the receiving client. Previously, we used PushStreamContent and JavaScript’s Server Sent Events to create an HTML5 chat.

In our new scenario, we will read the video stream from the file on the server’s hard drive, and flush it down to the client (using PushStreamContent) in the packets of 65 536 bytes. The streaming video playback could then start immediately (client doesn’t have to wait for the entire video to be flushed down), without causing unnecessary load on our server, especially as the process of writing to the client happens asynchronously. Once the client disconnects, the writing stops.

Implementation

PushStreamContent takes an Action in its constructor:

This Action is called as soon as the output stream (HTTP content to be flushed to the client) becomes available.

Therefore, we could create a small helper class, which would read the from the disk, and expose this activity for PushStreamContent to call repeatedly.

This class is obviously little simplified, for the sake of demo purposes, but hopefully you get the idea. We allow the consumer of the class to give as information about the file (for which we arbitrarily look in a specific location, the Downloads folder in this case). In the WriteToStream method, we proceed to read the file progressively and flush these bits to the output stream.

Notice that the signature of this method matches the Action expected by PushStreamContent and as a result can be used by it.

Now let’s move to the controller action, which, by now, will be very simple (all the heavy lifting happens in the above VideoStream class).

We allow the client to pass video info (name, extension), construct the instance of VideoStream and then create and instance of PushStreamContent which gets returned to the client.

All we need now is just a route registration:

Consuming the asynchronous video stream

We can now make an HTML5 web page, with the video tag.

In this case, I will be requesting this video: C:\Users\Filip\Downloads\CkY96QuiteBitterBeings.webm.

If we run this in the browser that supports WebM, we could see that the video (especially if you open the network inspection console) is streamed rather than loaded at once. To better illustrate this, I have recorded a short video which shows the application in action. I’ve put a breakpoint inside WriteToStream method, to show that subsequent packets of video get sent down *after* the playback has already started; the client can commence the playback already after the first 64kB packet. Also, as soon as the breakpoint hits, nothing more gets sent to the client, yet the browser still continues the playback of what it has already received.

Video below (choose 480p when playing for better quality):

Summary

While there are arguably many better solution for video streaming (media protocols, media servers and so on), in my opinion, this type of functionality is a pretty nifty example of how flexible Web API can be in terms of working with HTTP programming – and how many different things it can do.

On a side, PushStreamContent itself is a very interesting class, and if used correctly, can be a very powerful weapon in the arsenal of Web API developer. A very interesting article about a similar topic (async with PushStreamContent) can be found here, by Andrés Vettor. Really worth a read!

Be Sociable, Share!

  • http://twitter.com/sumitkm Sumit Maitra

    Very nifty indeed!

  • daniellang

    Filip, this is a very awesome post. I’d be interested to see usage scenarios other than video streaming where we could take advantage of streaming content. Would you say it would be wise to use it for streaming stock tickers and other realtime-data or should we then use SignalR instead?

  • http://www.timacheson.com/ Tim Acheson

    Cool! Would it be more accurate to describe this as progressive download, rather than streaming?

    • http://www.strathweb.com/ Filip W

      yes you are right, in the strict technical terms, since we deal with HTTP and no streaming server is involved, that would be progressive download. With that said, that wouldn’t make such catchy post title :-)

      • http://www.timacheson.com/ Tim Acheson

        Agreed ;)

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1266

  • Pingback: Dew Drop – December 4, 2012 (#1,475) | Alvin Ashcraft's Morning Dew

  • Pingback: Asynchronously streaming video with ASP.NET Web API – StrathWeb | Web Tech News

  • http://www.facebook.com/people/Bill-Clinton/100001363411575 Bill Clinton

    it would be great if we could see the video thanks..

    • http://www.strathweb.com/ Filip W

      sorry :) “Your account has reached the bandwidth limit and your content has been disabled. Viewers will no longer be able to access any content in your account.” Will re-upload the clip elsewhere.

      • http://www.strathweb.com/ Filip W

        done

  • Pingback: Interesting .NET Links - January 5 , 2012 | TechBlog

  • http://www.facebook.com/thinnguyentruong Nguyen Truong Thin

    Nice posts! Thank you!

  • http://www.facebook.com/people/Dharmesh-Sharma/100000317643550 Dharmesh Sharma

    realy nice work

  • Pingback: Microsoft exam 70-487 study guide | alertcoding

  • Anil Chakrahari

    can you share a demo project, it will be very useful

  • Himanshu Hajariwala

    Really nice post with Web API

  • gideon cohn

    Suppose I have a video that is 2 hours long. I use this method on it, and a user drags the video tag control slider all the way to 1 hour and 59 minutes. Can this method cope with that? Can the video-tag api also cope with it?

  • Rahul Behal

    Hi Fillip

    Thanks for the post!

    However, I am facing one issue – Video stops playing after some time – let us say plays for 9 sec out of 4 minutes 20 sec.

    I used the same code above, debugged it and found that stream reading/writing has

    finished after 9 sec.

    Can you please suggest the way ahead. I am using chrome 24.0.1312.57 m

    Thanks a lot,
    Rahul

  • Nahaz Nizam

    pls send me a sample project for this .or how to achieve this synchronous video streaming in normal asp.net web application

    • No Bugz

      for normal web application:
      create Generic Handler (add new item –> select generic handler)

      It will create new handler, but inherit from IHttpHandler with this method:
      public void ProcessRequest(HttpContext context)

      Modify class inherit to:
      public class RequestClip : HttpTaskAsyncHandler

      and modify method to:
      public override async Task ProcessRequestAsync(HttpContext context)

      then insert two lines of code:
      context.ThreadAbortOnTimeout = false;
      await doJobAsync(context);

      implement method: doJabAsync(HttpContext context):
      It too long. leave your email, I will send you the sample code

      • noithatavalo

        thanks you for your post,
        Can you send me your code(i’m a beginner), my email tienhung@cfco.com.vn

      • AlleyLuse

        I am a beginner too. Can you send me a example?
        alleyluse@gmail.com
        Thank you very much.

  • Pingback: Technology Post Roundup–7th Edition « Jonathan Rozenblit

  • Pingback: Microsoft Exam 70-487 – Developing Windows Azure and Web Services Study Guide « The Pragmatic Developer

  • Goshen Monzon Jimenez

    Hi, im getting an error which reads :

    ‘System.IO.Stream’ does not contain a definition for ‘WriteAsync’ and no extension method ‘WriteAsync’ accepting a first argument of type ‘System.IO.Stream’ could be found (are you missing a using directive or an assembly reference?)

    The error occurs right at:
    await outputStream.WriteAsync(buffer, 0, bytesRead);
    which is in the VideoStream class.

    Here are my using statements above the class.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;

    Am I missing something?

    • http://www.strathweb.com/ Filip W

      is it .net 45?

    • Jeremy

      You can achieve this by targeting .NET 4 also. In NuGet search for Microsoft.Bcl.Async. Install it. It installs the async extensions for .NET 4/Silverlight 4 and 5.

  • Goshen Monzon Jimenez

    Hi, im getting an error which reads :

    ‘System.IO.Stream’ does not contain a definition for ‘WriteAsync’ and no extension method ‘WriteAsync’ accepting a first argument of type ‘System.IO.Stream’ could be found (are you missing a using directive or an assembly reference?)

    The error occurs right at:
    await outputStream.WriteAsync(buffer, 0, bytesRead);
    which is in the VideoStream class.

    Here are my using statements above the class.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;

    Am I missing something?

  • dekic

    Has someone gotten this project to work, it’s explained really well, but for me it only loads for 3 seconds and then stops. Any help would be rather helpful :)

  • Pingback: Sending video stream from 1 client to another in webapi c# | BlogoSfera

  • Pingback: Meu guia de estudos para o Exam 70-487 Developing Windows Azure and Web Services | Vitor Meriat

  • Kevin Mack

    Love the post, great ideas for handling it with WebAPI for streaming. BUt I’m running into a slight problem, hoping you can help with. Using .net 4.5 I am getting an error reading (call is ambiguoius between system.func and system.action). I did some more research and when I try to cast it to an Action, as you mentioned above, I get the error “No Overload of WriteToStream matches delegate System.Action”. Any thoughts?

  • Kevin Mack

    Scratch my previous question. I got that working by moving the code from the Video stream class into the VideosController. My bigger question is that I verified my mp4 file works but wwhen run through the web API it says unsupported file type? thoughts?

  • Pingback: Dave Mills | Streaming Attachments with PushStreamContent

  • SumoS

    Hi, It’s working fine as expected but if stream small size of file working properly. For large file asynchronous streaming not happening… Player loading videos after while loop complete.(WriteToStream Method). Is anything needs to be configured for that?

    • David Levy

      having same issue, not streaming,

  • David

    I’m trying to create this exact project to see for myself, but I keep getting errors. Instead of listing all of my errors could you send me a sample project of this? It would be much appreciated.
    thank you

  • Neha Tekchandani

    Will this code work for .net 3.5 if yes can i get a Sample code

  • vijay sundrapandiyan

    Filip W Pls Post Sample Project……in mVC 4..

  • Ron Killaars

    Dear Andrés Vettor, Thanks for the great article!. Would it be possible to send me the sample project? I am trying to get it done but is seems I missing something. Could you send it to rkillaars@hotmail.com Thanks.

  • Pingback: Asynchronously streaming video with ASP.NET Web...

  • shankar

    Please can you Send me this code on my Email I am Beginner and want to so video streaming normal web app

  • hari

    Hi , please share the sample code to harimgn@gmail.com.

    Thanks in advance