前言
最近研究golang音视频处理的时候,试着将mp4推送流媒体服务。下面分享一下代码,大家有需要可以研究一下,按照自己的需求改改。
环境
需要安装:github.com/yapingcat/gomedia
代码
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
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推送流媒体服务内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/zhiweihongyan1/article/details/128216632