使用 GoLang 创建了一个提供 HTML/JS/CSS 和图像的 Web 服务器。当服务器尝试提供 MP4 视频文件时,视频加载失败,仅显示视频控件。
检查视频文件后,发现较小的视频可以正常工作,而较大的视频没有。该问题与视频大小和浏览器的默认缓冲行为有关。
范围请求支持:
对于大于特定大小的视频,浏览器需要服务器支持范围请求(部分内容服务)。这允许浏览器仅获取播放所需的视频部分,从而防止整个文件加载到内存中。
在这种情况下,GoLang 代码未配置为处理 Range 请求。提供的实现只是将整个文件作为单个响应提供。因此,浏览器无法播放较大的视频。
要解决此问题,采取了以下步骤:
或者,如果不首选 http.FileServe(),则可以实现自定义范围请求处理。这涉及在响应中设置以下标头:
对于 Range 请求,服务器应返回 HTTP 状态代码 206 Partial Content,而不是 200 OK。
自定义范围请求处理通过以下方式实现:
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)))
}
}
循环播放视频:
为了保证视频循环播放,添加了以下逻辑:
if contentType == "video/mp4" {
http.ServeFile(w, r, path)
} else {
w.Header().Add("Content-Type", contentType)
w.Write(data)
}
这对 MP4 视频使用 http.ServeFile(),它可以正确处理循环。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3