I'm writing a server in golang and I got it to serve a basic .mp4 file. It serves it by bytes. The problem is that I can not seek/skip through the video. I've tried searching throughout stackover flow and google to find an answer but I came up short..
Here is my code:
package main
import (
"net/http"
"io/ioutil"
"fmt"
"os"
"log"
"bytes"
)
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
// grab the generated receipt.pdf file and stream it to browser
streamPDFbytes, err := ioutil.ReadFile("./video.mp4")
log.Println(r)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
b := bytes.NewBuffer(streamPDFbytes)
// stream straight to client(browser)
w.Header().Set("Content-type", "video/mp4")
if _, err := b.WriteTo(w); err != nil { // <----- here!
fmt.Fprintf(w, "%s", err)
}
w.Write([]byte("Video Completed"))
}
func main() {
http.Handle("/", new(MyHandler))
http.ListenAndServe(":8080", nil)
}
Does anyone have the answer to how seeking works in golang?
Thanks, Have a great day!
The simplest way to stream MP4 video on Go with seeking support is
package main
import (
"net/http"
)
func main() {
fs := http.FileServer(http.Dir("."))
http.Handle("/", http.StripPrefix("/", fs))
http.ListenAndServe(":8080", nil)
}
And video will be available at http://localhost:8080/video.mp4
More complex is
package main
import (
"log"
"net/http"
"os"
"time"
)
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
video, err := os.Open("./video.mp4")
if err != nil {
log.Fatal(err)
}
defer video.Close()
http.ServeContent(w, r, "video.mp4", time.Now(), video)
}
func main() {
http.HandleFunc("/", ServeHTTP)
http.ListenAndServe(":8080", nil)
}
If you need something more flexible you should implement your own progressive streaming server.
In your code you forgot to add and process Range
/Accept-Range
headers that's why nor FF, nor Chrome doesn't show you seek bar but anyway I don't think that keeping whole MP4 file in memory is good idea.