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 main import (
"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 AVFormatContext
var ifmt_ctx, ofmt_ctx *libavformat.AVFormatContext
var pkt libavcodec.AVPacket
var in_filename, out_filename string
var i ffcommon.FInt
var videoindex ffcommon.FInt = -1
var frame_index ffcommon.FInt = 0
var start_time ffcommon.FInt64T = 0
var 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()
//Network
libavformat.AvformatNetworkInit()
//Input
ret = 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 = i
break
}
} ifmt_ctx.AvDumpFormat(0, in_filename, 0) //Output libavformat.AvformatAllocOutputContext2(&ofmt_ctx, nil, "flv", out_filename) //RTMP
//avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", out_filename);//UDP if ofmt_ctx == nil {
fmt.Printf("Could not create output context\n")
ret = libavutil.AVERROR_UNKNOWN
goto end
}
ofmt = ofmt_ctx.Oformat
for i = 0; i < int32(ifmt_ctx.NbStreams); i++ {
//Create output AVStream according to input AVStream
in_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_UNKNOWN
goto end
}
//Copy the settings of AVCodecContext
ret = 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 = 0
if 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 URL
if 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 header
ret = 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 AVPacket
ret = ifmt_ctx.AvReadFrame(&pkt)
if ret < 0 {
break
}
//FIX:No PTS (Example: Raw H.264)
//Simple Write PTS
if pkt.Pts == libavutil.AV_NOPTS_VALUE {
//Write PTS
time_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))
//Parameters
pkt.Pts = int64(float64(frame_index) * float64(calc_duration) / (libavutil.AvQ2d(time_base1) * libavutil.AV_TIME_BASE))
pkt.Dts = pkt.Pts
pkt.Duration = int64(float64(calc_duration) / (libavutil.AvQ2d(time_base1) * libavutil.AV_TIME_BASE))
}
//Important:Delay
if pkt.StreamIndex == uint32(videoindex) {
time_base := ifmt_ctx.GetStream(uint32(videoindex)).TimeBase
time_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_time
if 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/DTS
pkt.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 Screen
if 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 trailer
ofmt_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语言编写。的更多相关文章

  1. ffmpeg推送,EasyDarwin转发,vlc播放 实现整个RTSP直播

    部署EasyDarwin流媒体服务器 ffmpeg推送摄像机视频到EasyDarwin VLC播放 第一步:部署EasyDarwin流媒体服务器 EasyDarwin的部署过程我们就不再赘述了,在Ea ...

  2. git推送本地分支到远程分支

    场景 有时候我们开发需要开一个分支,这样可以有效的并行开发. 开分支有两种方式: 一种是在远程开好分支,本地直接拉下来; 一种是本地开好分支,推送到远程. 远程先开好分支然后拉到本地 git chec ...

  3. iOS 疑难杂症 — — 推送本地国际化 loc-key 本地化失败的问题

    声明  欢迎转载,但请保留文章原始出处:)  博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblogs.com 正文 一.准备 推送本地国际化官方 ...

  4. git推送本地分支到远端 以及删除远端分支的 命令

    git推送本地分支到远端 当前处于master分支,尝试用了git push origin warning: push.default is unset; its implicit value is ...

  5. Git for Windows之推送本地版本库到远程仓库

    Git for Windows之基础环境搭建与基础操作中介绍了Git基本环境的构建与基本的操作.生成了一个本地git版本库,本文将介绍如何将这个版本库推送到远程仓库(码云,github也可以). 1. ...

  6. git推送本地仓库到github

    总结一下,方便后人,也方便自己查阅.直接写步骤 一.本地创建一个文件夹,在里面写项目的文件(* .php/*.js.....). git本地操作: 1 .  cd  /path/to/project  ...

  7. git 分支管理 推送本地分支到远程分支等

    1.创建本地分支 local_branch git branch local_branch 2.创建本地分支local_branch 并切换到local_branch分支 git checkout - ...

  8. ffmpeg推送RTSP直播流到EasyDarwin报错问题的修复

    在之前的博客<ffmpeg推送,EasyDarwin转发,vlc播放 实现整个RTSP直播>中,我们介绍了如何采用ffmpeg进行RTSP推送,实现EasyDarwin直播分发的功能,近期 ...

  9. EasyCamera海康摄像机向EasyDarwin云平台推送音视频数据的缓存设计

    本文转自EasyDarwin团队成员Alex的博客:http://blog.csdn.net/cai6811376 EasyCamera在向EasyDarwin云平台推送音视频数据时,有时一个I帧会很 ...

  10. git 推送本地项目到远程库

    git 推送本地项目到远程库 1@DESKTOP-3H9092J MINGW64 /e/mozq/00store/01/SmartCard_MS $ git init Initialized empt ...

随机推荐

  1. MybatisPlus 实现多表联合分页条件查询

    方式一:XML 有点繁琐,不太想用 mapper接口 public interface RoomMapper extends BaseMapper<Room> { List<Room ...

  2. 【Flutter】环境搭建(Windows+Android Studio 3.6.1)

    最近参加的项目需要用到Flutter框架进行iOS/Android双端开发,然而第一步环境搭建的过程就忙活了一整个晚上,直到现在终于有时间静下心来整理一下搭建过程中遇到的困难. 0x00 Flutte ...

  3. Python内置函数:index

    index用于返回指定值在序列的第一个位置 序列.index(值,开始索引,结束索引) 开始索引默认为0,可不传 结束索引默认为序列长度,可不传 >>> str = 'abc' &g ...

  4. VsCode里面在JavaWeb项目里面配置Maven环境详解

    1.在之前已经新建完成一个JavaWeb项目的基础上开始 2.设置里面搜索Maven,找到这个,然后进行定位 3.将Tomcat Server配置进去(右上角有一个加号) (对于已经学过Java的并不 ...

  5. 震惊,一行MD5居然让小伙伴都回不了家!!!

    作者:京东零售 付伟 1. 前言 大家好,当你点开这篇文章的时候也许心想是哪个 XX 小编混到这里,先不要着急扔臭鸡蛋,本文是一篇标准(正经)的问题复盘文章.好了,一行MD5居然让小伙伴下不了班,到底 ...

  6. 红黑树(map与unorder_map)B B+树

    红黑树(map) 这个里面有插入的几种方式:红黑树性质的理解 先说性质,1 每个节点要么红要么黑,2 一个节点为红色,左右两个孩子都是黑, 3 根节点是黑, 4 每个叶子(nil)节点都是黑色, 5 ...

  7. 简述SpringAOP的实现原理

    ​ Spring默认采取的动态代理机制实现AOP,当动态代理不可用时 (代理类无接口)会使用CGlib机制. Spring提供了两种方式来生成代理对象:JDKProxy和Cglib,具体使用哪种方式生 ...

  8. java注解与反射--3

    java注解与反射--3 类的加载与ClassLoader java内存 堆 存放new的对象和数组 可以被所有的线程共享,不会存放别的对象引用 栈 存放基本变量类型 引用对象的变量 方法区 可以被所 ...

  9. RunnerGo可视化场景管理,还原真实场景

    在进行性能测试时,测试场景的正确配置非常关键.首先,需要根据业务场景和需求,设计出合理的测试场景,再利用相应的工具进行配置,实现自动化的性能测试. 在JMeter中,用户需要自己组织测试场景,或是在同 ...

  10. 随机森林n_estimators 学习曲线

    随机森林 单颗树与随机森林的的分对比 # 导入包 from sklearn.datasets import load_wine from sklearn.model_selection import ...