Go语学习笔记 - 实现将mp4通过rtmp推送流媒体服务

Posted 剑客阿良_ALiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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推送流媒体服务的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg5.0.1 代码读取MP4视频推送RTMP流

实现手机直播推送屏幕推送及录像功能RTMP推流组件之EasyRTMP-Android设置授权Key介绍

将 RTMP 转换为 MP4 的最佳方法

实现手机直播推送屏幕推送及录像功能RTMP推流组件之EasyRTMP-Android使用H265编码流程

有没有一种简单的方法可以在 java 中播放 rtmp 流?

如何推送RTMP直播流至流媒体系统进行网络直播