2023-03-05:ffmpeg推送本地视频至lal流媒体服务器(以RTMP为例),请用go语言编写。
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()
}
相关文章:

2023-03-05:ffmpeg推送本地视频至lal流媒体服务器(以RTMP为例),请用go语言编写。
2023-03-05:ffmpeg推送本地视频至lal流媒体服务器(以RTMP为例),请用go语言编写。 答案2023-03-05: 使用 github.com/moonfdd/ffmpeg-go 库。 先启动lal流媒体服务器软件,然后再执行命令: go…...

MathType7最新版免费数学公式编辑器
话说我也算是 MathType准资深(DB)用户了,当然自从感觉用DB不好之后,我基本上已经抛弃它了,只是前不久因为个别原因又捡起来用了用,30天试用期间又比较深入的折腾了下,也算是变成半个MathType砖家,coco玛奇朵简单介绍一下这款软件:在很可能看到这儿的你还没有出生的某个年月&…...

一文带你入门angular(中)
一、angular中的dom操作原生和ViewChild两种方式以及css3动画 1.原生操作 import { Component } from angular/core;Component({selector: app-footer,templateUrl: ./footer.component.html,styleUrls: [./footer.component.scss] }) export class FooterComponent {flag: b…...
单例设计模式共享数据问题分析、解决(c++11)设计多线程。
系列文章目录 单例设计模式共享数据问题分析、解决; 文章目录系列文章目录前言一、单例模式1.1 基本概念1.2 单例设计模式共享数据问题分析、解决1.3 std::call_once()介绍二、代码案例1.代码示例总结前言 关键内容:c11、多线程、共享数据、单例类 本章内容参考git…...
Embedding-based Retrieval in Facebook Search
facebook的社交网络检索与传统的搜索检索的差异是,除了考虑文本,还要考虑搜索者的背景。通用搜索主要考虑的是文本匹配,并没有涉及到个性化。像淘宝,youtube这些其实都是涉及到了用户自身行为的,除了搜索还有推荐&…...

xmu 离散数学 卢杨班作业详解【8-12章】
文章目录第八章 树23456810第九章46811第十章24567第十一章14571116第十二章131317第八章 树 2 (2) 设有k片树叶 2∗m2∗43∗3k2*m2*43*3k2∗m2∗43∗3k n23kn23kn23k mn−1mn-1mn−1 联立解得k9 T中有9片树叶 3 有三颗非同构的生成树 4 (1) c --abc e–abed f–dgf…...
Linux入门篇-权限管理
简介 用户管理也是和权限相关的知识点。权限的作用 权限对于普通文件和目录文件作用是不一样的 。[kioskfoundation0 ~]$ ls -l total 264 -rw-rw-r--. 2 kiosk kiosk 31943 May 29 2019 ClassPrep.txt -rw-rw-r--. 2 kiosk kiosk 7605 Jun 14 2019 ClassRHAPrep.txt -rw-rw-r…...

Linux(基于 Centos7) 常用操作
1.Linux 简介Linux 是一种 免费使用、自由传播的类 Unix 操作系统Linux操作系统内核,由林纳斯托瓦兹在1991年10月5日首次发布...Linux 是一套开源操作系统,它有稳定、消耗资源小、安全性高等特点大多数人都是直接使用 Linux 发行版(就是将 Li…...

Math类详解与Random类、三种随机数生成方式(java)
文章目录📖前言:🎀认识Random类🎀三种随机数生成方式🎀Math类的用途🎀Math类的方法📖前言: 本篇博客主要以介绍Math类的常用方法及认识Random类,及三种随机数生成方式 …...
Mac编译QT程序出现Undefined symbols for architecture x86_64
在Mac编写日志服务类, Logging_d.h内容如下 #pragma once #include <QLoggingCategory> Q_DECLARE_LOGGING_CATEGORY(hovering) Q_DECLARE_LOGGING_CATEGORY(creation) Q_DECLARE_LOGGING_CATEGORY(mouseevents) Q_DECLARE_LOGGING_CATEGORY(state) Q_DECLARE_LOGGING_C…...

蓝桥杯-李白打酒加强版
蓝桥杯-李白打酒加强版1、问题描述2、解题思路3、代码实现1、问题描述 话说大诗人李白, 一生好饮。幸好他从不开车。 一天, 他提着酒显, 从家里出来, 酒显中有酒 2 斗。他边走边唱: 无事街上走,提显去打酒。 逢店加一倍, 遇花喝一斗。 这一路上, 他一共遇到店 N 次…...
AtCoder Beginner Contest 292 (A - E) 记录第一场ABC
AtCoder Beginner Contest 292 A - E前言Q1 A - CAPS LOCKQ2 Yellow and Red CardQ3 Four VariablesQ4 D - Unicyclic ComponentsQ5 E - Transitivity前言 本来晚上在打Acwing周赛,最后一题Trie想不出来咋写,看群里有人说ABC要开始了,想着没…...

ubuntu安装使用putty
一、安装 安装虚拟机串口 sudo apt-get install putty sudo apt install -y setserial 二、使用 虚拟机连接串口 sudo setserial -g /dev/ttyS* 查看硬件对应串口 找到不是unknown的串口 sudo putty...
【CS144】Lab5与Lab6总结
Lab5与Lab6Lab汇总Lab5概述Lab6概述由于Lab5和Lab6相对比较简单(跟着文档一步一步写就行),于是放在一起做一个简单概述(主要是懒得写了…) Lab汇总 Lab5概述 lab5要求实现一个IP与Ethernet(以太网&#x…...

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

shell:#!/usr/bin/env python作用是什么
我们经常会在别人的脚本文件里看到第一行是下面这样 #!/usr/bin/python或者 #!/usr/bin/env python 那么他们有什么用呢? 要理解它,得把这一行语句拆成两部分。 第一部分是 #! 第二部分是 /usr/bin/python 或者 /usr/bin/env python 关于 #! 这个…...
计算机行业AIGC算力时代系列报告-ChatGPT芯片算力:研究框架
报告下载: 计算机行业AIGC算力时代系列报告-ChatGPT芯片算力:研究框架 简介 “AI算力时代已经来临,计算机行业正在经历着一场前所未有的变革!” 这是一个充满活力和兴奋的时代,人工智能(AI)已…...

『MyBatis技术内幕』源码调试前提
准备源代码包 下载源代码 3.4.6 版本 https://github.com/mybatis/mybatis-3/releases?page2 通过 idea 导入然后回自动下载所有依赖,根据 3.4.6 版本的 pom.xml 找到依赖的 mybatis-parent 版本 <parent><groupId>org.mybatis</groupId><ar…...
# Linux最新2022年面试题大汇总,附答案
# Linux最新2022年面试题大汇总,附答案 ### [1、cp(copy单词缩写,复制功能)](最新2021年面试题大汇总,附答案.md#1cpcopy单词缩写复制功能) cp /opt/java/java.log /opt/logs/ ;把java.log 复制到/opt/logs/下 cp /…...

css中重难点整理
一、vertical-align 在学习vertical-align的时候,可能会很困惑。即使网上有一大推文章讲veitical-align,感觉看完好像懂了,等自己布局的时候用到vertical-align的时候好像对它又很陌生。这就是我在布局的时候遇到的问题。 本来vertical-align就很不好理…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...