web-dev-qa-db-ja.com

Go langサーバーでビデオをストリーミングする

ビデオファイルを提供するために、この単純なhttpサーバーを作成しました。

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

ビデオは完璧に提供されますが、ビデオの時間を変更することはできません。タイムラインビデオカーソルをクリックしても、位置が変更されず、ビデオが特定の時間にジャンプしません。

http.ServeFile(w, r, "oceans_1.webm")を使用してビデオを配信すると、すべてが完璧に機能します。ビデオの時間を変更できます。

10
Simon

このさまざまな動作は、net/httpパッケージの ServeContent のドキュメントに直接記載されています(私の強調):

ServeContentは、提供されたReadSeekerのコンテンツを使用してリクエストに応答します。 io.CopyよりもServeContentの主な利点は、範囲リクエストを適切に処理し、MIMEタイプを設定し、If-Match、If-Unmodified-を処理することです。以降、If-None-Match、If-Modified-Since、およびIf-Rangeリクエスト。

net/httpコードを確認すると、 ServeFileserveContent を呼び出すことがわかります serveFile )、これは ServeContent によって呼び出される同じエクスポートされていない関数です。

さまざまな動作の理由については詳しく調べていませんが、パッケージのドキュメントでは、io.Copy戦略が機能していないのにhttp.ServeFileが機能している理由が明確になっています。

3
Jofre