Streaming MP4 video through .NET HTML5

前端 未结 1 1320
我寻月下人不归
我寻月下人不归 2021-02-06 12:09

I am trying to create a test page which will contain a HTML5 VIDEO tag which will allow converted videos to be played. I am successfully able to convert the videos and store th

1条回答
  •  有刺的猬
    2021-02-06 12:46

    FIXED!

    The problem here is presumably something to do with the HTML5 video implementation of range-requests. Without supporting range-requests in the page being used to SERVE the video, they just won't work.

    It was this very helpful post from Scott Mitchell which set me on the case: http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx

    And another helpful post from Chris Coulson which provided the implementation in C# for the solution! http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/

    My vb.net port of the code Chris found is below, to implement it simply put this in your page:

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

    VB.NET CODE:

    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 讨论(0)
提交回复
热议问题