Go語言學習之將mp4通過rtmp推送流媒體服務的實現方法

前言

最近研究golang音視頻處理的時候,試著將mp4推送流媒體服務。下面分享一下代碼,大傢有需要可以研究一下,按照自己的需求改改。

環境

需要安裝:github.com/yapingcat/gomedia

代碼

代碼如下:

package main
 
import (
	"fmt"
	"github.com/yapingcat/gomedia/go-codec"
	"github.com/yapingcat/gomedia/go-mp4"
	"github.com/yapingcat/gomedia/go-rtmp"
	"io"
	"net"
	"os"
	"time"
)
 
func main() {
	var (
		mp4Path = "./data/movie1.mp4"
		rtmpUrl = "rtmp://192.168.5.97:1935/live/home"
	)
	c, err := net.Dial("tcp4", "192.168.5.97:1935")
	if err != nil {
		fmt.Println(err)
	}
	cli := rtmp.NewRtmpClient(rtmp.WithComplexHandshake(),
		rtmp.WithComplexHandshakeSchema(rtmp.HANDSHAKE_COMPLEX_SCHEMA1),
		rtmp.WithEnablePublish())
	cli.OnError(func(code, describe string) {
		fmt.Printf("rtmp code:%s ,describe:%s\n", code, describe)
	})
	isReady := make(chan struct{})
	cli.OnStatus(func(code, level, describe string) {
		fmt.Printf("rtmp onstatus code:%s ,level %s ,describe:%s\n", code, describe)
	})
	cli.OnStateChange(func(newState rtmp.RtmpState) {
		if newState == rtmp.STATE_RTMP_PUBLISH_START {
			fmt.Println("ready for publish")
			close(isReady)
		}
	})
	cli.SetOutput(func(bytes []byte) error {
		_, err := c.Write(bytes)
		return err
	})
	go func() {
		<-isReady
		fmt.Println("start to read file")
		PushRtmp(mp4Path, cli)
	}()
 
	cli.Start(rtmpUrl)
	buf := make([]byte, 4096)
	n := 0
	for err == nil {
		n, err = c.Read(buf)
		if err != nil {
			continue
		}
		cli.Input(buf[:n])
	}
	fmt.Println(err)
}
 
func PushRtmp(fileName string, cli *rtmp.RtmpClient) {
	mp4File, err := os.Open(fileName)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer mp4File.Close()
	demuxer := mp4.CreateMp4Demuxer(mp4File)
	if infos, err := demuxer.ReadHead(); err != nil && err != io.EOF {
		fmt.Println(err)
	} else {
		fmt.Printf("%+v\n", infos)
	}
	mp4info := demuxer.GetMp4Info()
	fmt.Printf("%+v\n", mp4info)
	for {
		pkg, err := demuxer.ReadPacket()
		if err != nil {
			fmt.Println(err)
			break
		}
		if pkg.Cid == mp4.MP4_CODEC_H264 {
			time.Sleep(30 * time.Millisecond)
			cli.WriteVideo(codec.CODECID_VIDEO_H264, pkg.Data, uint32(pkg.Pts), uint32(pkg.Dts))
		} else if pkg.Cid == mp4.MP4_CODEC_AAC {
			cli.WriteAudio(codec.CODECID_AUDIO_AAC, pkg.Data, uint32(pkg.Pts), uint32(pkg.Dts))
		} else if pkg.Cid == mp4.MP4_CODEC_MP3 {
			cli.WriteAudio(codec.CODECID_AUDIO_MP3, pkg.Data, uint32(pkg.Pts), uint32(pkg.Dts))
		}
	}
}

代碼說明:

1、如果是其他格式的話,可以按照庫裡其他格式構建。

2、為什麼在視頻幀推送要睡30ms,可以按照幀率調整,因為讀取的速度比較快,會推太快。

執行結果:

rtmp onstatus code:NetStream.Publish.Start ,level Started publishing stream. ,describe:%!s(MISSING)
ready for publish
start to read file
[{Duration:299925 TrackId:1 Cid:1 Height:1080 Width:1920 SampleRate:0 SampleSize:0 ChannelCount:0 Timescale:24000 StartDts:0 EndDts:299882} {Duration:299990 TrackId:2 Cid:102 Height:0 Width:0 SampleRate:48000 SampleSize:16 ChannelCount:2 Timescale:48000 StartDts:0 EndDts:299968}]
{MajorBrand:1836020585 MinorVersion:512 CompatibleBrands:[1836020585 846164841 828601953 825520237] Duration:299990 Timescale:1000 CreateTime:0 ModifyTime:0}

拉流畫面:

這個代碼主要隻是簡單的推流,沒有太多對視頻幀的處理。

如果有需要的話,可以自己集成一些其他的圖像處理的庫。

可以實現實時的視頻處理並推送的功能。

總結

到此這篇關於Go語言學習之將mp4通過rtmp推送流媒體服務實現的文章就介紹到這瞭,更多相關Go將mp4通過rtmp推送流媒體服務內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: