2013-05-07 165 views
5

我正在嘗試創建一個包含HTML5 VIDEO標記的測試頁面,該標記將允許播放轉換後的視頻。我成功地能夠轉換視頻並將它們本地存儲在服務器上,但我希望能夠通過另一個.aspx頁面流式傳輸所有視頻。通過.NET流式傳輸MP4視頻HTML5

假設我有一個player.aspx頁面,它將包含HTML代碼和getvideo.aspx頁面,它除了提供視頻二進制文件外什麼也不做,我認爲下面的代碼可以在我的player.aspx頁面中正常工作:

<div style="text-align:center"> 
<video controls autoplay id="video1" width="920"> 
    <source src="http://www.mywebsite.com/getvideo.aspx?getvideo=1" type="video/mp4"> 
    Your browser does not support HTML5 video. 
</video> 

的getvideo.aspx頁面包含以下vb.net代碼:

Response.clearheaders 
Response.AddHeader("Content-Type", "video/mp4") 
Response.AddHeader("Content-Disposition", "inline;filename=""newvideo.mp4""") 

dim Err as string = "" 
Dim iStream As System.IO.Stream 

' Buffer to read 10K bytes in chunk: 
Dim buffer(buffersize) As Byte 
' Length of the file: 
Dim length As Integer 

' Total bytes to read: 
Dim dataToRead As Long 

' Identify the file to download including its path. 
Dim filepath As String = "./outout/videos/newvideo.mp4" 

' Identify the file name. 
Dim filename As String = System.IO.Path.GetFileName(filepath) 

' Open the file. 
try 
    iStream = New System.IO.FileStream(filepath, System.IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read) 
catch ex as exception 
    throw new exception("Could not create FileStream for [" & filepath & "], error follows." & vbcrlf & ex.toString) 
end try 

Try 
    ' Total bytes to read: 
    dataToRead = iStream.Length 

    ' Read the bytes. 
    While dataToRead > 0 
     ' Verify that the client is connected. 
     If system.web.httpcontext.current.Response.IsClientConnected Then 
      ' Read the data in buffer 
      length = iStream.Read(buffer, 0, buffersize) 
      ' Write the data to the current output stream. 
      system.web.httpcontext.current.Response.OutputStream.Write(buffer, 0, length) 
      ' Flush the data to the HTML output. 
      system.web.httpcontext.current.Response.Flush() 

      ReDim buffer(buffersize) ' Clear the buffer 
      dataToRead = dataToRead - length 
     Else 
      'prevent infinite loop if user disconnects 
      dataToRead = -1 
     End If 
    End While 

Catch ex As Exception 
    ' Trap the error, if any. 
    err = "Error accessing " & filepath & " : " & ex.tostring 
Finally 
    If IsNothing(iStream) = False Then 
     ' Close the file. 
     iStream.Close() 
    End If 
End Try 

if err<>"" then throw new exception(err) 

所有我得到我的頁面輸出爲HTML視頻播放器(Chrome的基本播放器),這似乎超時, PLAY按鈕變灰。 Chrome Developer工具中的網絡工具顯示它正在下載45mb並獲得200響應代碼。這表明它工作正常。雖然我收到了狀態爲「已取消」的第二個GET請求?

如果我訪問www.mywebsite.com/output/videos/myvideo.mp4,那麼這在瀏覽器中播放良好,所以我知道IIS配置爲正確流式傳輸視頻。

此外,如果我將響應內容處置更改爲「附件」,則瀏覽器在進入我的ASPX頁面時正確強制下載視頻,但這也無法在HTML播放器上正確播放。 HTML5 VIDEO標籤有沒有什麼「聰明」的東西可以阻止.aspx文件通過.net提供視頻?或者我錯過了一個響應標題?

謝謝!

+0

繼續調查,仍然沒有得到關於這個 – JLo 2013-06-06 10:05:34

回答

3

固定!

這裏的問題大概是與範圍請求的HTML5視頻實現有關。如果頁面中沒有支持範圍請求用於對視頻進行投稿,則它們將無法工作。

正是從斯科特·米切爾這讓我對這個情況非常有幫助的帖子: http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx

而且從克里斯·庫爾森另一個有用的帖子裏面提供的實現在C#中的解決方案! http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/

代碼克里斯發現我的vb.net端口低於,實現它只是把這個在您的網頁:

system.web.httpcontext.current.Response.ContentType = "video/" & convertFormat.toString 
RangeDownload(convertedVideo, system.web.httpcontext.current) 

VB.NET代碼:

private sub RangeDownload(fullpath as string, context as HttpContext) 

    dim size as long 
    dim start as long 
    dim theend as long 
    dim length as long 
    dim fp as long =0 
    using reader as new StreamReader(fullpath) 
     size = reader.BaseStream.Length 
     start = 0 
     theend = size - 1 
     length = size 
     '/ Now that we've gotten so far without errors we send the accept range header 
     '* At the moment we only support single ranges. 
     '* Multiple ranges requires some more work to ensure it works correctly 
     '* and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 
     '* 
     '* Multirange support annouces itself with: 
     '* header('Accept-Ranges: bytes'); 
     '* 
     '* Multirange content must be sent with multipart/byteranges mediatype, 
     '* (mediatype = mimetype) 
     '* as well as a boundry header to indicate the various chunks of data. 
     '*/ 
     context.Response.AddHeader("Accept-Ranges", "0-" + size) 
     '// header('Accept-Ranges: bytes') 
     '// multipart/byteranges 
     '// http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 

     if (not String.IsNullOrEmpty(context.Request.ServerVariables("HTTP_RANGE"))) then 
      dim anotherStart as long = start 
      dim anotherEnd as long = theend 
      dim arr_split as string() = context.Request.ServerVariables("HTTP_RANGE").Split("=") 'new char[] { Convert.ToChar("=") }) 
      dim range as string = arr_split(1) 

      '// Make sure the client hasn't sent us a multibyte range 
      if (range.IndexOf(",") > -1) then 
       '// (?) Shoud this be issued here, or should the first 
       '// range be used? Or should the header be ignored and 
       '// we output the whole content? 
       context.Response.AddHeader("Content-Range", "bytes " & start & "-" & theend & "/" & size) 
       throw new HttpException(416, "Requested Range Not Satisfiable") 
      end if 

      '// If the range starts with an '-' we start from the beginning 
      '// If not, we forward the file pointer 
      '// And make sure to get the end byte if spesified 
      if (range.StartsWith("-")) then 
       '// The n-number of the last bytes is requested 
       anotherStart = size - Convert.ToInt64(range.Substring(1)) 
      else 
       arr_split = range.Split("-") 
       anotherStart = Convert.ToInt64(arr_split(0)) 
       dim temp as long = 0 
       if (arr_split.Length > 1 andalso Int64.TryParse(arr_split(1).ToString(), temp)) then 
        anotherEnd = Convert.ToInt64(arr_split(1)) 
       else 
        anotherEnd = size 
       end if 
      end if 
      '/* Check the range and make sure it's treated according to the specs. 
      ' * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 
      ' */ 
      '// End bytes can not be larger than $end. 
      if (anotherEnd > theend) then 
       anotherEnd = theend 
      else 
       anotherEnd = anotherEnd 
      end if 
      '// Validate the requested range and return an error if it's not correct. 
      if (anotherStart > anotherEnd or anotherStart > size - 1 or anotherEnd >= size) then 
       context.Response.AddHeader("Content-Range", "bytes " + start + "-" + theend + "/" + size) 
       throw new HttpException(416, "Requested Range Not Satisfiable") 
      end if 

      start = anotherStart 
      theend = anotherEnd 

      length = theend - start + 1 '// Calculate new content length 
      fp = reader.BaseStream.Seek(start, SeekOrigin.Begin) 
      context.Response.StatusCode = 206 
     end if 
    end using 

    '// Notify the client the byte range we'll be outputting 
    context.Response.AddHeader("Content-Range", "bytes " & start & "-" & theend & "/" & size) 
    context.Response.AddHeader("Content-Length", length.ToString()) 
    '// Start buffered download 
    context.Response.WriteFile(fullpath, fp, length) 
    context.Response.End() 
end sub 
+0

的決議兩個網址是相同的,他們都指向斯科特米切爾的職位。也許克里斯庫爾森是這一個? http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/ – Jairo 2016-03-22 15:06:56

+0

哎呀!謝謝,那確實是一個 - 我會更新答案:) – JLo 2016-03-22 16:07:36

相關問題