2013-05-07 21 views
5

Sto tentando di creare una pagina di test che conterrà un tag HTML5 VIDEO che consentirà la riproduzione di video convertiti. Sono in grado di convertire i video e di memorizzarli localmente sul server, ma mi piacerebbe poter trasmettere tutti i video attraverso un'altra pagina .aspx.Streaming video MP4 tramite .NET HTML5

Supponendo Ho una pagina player.aspx che conterrà il codice HTML e la pagina getvideo.aspx che farà nulla se non fornire il video binario, ho pensato che il seguente codice avrebbe funzionato bene nella mia pagina 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> 

la pagina di getvideo.aspx contiene il seguente codice 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) 

Tutto ricevo sul mio output della pagina è un lettore video HTML (giocatore di base di cromo) che sembra timeout e la Il pulsante PLAY diventa grigio. Lo strumento Rete negli strumenti per sviluppatori di Chrome mostra che sta scaricando 45mb e riceve un codice di risposta di 200. Questo mi suggerisce che sta funzionando bene. Anche se ottengo una seconda richiesta GET con lo stato di "Annullato"?

Se visito www.mywebsite.com/output/videos/myvideo.mp4, questo viene riprodotto bene nel browser, quindi so che IIS è configurato per lo streaming video corretto.

Inoltre, se si modifica la disposizione del contenuto di risposta in "allegato", il browser forza correttamente il download del video quando si accede alla pagina ASPX, ma anche questo non viene riprodotto correttamente sul lettore HTML. C'è qualcosa di "intelligente" nel tag HTML5 VIDEO che sta fermando un file .aspx dal servizio di video via .net? O mi manca un'intestazione di risposta?

Grazie!

+0

Continuando a indagare , ancora non ha una risoluzione su questo – JLo

risposta

3

FISSO!

Il problema qui è presumibilmente a causa dell'implementazione video HTML5 delle richieste di intervallo. Senza supportare le richieste di intervallo nella pagina utilizzata per SERVIRE il video, semplicemente non funzioneranno.

E 'stato questo post molto utile da Scott Mitchell, che mi mise sul caso: http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx

E un altro post utili da Chris Coulson che ha fornito l'implementazione in C# per la soluzione! http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/

mio porto vb.net del codice Chris trovato è inferiore, per la sua attuazione semplicemente mettere questo nella tua pagina:

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

CODICE 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

Entrambi gli URL sono uguali ed entrambi puntano al post di Scott Mitchell. Forse quello di Chris Coulson è questo? http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/ – Jairo

+0

Whoops! Grazie, è stato davvero quello - aggiornerò la risposta :) – JLo

Problemi correlati