Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream video in Go lang server

I've written this simple http server to serve video file:

package main

import (
    "net/http"
    "os"
    "bytes"
    "io"
    "fmt"
)

func handler(w http.ResponseWriter, r *http.Request) {

rangeValue := r.Header.Get("range")
fmt.Println("Range:")
fmt.Println(rangeValue)

buf := bytes.NewBuffer(nil)
f, _ := os.Open("oceans_1.webm")
io.Copy(buf, f)           // Error handling elided for brevity.
f.Close()

w.Header().Set("Accept-Ranges","bytes")
w.Header().Set("Content-Type", "video/webm")
w.Header().Set("Content-Length","22074728")
w.Header().Set("Last-Modified", "Wed, 29 Nov 2017 17:10:44 GMT")

w.WriteHeader(206)
w.Write(buf.Bytes())
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

The video is served perfect, but I can not change time of the video. When I click on the timeline video cursor it doesn't change the position and the video doesn't jump to specific time.

When I serve the video using http.ServeFile(w, r, "oceans_1.webm") everything works perfect - I can change video time.

like image 702
Simon Avatar asked Nov 29 '17 19:11

Simon


1 Answers

This different behavior is directly addressed on the net/http package, on the documentation for ServeContent (emphasis mine):

ServeContent replies to the request using the content in the provided ReadSeeker. The main benefit of ServeContent over io.Copy is that it handles Range requests properly, sets the MIME type, and handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, and If-Range requests.

If you check the net/http code, you'll see that ServeFile calls serveContent (through serveFile), which is the same unexported function called by ServeContent.

I've not digged into the reason for the different behaviors, but the documentation on the package makes quite clear why your io.Copy strategy is not working, while the http.ServeFile does.

like image 149
Jofre Avatar answered Oct 24 '22 19:10

Jofre