一直在用 udpxy 看北京联通的 IPTV ,很好奇到底是怎么实现的,
但是 udpxy 的代码量还是有一些,
最近花了一晚上,终于用 go 实现了一个最简单的版本,感觉很简洁
https://gist.github.com/darren/fe449a04bfddbed09ce477e1d33d6562
package main
import (
"flag"
"io"
"log"
"net"
"net/http"
"os"
"strings"
)
var addr = flag.String("l", ":18000", "Listening address")
var iface = flag.String("i", "eth0", "Listening multicast interface")
var inf *net.Interface
func handleHTTP(w http.ResponseWriter, req *http.Request) {
parts := strings.FieldsFunc(req.URL.Path, func(r rune) bool {
return r == '/'
})
if len(parts) < 2 {
w.WriteHeader( http.StatusBadRequest)
io.WriteString(w, "No address specified")
return
}
raddr := parts[1]
addr, err := net.ResolveUDPAddr("udp4", raddr)
if err != nil {
w.WriteHeader( http.StatusBadRequest)
io.WriteString(w, err.Error())
return
}
conn, err := net.ListenMulticastUDP("udp4", inf, addr)
if err != nil {
w.WriteHeader( http.StatusInternalServerError)
io.WriteString(w, err.Error())
return
}
defer conn.Close()
w.Header().Set("Content-Type", "application/octet-stream")
w.WriteHeader( http.StatusOK)
n, err := io.Copy(w, conn)
log.Printf("%s %s %d [%s]", req.RemoteAddr, req.URL.Path, n, req.UserAgent())
}
func main() {
if os.Getppid() == 1 {
log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime))
} else {
log.SetFlags(log.Lshortfile | log.LstdFlags)
}
flag.Parse()
var err error
inf, err = net.InterfaceByName(*iface)
if err != nil {
log.Fatal(err)
return
}
var mux http.ServeMux
mux.HandleFunc("/rtp/", handleHTTP)
log.Fatal( http.ListenAndServe(*addr, &mux))
}
启动后,使用 iina 播放:iina http://localhost:18000/rtp/239.3.1.62:8112
不过这样的实现 VLC 播放器无法直接播放, Apple TV 上某些底层 使用了 VLC 的播放器也无法播放了 需要解析 RTP 包,把 payload 提取出来
找了一番 RTP 协议的实现,发现已经有现成的了 github.com/pion/rtp
具体实现可以参考 https://github.com/darren/retv/blob/54378d16d6e1042b9259280b3a7aea50087d0518/rtp.go#L73
下一步的想法:自动把视频流切成 segments,实现 HLS ,让浏览器也能直接播放 😄
1
FrankAdler 2023-02-15 23:58:37 +08:00
监听多播 UDP ,然后返回收到的数据,看起来确实挺简单的,很好奇 udpxy 那么多代码都做了哪些额外工作
|
2
darrh00 OP @FrankAdler
大概看了 udpxy 的代码,我觉得主要这几个方面吧: 1. HTTP 协议的处理,而 Go 自带了电池😄, 2. 多进程处理,每来一个播放请求,都需要派生子进程进行处理,goroutine 简单, 3. RTP 协议的处理,而 Go 的 rtp 的第三方协议的处理包看起来挺成熟的,现成的, 4. 视频流的录制到文件功能,Go 实现应该也挺简单。 |
3
noahzh 2023-02-16 10:24:54 +08:00
这个好,udpxy 太古老了。
|
4
uvhchina 2023-03-02 19:20:38 +08:00 1
好像有个 msd_lite?
|
5
zhangtao1518 2023-04-15 09:15:37 +08:00
|