# rtp-http-flv **Repository Path**: ericps/rtp-http-flv ## Basic Information - **Project Name**: rtp-http-flv - **Description**: 边缘节点:接收 RTP 组播包,提供 HTTP-FLV 服务 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-02-20 - **Last Updated**: 2024-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## EdgeServer ![system.png](https://s2.loli.net/2022/10/04/q2GfX9DdxPhsACH.png) ### 功能概览 #### 1. 收rtmp数据后封装为flv_tag ![在这里插入图片描述](https://img-blog.csdnimg.cn/bcd259043ee04567a27e28f577e15892.png) #### 2. 将flv_tag打包为rtp数据包并发送 flv_tag超过1000字节则分片发送,mark位标志是否为一个flvtag的结束,接收端根据mark位重组得到flv_tag #### 3. 边缘节点收到rtp包后,排序,检查丢包,如果丢包使用quic重传rtp包 #### 4. 边缘节点得到flv_tag后通过http-flv服务发送到客户端flv.js ### Start #### 主要参数配置 ```go var ( h bool API_URL string UDP_SOCKET_ADDR string QUIC_ADDR string RECORD_DIR string RTP_QUEUE_PADDING_WINDOW_SIZE int DISABLE_QUIC bool RTP_QUEUE_CHAN_SIZE int PACKET_LOSS_RATE float64 HTTP_FLV_ADDR string ) func init() { flag.BoolVar(&h, "h", false, "this help") flag.StringVar(&API_URL, "api_url", "http://127.0.0.1:8090", "http api server addr") flag.StringVar(&UDP_SOCKET_ADDR, "udp_addr", "127.0.0.1:5222", "udp listen addr") flag.StringVar(&QUIC_ADDR, "quic_addr", "localhost:4242", "quic server addr") flag.IntVar(&RTP_QUEUE_PADDING_WINDOW_SIZE, "padding_size", 1000, "rtp queue window") flag.BoolVar(&DISABLE_QUIC, "disable_quic", false, "enable quic service") flag.IntVar(&RTP_QUEUE_CHAN_SIZE, "queue_chan_size", 100, "rtp queue chan size") flag.StringVar(&RECORD_DIR, "record_dir", "./record", "stream record dir") flag.Float64Var(&PACKET_LOSS_RATE, "pack_loss", 0.002, "the rate to loss some packets") flag.StringVar(&HTTP_FLV_ADDR, "httpflv_addr", ":7001", "HTTP-FLV server listen address") flag.Usage = usage } func usage() { flag.PrintDefaults() } func GetFlag() bool { flag.Parse() if h { flag.Usage() return false } return true } ``` #### 文件结构 - `cache.go`:主要是缓存 flvTag 的初始段 initialization segment,通常包含在首个音频和视频的 Tag 中,包含了媒体的基本信息,例如编解码格式以及采样率等,播放器必须拿到才能正确解码播放视频 ```go type SegmentPacket struct { full bool p []byte } type SegmentCache struct { videoSeq *SegmentPacket audioSeq *SegmentPacket metadata *SegmentPacket full bool } ``` - `conn.go` `quic_client.go`:quic 客户端,主要根据 sequence number 重传 rtp packet - `RtpQueue.go`:接收 rtp packet 的队列,滑动窗口思想 ```go type queue struct { m sync.RWMutex //maxSize int Ssrc uint32 //队列所属的流 FirstSeq uint16 //第一个Rtp包的序号 PaddingWindowSize int //滑动窗口大小 queue *arraylist.List //rtpPacket队列 checked bool //窗口内是否都已检验 readChan chan interface{} play bool flvRecord *FlvRecord //解析flv结构 flvWriters *arraylist.List //http-flv对象 flvFile *utils.File //录制文件 cache *SegmentCache } ``` - `server.go`:http-flv 服务端,主要通过 `handleConn` 处理 http-flv 请求 - `writer.go`:提供 http-flv 服务时向客户端传输数据包,主要数据结构是 flvWriter ```go type FLVWriter struct { Uid string av.RWBaser app, title, url string buf []byte closed bool closedChan chan struct{} ctx http.ResponseWriter packetQueue chan []byte // 数据通道 init bool } ``` - `main.go`:主要代码逻辑,开启 http-flv 服务以及接收组播的 rtp 数据 #### 运行 设置参数之后,直接 `go run main.go` ### Todo - [x] 效率问题?协程 - [x] 给出 flags 参数处理? - [ ] 代码逻辑优化?无用包 - [ ] UpdatePlayers