rtmp协议作为直播姐的一大利器,周边生态很成熟,比如OBS这些直播工具,可以很好的满足网络推各种流,但是网页播放,传统一般是采用的swf播放插件,现在webrtc越来越流行,浏览器天然支持让音视频应用变得更加简洁高效,而且实时性也得到了不晓得提升。

万能的开源给了我无穷的力量,没有什么是ctrl c v解决不了的,于是稍做整合就出来了一套效果不错的直播推流软件,想给女朋友同步分享看剧的朋友有福了,show me your code

func (h *Handler) OnAudio(timestamp uint32, payload io.Reader) error {
	// Convert AAC to opus
	var audio flvtag.AudioData
	if err := flvtag.DecodeAudioData(payload, &audio); err != nil {
		return err
	}

	data := new(bytes.Buffer)
	if _, err := io.Copy(data, audio.Data); err != nil {
		return err
	}
	if data.Len() <= 0 {
		log.Println("no audio datas", timestamp, payload)
		return fmt.Errorf("no audio datas")
	}
	// log.Println("\r\ntimestamp->", timestamp, "\r\npayload->", payload, "\r\naudio data->", data.Bytes())
	datas := data.Bytes()
	// log.Println("\r\naudio data len:", len(datas), "->") // hex.EncodeToString(datas))

	if audio.AACPacketType == flvtag.AACPacketTypeSequenceHeader {
		log.Println("Created new codec ", hex.EncodeToString(datas))
		err := h.initAudio(h.audioClockRate)
		if err != nil {
			log.Println(err, "error initializing Audio")
			return fmt.Errorf("can't initialize codec with %s", err.Error())
		}
		err = h.audioDecoder.InitRaw(datas)

		if err != nil {
			log.Println(err, "error initializing stream")
			return fmt.Errorf("can't initialize codec with %s", hex.EncodeToString(datas))
		}

		return nil
	}

	pcm, err := h.audioDecoder.Decode(datas)
	if err != nil {
		log.Println("decode error: ", hex.EncodeToString(datas), err)
		return fmt.Errorf("decode error")
	}
	// log.Println("\r\npcm len ", len(pcm), " ->") //, pcm)
	blockSize := 960
	for h.audioBuffer = append(h.audioBuffer, pcm...); len(h.audioBuffer) >= blockSize*4; h.audioBuffer = h.audioBuffer[blockSize*4:] {
		pcm16 := make([]int16, blockSize*2)
		pcm16len := len(pcm16)
		for i := 0; i < pcm16len; i++ {
			pcm16[i] = int16(binary.LittleEndian.Uint16(h.audioBuffer[i*2:]))
		}
		bufferSize := 1024
		opusData := make([]byte, bufferSize)
		n, err := h.audioEncoder.Encode(pcm16, opusData)
		// n, err := h.audioEncoder.ReadEncode(pcm16, opusData)
		if err != nil {
			return err
		}
		opusOutput := opusData[:n]
		// log.Println(" pcm len:", pcm16len, " data->", " opusData len", n, " data->")
		if audioErr := h.audioTrack.WriteSample(media.Sample{
			Data:     opusOutput,
			Duration: 20 * time.Millisecond,
		}); audioErr != nil {
			log.Println("WriteSample err", audioErr)
		}

	}

	return nil
}

以上代码,就是简单的实现了AAC转opus的关键一环,将无声的世界变得更美妙的,

取之于开源用之于开源,以下是开源网站地址xiangxud/rtmp-to-webrtc: Demonstrate a RTMP server that publishes to WebRTC (github.com)实现了核心的音视频转接,欢迎大家继续完善,本项目基于技术实践,学习目的,大家严格遵守法律法规,不要将项目用于非法用途。

我也在开发功能更强大得下一版本,增加设备管理,多链路对多peers,强大的订阅发布功能,房间管理,IM等,兴趣是最好的老师,只要有梦想,一定会实现,程序员永远不老!

以下部分功能

obs推流测试

925891debdd644cfb43311206de31719.jpg

 

推流至视频会议,多房间多参与者

82edd164e69842db9501a7042d2570c5.jpg

 

 优化后的效果还不错

ffe520bc730a44488dca9925e75a1b2e.jpg8c48ae3290544b52adf0065a7bf21b72.png

fd650e27495b4ece8db08555ea597b9e.png

d217017a1f3e48abb297e2bf9d14f0c9.png

 

 

 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐