A webserver was created using GoLang that serves HTML/JS/CSS and images. When the server attempted to provide an MP4 video file, the video failed to load, showing only video controls.
Upon examining the video files, it was discovered that the smaller video worked while the larger video did not. The issue was related to the video size and the browser's default buffering behavior.
Range Request Support:
For videos larger than a certain size, the browser requires the server to support Range requests (partial content serving). This allows the browser to fetch only the portion of the video needed for playback, preventing the entire file from being loaded into memory.
In this case, the GoLang code was not configured to handle Range requests. The provided implementation simply served the entire file as a single response. As a result, the browser was not able to play the larger video.
To resolve the issue, the following steps were taken:
Alternatively, if http.FileServe() is not preferred, custom range request handling can be implemented. This involves setting the following headers in the response:
For Range requests, the server should return an HTTP status code of 206 Partial Content instead of 200 OK.
Custom range request handling was implemented in the following manner:
<code class="go">func (vh *viewHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { path := r.URL.Path[1:] data, err := ioutil.ReadFile(string(path)) if err == nil { var contentType string if strings.HasSuffix(path, ".mp4") { contentType = "video/mp4" size := binary.Size(data) if size > 0 { requestedBytes := r.Header.Get("Range") w.Header().Add("Accept-Ranges", "bytes") w.Header().Add("Content-Length", strconv.Itoa(size)) w.Header().Add("Content-Range", "bytes "+requestedBytes[6:len(requestedBytes)]+strconv.Itoa(size-1)+"/"+strconv.Itoa(size)) w.WriteHeader(206) } } else { w.Header().Add("Content-Type", contentType) w.Write(data) } } else { log.Println("ERROR!") w.WriteHeader(404) w.Write([]byte("404 - " + http.StatusText(404))) } }</code>
Looping Video:
To ensure that the video loops, the following logic was added:
<code class="go">if contentType == "video/mp4" { http.ServeFile(w, r, path) } else { w.Header().Add("Content-Type", contentType) w.Write(data) }</code>
This uses http.ServeFile() for MP4 videos, which correctly handles looping.
The above is the detailed content of Why does my GoLang webserver fail to serve large MP4 videos?. For more information, please follow other related articles on the PHP Chinese website!