简体   繁体   中英

How do I manually proxy application/octet-stream (live video) in Go?

I am trying to build an application which would act as a streaming proxy server with caching features. The thing is, I want to do it manually without using NewSingleHostReverseProxy . Manually means performing these steps:

  1. Perform single GET request to the server
  2. Read resp.Body to buffer and write to connected client(s)

And the issue is that VLC doesn't play anything. If I access stream directly - VLC plays it without problems, but if I do it via GO - VLC (as well as Kodi) just keeps buffering and never starts playing.

Things I've tried, but did not work:

  1. io.Copy(...)
  2. bufio reader/scanner and writing to the connected client. Flushing also did not help.

This is what curl -v <stream_url> says (accessing streaming url directly):

...
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 Ok
< Server: Myserver
< Cache-Control: no-cache
< Pragma: no-cache
< Content-Type: application/octet-stream
< Access-Control-Allow-Origin: *
< Connection: close
< 
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 2896)
* Closing connection 0

This is what curl -v <my_app_url> says:

...
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Cache-Control: no-cache
< Content-Type: application/octet-stream
< Pragma: no-cache
< Server: Myserver
< Date: Sun, 29 Dec 2019 09:13:44 GMT
< Transfer-Encoding: chunked
< 
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 14480)
* Failed reading the chunked-encoded stream
* Closing connection 0

Seems the issue is here, but how do I solve it?

Good:

* Failed writing body (0 != 2896)
* Closing connection 0

Bad:

* Failed writing body (0 != 14480)
* Failed reading the chunked-encoded stream
* Closing connection 0

Also adding a source code for example:

func main() {
    http.HandleFunc("/stream", func(w http.ResponseWriter, r *http.Request) {
        resp, err := http.Get("http://example.com/stream/videostream")
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        reader := bufio.NewReader(resp.Body)
        buf := make([]byte, 1024)
        for {
            k, _ := reader.Read(buf)
            if k == 0 {
                break
            }
            w.Write(buf)
        }
    })
    log.Fatal(http.ListenAndServe(":8080", nil))
}

I was building a dynamic M3U playlist and putting .m3u8 ending on each link. All the links are of unknown type, so I thought media players will just look at Content-Type and handle media accordingly, but actually they look at URL endings as well (whether URL contains .m3u8 or not).

If you put at the end of the link .m3u8 , then set that link's Content-Type as application/octet-stream and provide actual application/octet-stream stream - players will never start showing any video stream. Solution - do not append .m3u8 to URL if that URL is not m3u8 format media. Without m3u8 media players can still show the video.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM