1

Using MVC3 and flowplayer, I have a video player that is set up to get video files with the following markup:

<div id="video">
    <div id="video-viewport">
      <!-- The data-ratio is a decimal number represeting the height of the video in proportion to the width -->
      <div class="flowplayer" data-swf="http://releases.flowplayer.org/5.1.1/flowplayer.swf"
        data-ratio="0.417" data-engine="html5" data-keyboard="true" data-native_ipad_fullscreen="true"
        data-volume="0.6">
        <video>
       <!-- By default Flowplayer attempts to use HTML5 video and if it's not
       supported then Flash (9.0+) and MP4 is used. MP4 is enough for
       complete browser support but providing WebM and/or OGG gives you
       broader support for HTML5 video which is the preferred technology. -->
     <!-- MP4 gives a complete cross browser support with the aid of Flash -->
     <source type="video/mp4" src="@Url.Action("GetVideo", "Video", new { id = Model.WebMp4Video.Id })"/>
     <!-- WEBM gives HTML5 video support for the latest Firefox, Chrome and Opera browser -->
      <source type="video/webm" src="@Url.Action("GetVideo", "Video", new { id = Model.WebMVideo.Id })"/> 
     <!-- OGG gives HTML5 support for older versions of Firefox and Opera -->
      <source type="video/ogv" src="@Url.Action("GetVideo", "Video", new { id = Model.OgvVideo.Id })"/> 
      </video>
      </div>
    </div>
  </div> <!--/video-->

In the controller I have this method returning the videos:

    public ActionResult GetVideo(string id) {
                ...
        var cd = new System.Net.Mime.ContentDisposition {
        Inline = false
    };
    FileInfo info = new FileInfo(path);
    Response.AppendHeader("Content-Disposition", cd.ToString());
    return new RangeFilePathResult(MimeType, info.FullName, info.LastWriteTimeUtc, info.Length); 
 }

RangeFilePathResult has been a life saver in returning partial responses and this all works fine in Firefox and IE, but in Chrome I am getting a frequent error:

"server cannot set status after http headers have been sent".

and the player itself crashes, revealing the following error on the page:

html5: Video not properly encoded

I am still trying to get my head around partial responses, but could this be because the RangeFileResult sets a status code 206 with each partial response? Or is there anything else I am missing here?

Edit: If I debug through the RangeFileResult code and also inspect the Network tab in Chrome, I notice that the request to the controller method returns the partial response, with status pending, as soon as the code hits this line:

context.HttpContext.Response.Flush();

there seems to be a delay on this, sometimes more than 10 seconds, but when this is complete the status of the repsonse changes to 206. Often while the video is playing, though, the status is again changed to cancelled and this is when the

html5: Video not properly encoded

message appears on the video player.

Edit2: The repsonses I am getting are as follows (3 responses, first and third are cancelled, second has 206 status:

Request

URL: http://localhost:64729/Video/GetVideo/24
Method: GET
Status Code: 206 Partial Content

Request Headers

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:.ASPXAUTH=BD5B9748E6985F5659B56289A5543C11CACBF1602AFFD5D4335453560988B870F2543269809401D13EE9F12EFBAC2D4CE0322B5F826871B9968B3D2986C01E35C536B28B5EC24E8E4F631D094B0DBEFF76DA84DA7CCC753E06C38C0FA36A858AC87548099BD23D4BE9B80434970A542489EC5E5F4543A9C98CA573F196DCBFE1B8CC18C10AE1AFEB0E4E899C6CA4DEFC59138E170954016DCB9C007FDC7C2B2950436E24AA5FF9C0888822626C9AE01C07A98F317A9499F0E9D5E61434F959E9;ASP.NET_SessionId=o112vzki5owvbptr4kudbdax
Host:localhost:64729
Range:bytes=0-
Referer:http://localhost:64729/Video/Index/3
User-Agent:Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17

Response headers

Cache-Control:private, s-maxage=0
Connection:Close
Content-Length:7362920
Content-Range:bytes 0-7362919/7362920
Content-Type:video/mp4
Date:Tue, 15 Jan 2013 12:55:24 GMT
Server:ASP.NET Development Server/10.0.0.0
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:3.0

Request

URL: http://localhost:64729/Video/GetVideo/24
Method: GET
Status Code: 206 Partial Content

Request headers

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:.ASPXAUTH=BD5B9748E6985F5659B56289A5543C11CACBF1602AFFD5D4335453560988B870F2543269809401D13EE9F12EFBAC2D4CE0322B5F826871B9968B3D2986C01E35C536B28B5EC24E8E4F631D094B0DBEFF76DA84DA7CCC753E06C38C0FA36A858AC87548099BD23D4BE9B80434970A542489EC5E5F4543A9C98CA573F196DCBFE1B8CC18C10AE1AFEB0E4E899C6CA4DEFC59138E170954016DCB9C007FDC7C2B2950436E24AA5FF9C0888822626C9AE01C07A98F317A9499F0E9D5E61434F959E9;ASP.NET_SessionId=o112vzki5owvbptr4kudbdax
Host:localhost:64729
Range:bytes=7339303-
Referer:http://localhost:64729/Video/Index/3
User-Agent:Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17

Response headers

Cache-Control:private, s-maxage=0
Connection:Close
Content-Length:23617
Content-Range:bytes 7339303-7362919/7362920
Content-Type:video/mp4
Date:Tue, 15 Jan 2013 12:55:24 GMT
Server:ASP.NET Development Server/10.0.0.0
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:3.0

Request

URL: http://localhost:64729/Video/GetVideo/24
Method: GET
Status Code: 206 Partial Content

Request headers

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:.ASPXAUTH=BD5B9748E6985F5659B56289A5543C11CACBF1602AFFD5D4335453560988B870F2543269809401D13EE9F12EFBAC2D4CE0322B5F826871B9968B3D2986C01E35C536B28B5EC24E8E4F631D094B0DBEFF76DA84DA7CCC753E06C38C0FA36A858AC87548099BD23D4BE9B80434970A542489EC5E5F4543A9C98CA573F196DCBFE1B8CC18C10AE1AFEB0E4E899C6CA4DEFC59138E170954016DCB9C007FDC7C2B2950436E24AA5FF9C0888822626C9AE01C07A98F317A9499F0E9D5E61434F959E9;ASP.NET_SessionId=o112vzki5owvbptr4kudbdax 
Host:localhost:64729
Range:bytes=48-
Referer:http://localhost:64729/Video/Index/3
User-Agent:Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17

Response headers

Cache-Control:private, s-maxage=0
Connection:Close
Content-Length:7362872
Content-Range:bytes 48-7362919/7362920
Content-Type:video/mp4
Date:Tue, 15 Jan 2013 12:55:24 GMT
Server:ASP.NET Development Server/10.0.0.0
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:3.0
tpeczek
  • 23,867
  • 3
  • 74
  • 77
DevDave
  • 6,700
  • 12
  • 65
  • 99
  • 1
    Please drop the `Response.AppendHeader("Content-Disposition", cd.ToString())` and try again (you shouldn't be needing Content-Disposition header when you streaming video, and certainly it shouldn't be with `Inline = false`). Other than this I don't see any issue at this point. Let us also know how your video file is encoded (not all browsers support all encodings). – tpeczek Jan 15 '13 at 12:16
  • thanks, I will give these a try – DevDave Jan 15 '13 at 12:16
  • @tpeczek, the problem remains the same if I remove the code that you mentioned. Also, I'm not using any encoding that I'm aware of, what would be the default? – DevDave Jan 15 '13 at 12:24
  • You must be using some kind of encoding (the encoding is the format in which the video file has been created). Three main are MPEG-4 (H.264), WebM (VP8), OGG (Theora) and it usually requires to provide more than one format if you want to cover all the browsers. You can read more about it here: http://drupal.org/node/1565532 (the article also provides sample properly encoded files for testing purposes). – tpeczek Jan 15 '13 at 12:32
  • Oh sorry, I use FFMpeg to create an MP4, WebM and Ogv video for each uploaded video, so each of these formats is made available on my video page. – DevDave Jan 15 '13 at 12:33
  • Can you provide me (via email) with some simplified project and test files so I can reproduce the issue? – tpeczek Jan 15 '13 at 12:39
  • Can you also add to your question the content from Network tab in chrome (I'm interested in Range header value). – tpeczek Jan 15 '13 at 12:47
  • I have posted 3 repsonses I get when I try to load the page. Also, do you think mp4 is appropriate for H.264, or should I be producing m4v files? – DevDave Jan 15 '13 at 13:00
  • I did some research in meantime and there seems to be one very specific edge case with Chrome. If you have access to RangeFileResult source code I can post a possible fix here for you to implement (although it is not tested so you will be a guinea pig on this). – tpeczek Jan 15 '13 at 13:09
  • sounds good! where will you post the fix? – DevDave Jan 15 '13 at 13:11
  • I have posted the fix as answer, please check it and let me know (I hope you know where you need to add the code). – tpeczek Jan 15 '13 at 13:23

2 Answers2

1

After some intensive testing (thank you for sample project) it looks like Chrome is having some issues with mp4 format.

In order to fix this situation it should be enough to move webm as the first format so Chrome will pick it up instead of mp4 (IE will skip to mp4 so it will work too):

<div id="video">
    <div id="video-viewport">
        <div class="flowplayer" data-swf="http://releases.flowplayer.org/5.1.1/flowplayer.swf" data-ratio="0.417" data-engine="html5" data-keyboard="true" data-native_ipad_fullscreen="true" data-volume="0.6">
            <video>
                <source type="video/webm" src="@Url.Action("GetVideo", "Video", new { id = Model.WebMVideo.Id })"/> 
                <source type="video/ogv" src="@Url.Action("GetVideo", "Video", new { id = Model.OgvVideo.Id })"/>
                <source type="video/mp4" src="@Url.Action("GetVideo", "Video", new { id = Model.WebMp4Video.Id })"/>
            </video>
        </div>
    </div>
</div>
tpeczek
  • 23,867
  • 3
  • 74
  • 77
  • I have added the code at the end of the GetRanges method (in the else statement), and the first response is now getting the status 200. But the problem still remains for me. – DevDave Jan 15 '13 at 13:36
  • Also, the Firefox video is still playing but the code change seems to have affected it, in that you are unable to skip forwards in the video, and it does not show buffering bar. – DevDave Jan 15 '13 at 13:38
  • @Tyler I will need a repro project from you, there is nothing more I can figure out from static analysis. Didi you check with the sample files from article I have sent you to make sure it is not encoding problem? – tpeczek Jan 15 '13 at 13:56
  • I have not received any email from you yet. I will try to put a sample project together. Thanks for all the help – DevDave Jan 15 '13 at 14:04
  • @tepczek. Hi, I have sent you an example solution, to the email address listed in your blog. Sorry for the delay – DevDave Jan 15 '13 at 15:08
  • @Tyler I will look at it as soon as I'm back home and let you know. – tpeczek Jan 15 '13 at 15:34
0

You can try this , it fixed my problem whick seems the same with yours .

<script>
    flowplayer.conf={
        engine:'flash'
    };
</script>