最简单的 Golang Go语言代码实现联通的 iptv 转换为 http 流 实现类似 udpxy 的功能

发布于 1周前 作者 eggper 来自 Go语言

一直在用 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 ,让浏览器也能直接播放 😄


最简单的 Golang Go语言代码实现联通的 iptv 转换为 http 流 实现类似 udpxy 的功能

更多关于最简单的 Golang Go语言代码实现联通的 iptv 转换为 http 流 实现类似 udpxy 的功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

监听多播 UDP ,然后返回收到的数据,看起来确实挺简单的,很好奇 udpxy 那么多代码都做了哪些额外工作

更多关于最简单的 Golang Go语言代码实现联通的 iptv 转换为 http 流 实现类似 udpxy 的功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html




大概看了 udpxy 的代码,我觉得主要这几个方面吧:

1. HTTP 协议的处理,而 Go 自带了电池😄,

2. 多进程处理,每来一个播放请求,都需要派生子进程进行处理,goroutine 简单,

3. RTP 协议的处理,而 Go 的 rtp 的第三方协议的处理包看起来挺成熟的,现成的,

4. 视频流的录制到文件功能,Go 实现应该也挺简单。

这个好,udpxy 太古老了。

好像有个 msd_lite?

在 Go 语言中实现类似 udpxy 的功能,将联通的 IPTV 流转换为 HTTP 流,是一个相对复杂的任务,因为它涉及到网络协议的转换和流媒体的处理。不过,我可以提供一个简化的示例框架,展示如何开始这个项目。

首先,你需要一个能够接收和处理 IPTV UDP 流的组件。这通常涉及到使用 net 包来监听 UDP 端口。

package main

import (
    "fmt"
    "net"
    "net/http"
    "io"
    "sync"
)

func handleUDP(conn *net.UDPConn, wg *sync.WaitGroup) {
    defer wg.Done()
    buffer := make([]byte, 1024)
    for {
        n, addr, err := conn.ReadFromUDP(buffer)
        if err != nil {
            fmt.Println("Error reading UDP:", err)
            return
        }
        // Here you would typically forward the data to an HTTP client
        fmt.Printf("Received %d bytes from %s\n", n, addr)
    }
}

func main() {
    addr, err := net.ResolveUDPAddr("udp", ":12345")
    if err != nil {
        fmt.Println("Error resolving address:", err)
        return
    }
    conn, err := net.ListenUDP("udp", addr)
    if err != nil {
        fmt.Println("Error listening on UDP:", err)
        return
    }
    defer conn.Close()

    var wg sync.WaitGroup
    wg.Add(1)
    go handleUDP(conn, &wg)
    wg.Wait()

    // HTTP server setup would go here, but is omitted for brevity
}

这个示例代码展示了如何监听一个 UDP 端口并读取数据。为了完成整个功能,你还需要实现一个 HTTP 服务器,将接收到的 UDP 数据流发送给连接的 HTTP 客户端。这通常涉及到使用 net/http 包,并且可能需要处理流媒体传输的特定细节,如适当的缓冲和实时性。

回到顶部