通过.NET HTML5流式传输MP4视频

我正在尝试创建一个包含 HTML5 VIDEO标签的测试页面,该标签将允许播放转换后的视频.我成功地将视频转换并在服务器上本地存储,但我希望能够通过另一个.aspx页面传输所有视频.

假设我有一个包含HTML代码的player.aspx页面和除了提供视频二进制文件之外什么都不做的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,buffersize)
            ' Write the data to the current output stream.
            system.web.httpcontext.current.Response.OutputStream.Write(buffer,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开发者工具中的网络工具显示它正在下载45mb并获得200响应代码.这告诉我它工作正常.虽然我收到状态为“已取消”的第二个GET请求?

如果我访问www.mywebsite.com/output/videos/myvideo.mp4然后这在浏览器中播放正常,所以我知道IIS配置为正确流式传输视频.

此外,如果我将响应内容处置更改为“附件”,则浏览器在转到我的ASPX页面时会正确强制下载视频,但这也无法在HTML播放器上正确播放.是否有一些“聪明”的HTML5 VIDEO标签正在阻止.aspx文件通过.net提供视频?或者我错过了回复标题

谢谢!

解决方法

固定!

这里的问题可能与范围请求的HTML5视频实现有关.如果不在用于发送视频的页面支持范围请求,它们将无法工作.

Scott Mitchell的这篇非常有用的帖子让我了解了这个案例:
http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx

还有来自Chris Coulson的另一个有用的帖子,它为C#提供了解决方案的实现!
http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/

我发现的代码Chris的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

相关文章

HTML5不是新事物。自从最初发布(2008年1月)以来,我们一直在使用它的一些功能。后来,我再次仔细查看...
Pointer Events API 是Hmtl5的事件规范之一,它主要目的是用来将鼠标(Mouse)、触摸(touch)和触控笔(...
CSS动画非常的有趣;这种技术的美就在于,通过使用很多简单的属性,你能创建出漂亮的消隐效果。其中代表...
clip-path介绍 clip-path 直译过来就是裁剪路径,使用SVG或形状定义一个HTML元素的可见区域的方法。想象...
语法 必需。动画时长的百分比。 合法的值: 0-100% from(与 0% 相同) to(与 100% 相同) 定义和用法...
基本代码 html代码: 首先定义一些基本的样式和动画: background-size: auto 100%; 这段代码的意思是让...