2023-03-05:ffmpeg推送本地视频至lal流媒体服务器(以RTMP为例),请用go语言编写。

news/2024/5/20 2:06:25/文章来源:https://blog.csdn.net/weixin_48502062/article/details/129352760

2023-03-05:ffmpeg推送本地视频至lal流媒体服务器(以RTMP为例),请用go语言编写。

答案2023-03-05:

使用 github.com/moonfdd/ffmpeg-go 库。

先启动lal流媒体服务器软件,然后再执行命令:

go run ./examples/leixiaohua1020/simplest_ffmpeg_streamer/main.go

参考了雷霄骅的最简单的基于FFmpeg的推流器(推送RTMP),代码用golang编写。代码如下:

// https://github.com/leixiaohua1020/simplest_ffmpeg_streamer/blob/master/simplest_ffmpeg_streamer/simplest_ffmpeg_streamer.cpp
package mainimport ("fmt""os""os/exec""time""github.com/moonfdd/ffmpeg-go/ffcommon""github.com/moonfdd/ffmpeg-go/libavcodec""github.com/moonfdd/ffmpeg-go/libavformat""github.com/moonfdd/ffmpeg-go/libavutil"
)func main0() (ret ffcommon.FInt) {var ofmt *libavformat.AVOutputFormat//Input AVFormatContext and Output AVFormatContextvar ifmt_ctx, ofmt_ctx *libavformat.AVFormatContextvar pkt libavcodec.AVPacketvar in_filename, out_filename stringvar i ffcommon.FIntvar videoindex ffcommon.FInt = -1var frame_index ffcommon.FInt = 0var start_time ffcommon.FInt64T = 0var err error//in_filename  = "cuc_ieschool.mov";//in_filename  = "cuc_ieschool.mkv";//in_filename  = "cuc_ieschool.ts";//in_filename  = "cuc_ieschool.mp4";//in_filename  = "cuc_ieschool.h264";in_filename = "./out/cuc_ieschool.flv" //输入URL(Input file URL)//in_filename  = "shanghai03_p.h264";_, err = os.Stat(in_filename)if err != nil {if os.IsNotExist(err) {fmt.Println("create flv file")exec.Command("./lib/ffmpeg", "-i", "./resources/big_buck_bunny.mp4", "-vcodec", "copy", "-acodec", "copy", in_filename).Output()}}out_filename = "rtmp://localhost/publishlive/livestream" //输出 URL(Output URL)[RTMP]//out_filename = "rtp://233.233.233.233:6666";//输出 URL(Output URL)[UDP]libavformat.AvRegisterAll()//Networklibavformat.AvformatNetworkInit()//Inputret = libavformat.AvformatOpenInput(&ifmt_ctx, in_filename, nil, nil)if ret < 0 {fmt.Printf("Could not open input file.")goto end}ret = ifmt_ctx.AvformatFindStreamInfo(nil)if ret < 0 {fmt.Printf("Failed to retrieve input stream information")goto end}for i = 0; i < int32(ifmt_ctx.NbStreams); i++ {if ifmt_ctx.GetStream(uint32(i)).Codec.CodecType == libavutil.AVMEDIA_TYPE_VIDEO {videoindex = ibreak}}ifmt_ctx.AvDumpFormat(0, in_filename, 0)//Outputlibavformat.AvformatAllocOutputContext2(&ofmt_ctx, nil, "flv", out_filename) //RTMP//avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", out_filename);//UDPif ofmt_ctx == nil {fmt.Printf("Could not create output context\n")ret = libavutil.AVERROR_UNKNOWNgoto end}ofmt = ofmt_ctx.Oformatfor i = 0; i < int32(ifmt_ctx.NbStreams); i++ {//Create output AVStream according to input AVStreamin_stream := ifmt_ctx.GetStream(uint32(i))out_stream := ofmt_ctx.AvformatNewStream(in_stream.Codec.Codec)if out_stream == nil {fmt.Printf("Failed allocating output stream\n")ret = libavutil.AVERROR_UNKNOWNgoto end}//Copy the settings of AVCodecContextret = libavcodec.AvcodecCopyContext(out_stream.Codec, in_stream.Codec)if ret < 0 {fmt.Printf("Failed to copy context from input to output stream codec context\n")goto end}out_stream.Codec.CodecTag = 0if ofmt_ctx.Oformat.Flags&libavformat.AVFMT_GLOBALHEADER != 0 {out_stream.Codec.Flags |= libavcodec.AV_CODEC_FLAG_GLOBAL_HEADER}}//Dump Format------------------ofmt_ctx.AvDumpFormat(0, out_filename, 1)//Open output URLif ofmt.Flags&libavformat.AVFMT_NOFILE == 0 {ret = libavformat.AvioOpen(&ofmt_ctx.Pb, out_filename, libavformat.AVIO_FLAG_WRITE)if ret < 0 {fmt.Printf("Could not open output URL '%s'", out_filename)goto end}}//Write file headerret = ofmt_ctx.AvformatWriteHeader(nil)if ret < 0 {fmt.Printf("Error occurred when opening output URL\n")goto end}start_time = libavutil.AvGettime()for {var in_stream, out_stream *libavformat.AVStream//Get an AVPacketret = ifmt_ctx.AvReadFrame(&pkt)if ret < 0 {break}//FIX:No PTS (Example: Raw H.264)//Simple Write PTSif pkt.Pts == libavutil.AV_NOPTS_VALUE {//Write PTStime_base1 := ifmt_ctx.GetStream(uint32(videoindex)).TimeBase//Duration between 2 frames (us)calc_duration := int64(libavutil.AV_TIME_BASE / libavutil.AvQ2d(ifmt_ctx.GetStream(uint32(videoindex)).RFrameRate))//Parameterspkt.Pts = int64(float64(frame_index) * float64(calc_duration) / (libavutil.AvQ2d(time_base1) * libavutil.AV_TIME_BASE))pkt.Dts = pkt.Ptspkt.Duration = int64(float64(calc_duration) / (libavutil.AvQ2d(time_base1) * libavutil.AV_TIME_BASE))}//Important:Delayif pkt.StreamIndex == uint32(videoindex) {time_base := ifmt_ctx.GetStream(uint32(videoindex)).TimeBasetime_base_q := libavutil.AVRational{1, libavutil.AV_TIME_BASE}pts_time := libavutil.AvRescaleQ(pkt.Dts, time_base, time_base_q)now_time := libavutil.AvGettime() - start_timeif pts_time > now_time {libavutil.AvUsleep(uint32(pts_time - now_time))}}in_stream = ifmt_ctx.GetStream(pkt.StreamIndex)out_stream = ofmt_ctx.GetStream(pkt.StreamIndex)/* copy packet *///Convert PTS/DTSpkt.Pts = libavutil.AvRescaleQRnd(pkt.Pts, in_stream.TimeBase, out_stream.TimeBase, libavutil.AV_ROUND_NEAR_INF|libavutil.AV_ROUND_PASS_MINMAX)pkt.Dts = libavutil.AvRescaleQRnd(pkt.Dts, in_stream.TimeBase, out_stream.TimeBase, libavutil.AV_ROUND_NEAR_INF|libavutil.AV_ROUND_PASS_MINMAX)pkt.Duration = libavutil.AvRescaleQ(pkt.Duration, in_stream.TimeBase, out_stream.TimeBase)pkt.Pos = -1//Print to Screenif pkt.StreamIndex == uint32(videoindex) {fmt.Printf("Send %8d video frames to output URL\n", frame_index)frame_index++}//ret = av_write_frame(ofmt_ctx, &pkt);ret = ofmt_ctx.AvInterleavedWriteFrame(&pkt)if ret < 0 {fmt.Printf("Error muxing packet\n")break}pkt.AvFreePacket()}//Write file trailerofmt_ctx.AvWriteTrailer()
end:libavformat.AvformatCloseInput(&ifmt_ctx)/* close output */if ofmt_ctx != nil && ofmt.Flags&libavformat.AVFMT_NOFILE == 0 {ofmt_ctx.Pb.AvioClose()}ofmt_ctx.AvformatFreeContext()if ret < 0 && ret != libavutil.AVERROR_EOF {fmt.Printf("Error occurred.\n")return -1}return 0
}func main() {os.Setenv("Path", os.Getenv("Path")+";./lib")ffcommon.SetAvutilPath("./lib/avutil-56.dll")ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")ffcommon.SetAvfilterPath("./lib/avfilter-56.dll")ffcommon.SetAvformatPath("./lib/avformat-58.dll")ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")ffcommon.SetAvswscalePath("./lib/swscale-5.dll")genDir := "./out"_, err := os.Stat(genDir)if err != nil {if os.IsNotExist(err) {os.Mkdir(genDir, 0777) //  Everyone can read write and execute}}go func() {time.Sleep(1000)exec.Command("./lib/ffplay.exe", "rtmp://localhost/publishlive/livestream").Output()if err != nil {fmt.Println("play err = ", err)}}()main0()
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_77922.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT配置安卓环境(保姆级教程)

目录 下载环境资源 JDK1.8 NDK SDK ​安装QT 配置环境 下载环境资源 JDK1.8 介绍JDK是Java开发的核心工具&#xff0c;为Java开发者提供了一套完整的开发环境&#xff0c;包括开发工具、类库和API等&#xff0c;使得开发者可以高效地编写、测试和运行Java应用程序。 下载…

Java分布式解决方案(三)

文章目录&#x1f525;MySQL事务-MySQL中锁的分类&#x1f525;MySQL事务-MySQL中的死锁问题&#x1f525;MySQL事务-MySQL中锁的分类 MySQL中锁的分类 从本质上讲&#xff0c;锁是一种协调多个进程或多个线程对某一资源的访问的机制&#xff0c;MySQL使用锁和MVCC机制实现了…

【博学谷学习记录】超强总结,用心分享|狂野大数据课程【Spark SQL函数定义】的总结分析

5.1 如何使用窗口函数 回顾: 窗口函数格式:分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])学习的相关分析函数有那些? 第一类: row_number() rank() dense_rank() ntile()第二类: 和聚合函数组合使用 sum() avg() max() min() count…

sklearn使用入门

文章目录1.机器学习1.1 机器学习简介1.2 有监督学习(supervised learning)1.3 无监督学习(unsupervised learning)1.4 半监督学习2. 机器学习工具SKlearn2.1 sklearn2.2 sklearn常用模块2.2.1 分类2.2.2 回归2.2.3 聚类2.2.4 降维2.2.5 模型选择2.2.6 数据预处理2.3 sklearn使用…

ChatGPT vs Bard 背后的技术对比分析和未来发展趋势

ChatGPT vs Bard 背后的技术对比分析和未来发展趋势 目录 ChatGPT vs Bard 背后的技术对比分析和未来发展趋势

SQLI-Labs(3)8-14关【布尔盲注和时间盲注】

目录 第八关 第九关&#xff1a; 第十关 第十一关 第十二关 第十三关 第十四关 第八关 我们用测试语句来测试是否为注入点 从上图中得知存在注入点&#xff0c;那么接下来就是爆列 一共有三列&#xff0c;接下来用union select 和报错注入都试一下发现没有回显点&…

嵌入式安防监控项目——前期知识复习

目录 一、概述 二、C语言 三、数据结构 四、IO进程 五、网络 六、ARM体系结构和接口技术 七、系统移植 八、内核驱动 一、概述 我再报班之前学过51和32&#xff0c;不过都是自学的。报班开始先从应用层入手的&#xff0c;C语言和数据结构。只要是个IT专业的大学这都是必…

cadence专题【1】--多引脚IC如何创建orcad原理图库

cadense下载说明新建工程一、采用传统方式创建1、新建库文件2、放置pin array3、修改管脚信息二、采用电子表格方式创建1、新建库文件2、Ctrlc、Ctrlvcadense下载说明 cadence是目前最流行的EDA&#xff0c;下载装机全交给阿狸狗即可。 浏览器搜索cadence吴川斌或点击链接: ht…

既然有MySQL了,为什么还要有Redis?

目录专栏导读一、同样是缓存&#xff0c;用map不行吗&#xff1f;二、Redis为什么是单线程的&#xff1f;三、Redis真的是单线程的吗&#xff1f;四、Redis优缺点1、优点2、缺点五、Redis常见业务场景六、Redis常见数据类型1、String2、List3、Hash4、Set5、Zset6、BitMap7、Bi…

GDScript 导出变量 (Godot4.0)

概述 导出变量的功能在3.x版本中也是有的&#xff0c;但是4.0版本对其进行了语法上的改进。 导出变量在日常的游戏制作中提供节点的自定义参数化调节功能时非常有用&#xff0c;除此之外还用于自定义资源。 本文是&#xff08;Bilibili巽星石&#xff09;在4.0官方文档《GDScr…

Java学习笔记 --- jQuery

一、jQuery介绍 jQuery&#xff0c;顾名思义&#xff0c;也就是JavaScript和查询&#xff08;Query&#xff09;&#xff0c;它就是辅助JavaScript开发的js类库。它的核心思想是write less&#xff0c;do more&#xff08;写得更少&#xff0c;做得更多&#xff09;&#xff0c…

C语言实现扫雷【详细讲解+全部源码】

扫雷的实现1. 配置运行环境2. 扫雷游戏的初步实现2.1 建立扫雷分布模块2.2 创建名为board的二维数组并进行棋盘初始化2.3 打印棋盘3. 接下来该讨论的事情3.1 布置雷3.2 排查雷3.3 统计坐标周围有几个雷4. 完整扫雷游戏的实现4.1 game.h4.2 game.c4.3 扫雷.c1. 配置运行环境 本游…

信息安全与数学基础-笔记-③一次同余方程

知识目录一次同余方程的解中国剩余定理中国剩余定理的应用一次同余方程的解 本文只研究一次同余方程的解。 f(x) 三 0 (mod m)&#xff0c; 若有一个s能够满足该式子&#xff0c;那么该数字就是该式子的解&#xff0c; 在同余方程式中的解一般写成&#xff1a;x三s (mod m) 同…

04_Apache Pulsar的可视化监控管理、Apache Pulsar的可视化监控部署

1.4.Apache Pulsar的可视化监控管理 1.4.1.Apache Pulsar的可视化监控部署 1.4.Apache Pulsar的可视化监控管理 1.4.1.Apache Pulsar的可视化监控部署 第一步&#xff1a;下载Pulsar-Manager https://archive.apache.org/dist/pulsar/pulsar-manager/pulsar-manager-0.2.0/…

分布式对象存储——Apache Hadoop Ozone

前言 本文隶属于专栏《大数据技术体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见大数据技术体系 1. 概述 Ozone是Apache Hadoop项目的子项目&#xf…

嵌入式和Python(二):python初识及其基本使用规则

目录 一&#xff0c;python基本特点 二&#xff0c;python使用说明 ● 两种编程方式 ① 交互式编程 ② 脚本式编程 ● python中文编码 ● python行和缩进 ● python引号 ● python空行 ● python等待用户输入 ① 没有转换变量类型 ② 转换变量类型 ● python变…

Raspbian镜像无头烧录

Raspbian镜像无头烧录1. 源由2. 需求3. 分析4. 步骤4.1 删除tf卡分区内容4.2 balena烧录镜像4.3 配置USB直接登录4.4 配置WiFi 2.4G网络登录4.5 修改登录账号密码4.6 数据同步和弹出tf卡5. 登录5.1 登录异常处理5.2 WiFi 2.4G网络登录5.3 USB直接登录6. 参考资料7. 补充资料这里…

套接字实现TCP

套接字 套接字的意义就是客户端与服务器进行双向通信的端点&#xff0c;如果有不理解点上面套接字三字更近距离了解套接字。 网络套接字与客户连接的特定网络有关的服务端口号&#xff0c;这个端口号允许linux进入特定的端口号的连接转到正确的服务器进程。 套接字通信的建立过…

JVM运行时数据区—程序计数器

JVM中的程序计数寄存器&#xff08;Program Counter Register&#xff09;中&#xff0c;Register的命名源于CPU的寄存器&#xff0c;寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。 一个线程对应一个…

JavaScript事件循环及任务处理

JavaScript事件循环及任务处理## 浏览器中 JavaScript 的执行流程和 Node.js 中的流程都是基于 事件循环 的。 理解事件循环的工作方式对于代码优化、性能优化很重要&#xff0c;有时对于正确的架构也很重要。 我们首先介绍事件循环工作方式的理论细节&#xff0c;然后介绍该知…