2012-08-25 50 views
4

我有一段代碼,我一直在努力爲視頻提供服務。代碼如下:.net MVC流媒體MP4到iDevice問題

public ResumingFileStreamResult GetMP4Video(string videoID) 
    { 
     if (User.Identity.IsAuthenticated) 
     { 
      string clipLocation = string.Format("{0}\\Completed\\{1}.mp4", ConfigurationManager.AppSettings["VideoLocation"].ToString(), videoID); 

      FileStream fs = new FileStream(clipLocation, FileMode.Open, FileAccess.Read); 

      ResumingFileStreamResult fsr = new ResumingFileStreamResult(fs, "video/mp4"); 

      return fsr; 
     } 
     else 
     { 
      return null; 
     } 
    } 

這是我的HTML代碼:

<video controls preload poster="@Url.Content(string.Format("~/Videos/{0}_2.jpg", Model.VideoID))"> 
    <source src="@Url.Action("GetMP4Video", "Video", new { videoID = Model.VideoID })" type="video/mp4" /> 
    <source src="@Url.Action("GetWebMVideo", "Video", new { videoID = Model.VideoID })" type="video/webm" /> 

     <object id="flowplayer" data="@Url.Content("~/Scripts/FlowPlayer/flowplayer-3.2.14.swf")" type="application/x-shockwave-flash" width="640" height="360"> 
      <param name="movie" value="@Url.Content("~/Scripts/FlowPlayer/flowplayer-3.2.14.swf")" /> 
      <param name="allowfullscreen" value="true" /> 
      <param name="flashvars" value="config={'playlist':['@Url.Content(string.Format("~/Videos/{0}_2.jpg", Model.VideoID))',{'url':'@Url.Action("GetMP4Video", "Video", new { videoID = Model.VideoID })','autoPlay':false}]}" /> 
     </object> 
</video> 

我的問題是這樣的設置似乎工作,從我的桌面上所有瀏覽器都正常,但當我嘗試使用加載頁面我iPad或iPhone只顯示播放圖標,並通過它顯示無法播放。我嘗試將mp4視頻的源代碼更改爲直接鏈接到mp4視頻,並立即開始播放。

有沒有什麼特別的我需要做的,我錯過了命令使我的方法兼容iDevices?任何幫助,將不勝感激。

回答

2

感謝您的回覆,並給出的信息是非常有幫助的。最後,我使用以下solution來實現字節範圍請求。

2

要在iOS設備上您的視頻上播放,您需要實現字節範圍(或部分)請求支持。這些類型的請求允許下載並非全部內容,而是部分地下載塊(典型的流式傳輸)。這是iOS設備如何在頁面上播放視頻的唯一方式。

部分請求使用Range標頭告訴服務器下一個塊的位置和大小。另一端的服務器響應206 Partial Content和請求的塊內容。

你可以找到幾個ASP.NET處理程序的實現,它們可以處理Internet中的部分請求。我建議爲此使用StaticFileHandler:易於安裝,並具有開箱即用的緩存功能。它也可以通過Nuget交付,但是該包叫做Talifun.Web

要配置StaticFileHandler,註冊在web.config中的處理程序MP4文件,並在單獨的配置部分進行配置:

<configuration> 
    <configSections> 
    <section name="StaticFileHandler" type="Talifun.Web.StaticFile.Config.StaticFileHandlerSection, Talifun.Web" requirePermission="false" allowDefinition="MachineToApplication"/> 
    </configSections> 

    <StaticFileHandler webServerType="NotSet"> 
    <!-- The defaults to use when an extension is found that does not have a specific rule --> 
    <fileExtensionDefault name="Default" serveFromMemory="true" maxMemorySize="100000" compress="true"/> 
    <!-- Specific rules for extension types --> 
    <fileExtensions> 
     <fileExtension name="VideoStaticContent" extension="3gp, 3g2, asf, avi, dv, flv, mov, mp4, mpg, mpeg, wmv" serveFromMemory="true" maxMemorySize="100000" compress="false"/> 
    </fileExtensions> 
    </StaticFileHandler> 

    <system.webServer> 
    <handlers> 
     <add name="StaticContentHandler" verb="GET,HEAD" path="*.mp4" type="Talifun.Web.StaticFile.StaticFileHandler, Talifun.Web"/> 
    </handlers> 
    </system.webServer> 
</configuration> 

如果還可以輕鬆地應用您的自定義邏輯,例如授權或自定義視頻文件源,通過創建您的ASP.NET處理程序並直接調用StaticFileManager

public class MyOwnVideoHandler : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     // Authorization or any other stuff. 
     ... 

     // Get file from your storage. 
     FileInfo file = ...; 

     // Serve the file with StaticFileHandler. 
     StaticFileManager.Instance.ProcessRequest(new HttpContextWrapper(context), file); 
    } 
} 

此外,您還可以在Scott Mitchell's article about partial requests看一看有關詳細信息,並使用它的作者寫的處理程序:它爲我工作,但它沒有緩存功能。

2

@whyleee是正確的。我不能說StaticFileHandler有多好,但我自己也一直在面對同樣的問題,這讓我發瘋。一個Range標頭必須包含在RequestResponse標題中才能正常工作。例如,一個輕微修改你的代碼,從我自己的處理方法的一些代碼,看起來像這樣(請記住,這是使用ashx的處理程序):

//First, accept Range headers. 
context.Response.AddHeader("Accept-Ranges", "bytes") 

//Then, read all of the bytes from the file you are requesting. 
Dim file_info As New System.IO.FileInfo(clipLocation) 
Dim bytearr As Byte() = File.ReadAllBytes(file_info.FullName) 

//Then, you will need to check for a range header, and then serve up a 206 Partial Content status code in your response. 
Dim startbyte As Integer = 0 
If Not context.Request.Headers("Range") Is Nothing Then 
    //Get the actual byte range from the range header string, and set the starting byte. 
    Dim range As String() = context.Request.Headers("Range").Split(New Char() {"="c, "-"c}) 
    startbyte = Convert.ToInt64(range(1)) 

    //Set the status code of the response to 206 (Partial Content) and add a content range header. 
    context.Response.StatusCode = 206 
    context.Response.AddHeader("Content-Range", String.Format(" bytes {0}-{1}/{2}", startbyte, bytearr.Length - 1, bytearr.Length)) 
End If 

//Finally, write the video file to the output stream, starting from the specified byte position. 
context.Response.OutputStream.Write(bytearr, startbyte, bytearr.Length - startbyte) 

正如我雖然說,這是代碼對於.ashx處理程序,我不確定它對您的情況有多大影響,但我希望它能幫助您!