最近在github上发现了一个go写的webrtc库,心血来潮,下载运行了一下。
1,下载、编译、执行demo
选择play-from-disk这个例子,测试一下从.ivf文件读取vp8帧发送到浏览器
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/play-from-disk
go build
这个时候当前目录下会生成 play-from-disk 可执行文件,在当前目录下放一个output.ivf文件,然后执行 ./play-from-disk 这个时候这个命令行程序等待输入base64编码的sdp
2,启动http服务器
在example目录下运行
go run examples.go
- 打开 http://127.0.0.1/example/js/play-from-disk/ , 等Browser Session Description 里面生成本地的sdp, 如果没有显示的话,修改一下stun服务器,可能是google stun服务器无法访问
- 点击 Copy browser Session Description to clipboard 复制浏览器的sdp到粘贴板,在play-from-disk的命令行程序粘贴浏览器sdp,回车
- 这个时候play-from-disk也会输出它的sdp, 复制这个sdp 粘贴到浏览器的Remote Session Description输入框中
- 点击Start Session 按钮,这个时候就可以看到output.ivf的视频内容
至此,一个简单的golang webrtc测试就成功了
3,换一个flv封装的h264视频
官方的demo用的是vp8/vp9 视频文件做测试,那么h264也可以吗?经过一点折腾,确定也是ok的,首先生成一个flv测试文件
ffmpeg -f avfoundation -framerate 30 -pix_fmt yuyv422 -i "0" -vcodec h264 -profile baseline ka.flv
然后改一下main.go 这样play-from-disk可以支持flv h264了
go func() {
fmt.Println("Wait for connection")
<-iceConnectedCtx.Done()
fmt.Println("Wait for connection done")
f, _ := os.Open("ka.flv")
d, err := flv.NewDemuxer(f)
if err == nil {
fmt.Println("read flv ok")
defer func() {
d.Close()
}()
}
ver, v, a, _ := d.ReadHeader()
fmt.Printf("ver %d has video %v , has audio %v\n", ver, v, a)
var idx int
var sps, pps []byte
ticker := time.NewTicker(time.Millisecond * time.Duration(33))
for ; true; <-ticker.C {
tagType, tagSize, _, err := d.ReadTagHeader()
if err != nil {
fmt.Println("read done")
break
}
if tagType != 9 {
d.ReadTag(tagSize)
continue
}
tagData, _ := d.ReadTag(tagSize)
idx++
codecId := tagData[0] & 0x0f
frameType := (tagData[0] & 0xf0) >> 4
fmt.Printf("[%d] cid %d ft %d pt %d tt %d, ts %d\n", idx, codecId, frameType, tagData[1], tagType, tagSize)
now := time.Now()
if tagData[1] == 0 {
spsLen := tagData[12]
spsStart := 12 + 1
ppsLen := tagData[12+1+spsLen+2]
ppsStart := 12 + 1 + spsLen + 2 + 1
sps = make([]byte, spsLen)
pps = make([]byte, ppsLen)
copy(sps, tagData[spsStart:spsStart+int(spsLen)])
copy(pps, tagData[ppsStart:int(ppsStart)+int(ppsLen)])
fmt.Printf("sps len %d, pps len %d\n", spsLen, ppsLen)
} else {
naluStart := 5
if frameType == 1 {
fmt.Printf("sps len %d, pps len %d\n", len(sps), len(pps))
videoTrack.WriteSample(media.Sample{Data: sps, Timestamp: now})
videoTrack.WriteSample(media.Sample{Data: pps, Timestamp: now})
}
for {
naluLen := binary.BigEndian.Uint32(tagData[naluStart : naluStart+4])
fmt.Printf("nalu len %d\n", naluLen)
videoTrack.WriteSample(media.Sample{Data: tagData[naluStart+4 : naluStart+4+int(naluLen)], Timestamp: now})
naluStart += int(naluLen) + 4
if naluStart >= len(tagData) {
break
}
}
}
}
}()
这段代码解析flv文件,提取出h264 nalu 然后通过webrtc发送。h264解析用到了"github.com/ossrs/go-oryx-lib/flv"
4,可能在什么地方有用
由于golang是可以轻松实现交叉编译,这就意味着它可以运行在一些嵌入式linux的环境中,轻松实现webrtc支持。相对于c++版本的webrtc库,这个golang的版本集成起来就很轻松了