"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > Why does my GoLang webserver fail to serve large MP4 videos?

Why does my GoLang webserver fail to serve large MP4 videos?

Published on 2024-11-08
Browse:394

Why does my GoLang webserver fail to serve large MP4 videos?

GoLang HTTP Webserver Serving MP4 Video

Challenge

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.

Investigation

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.

Solution

To resolve the issue, the following steps were taken:

  1. Use http.FileServe(): The http.FileServe() method handles Range requests by default. By using this method to serve the video file, the server was able to provide partial content to the browser.
  2. Configure Custom Range Request Handling:

Alternatively, if http.FileServe() is not preferred, custom range request handling can be implemented. This involves setting the following headers in the response:

  • Accept-Ranges: bytes
  • Content-Length (size of the file)
  • Content-Range (bytes range requested)
  1. Use HTTP Status Code 206:

For Range requests, the server should return an HTTP status code of 206 Partial Content instead of 200 OK.

Implementation

Custom range request handling was implemented in the following manner:

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)))
    }
}

Looping Video:

To ensure that the video loops, the following logic was added:

if contentType == "video/mp4" {
    http.ServeFile(w, r, path)
} else {
    w.Header().Add("Content-Type", contentType)
    w.Write(data)
}

This uses http.ServeFile() for MP4 videos, which correctly handles looping.

Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3