当前位置:首页 > 实用技巧 >

如何修改视频解码(如何修改视频上的文字内容)

来源:原点资讯(www.yd166.com)时间:2023-05-22 11:59:09作者:YD166手机阅读>>

2023-04-01:当Go语言遇见FFmpeg视频解码器,使用Go语言改写decode_video.c文件,提升视频解码效率与开发体验。

答案2023-04-01:

步骤如下:

1.导入必要的依赖库,包括 fmt、os、unsafe 和其它 FFmpeg 库相关的 Go 库。

2.定义一个名为 main0() 的函数,该函数负责视频解码操作。在函数中定义了许多变量,例如文件名、编解码器、解析器、编解码器上下文、文件句柄、AVFrame 等等。

3.通过命令行参数获取输入文件名和输出文件名,并进行一些基本的参数检查。

4.通过调用 AvPacketAlloc() 函数创建一个 AVPacket 对象,用于存储解码后的帧数据。如果创建失败,则退出程序。

5.初始化输入缓冲区 inbuf 并设置结尾填充字节为 0。

6.调用 AvcodecFindDecoder() 函数查找 MPEG-1 视频解码器。如果找不到,则退出程序。

7.调用 AvParserInit() 函数初始化解析器。如果初始化失败,则退出程序。

8.调用 AvCodecAllocContext3() 函数分配一个新的编解码器上下文对象。如果分配失败,则退出程序。

9.调用 AvcodecOpen2() 函数打开编解码器。如果打开失败,则退出程序。

10.打开输入文件,并创建一个 AVFrame 对象。

11.进入循环,读取输入文件并将其分解成视频帧。如果读取失败或读取完毕,则跳出循环。

12.调用 AvParserParse2() 函数将输入缓冲区中的数据解析为视频帧,并存储在 AVPacket 对象中。如果解析失败,则退出程序。

13.如果成功解析到一个视频帧,则调用 decode() 函数对其进行解码并保存到输出文件中。

14.在循环结束后,调用 decode() 函数对剩余的数据进行解码并保存到输出文件中。

15.关闭输入文件句柄、解析器、编解码器上下文和 AVFrame 对象等资源,以避免内存泄漏。

16.定义一个名为 pgm_save() 的函数,该函数用于将视频帧写入 PGM 格式文件。

17.定义一个名为 decode() 的函数,该函数用于对视频帧进行解码并调用 pgm_save() 函数将其写入 PGM 格式文件。

18.定义 main() 函数,该函数将 FFmpeg 库的路径设置为当前目录下的 lib 子目录,并调用 main0() 函数进行视频解码操作。

注意:在 Windows 操作系统中,您可能需要将 FFmpeg 库的可执行文件添加到 PATH 环境变量中,或者使用 SetXXXPath() 函数设置它们的路径,才能够正常运行此代码。

代码见github/moonfdd/ffmpeg-go。

执行命令:

./lib/ffmpeg -i ./resources/big_buck_bunny.mp4 -c:v mpeg1video ./out/big_buck_bunny.mpg go run ./examples/internalexamples/decode_video/main.go ./out/big_buck_bunny.mpg ./out/ppm/big_buck_bunny.yuv ./lib/ffplay ./out/ppm/big_buck_bunny.yuv-113.ppm

golang代码如下:

package main import ( "fmt" "os" "unsafe" "github.com/moonfdd/ffmpeg-go/ffcommon" "github.com/moonfdd/ffmpeg-go/libavcodec" "github.com/moonfdd/ffmpeg-go/libavutil" ) func main0() (ret ffcommon.FInt) { var Filename, outfilename string var codec *libavcodec.AVCodec var parser *libavcodec.AVCodecParserContext var c *libavcodec.AVCodecContext var f *os.File var frame *libavutil.AVFrame var inbuf [INBUF_SIZE libavcodec.AV_INPUT_BUFFER_PADDING_SIZE]ffcommon.FUint8T var data *ffcommon.FUint8T var data_size ffcommon.FSizeT var pkt *libavcodec.AVPacket if len(os.Args) <= 2 { fmt.Printf("Usage: %s <input file> <output file>\nAnd check your input file is encoded by mpeg1video please.\n", os.Args[0]) os.Exit(0) } filename = os.Args[1] outfilename = os.Args[2] pkt = libavcodec.AvPacketAlloc() if pkt == nil { os.Exit(1) } /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ //memset(inbuf INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); /* find the MPEG-1 video decoder */ codec = libavcodec.AvcodecFindDecoder(libavcodec.AV_CODEC_ID_MPEG1VIDEO) if codec == nil { fmt.Printf("Codec not found\n") os.Exit(1) } parser = libavcodec.AvParserInit(int32(codec.Id)) if parser == nil { fmt.Printf("parser not found\n") os.Exit(1) } c = codec.AvcodecAllocContext3() if c == nil { fmt.Printf("Could not allocate video codec context\n") os.Exit(1) } /* For some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because this information is not available in the bitstream. */ /* open it */ if c.AvcodecOpen2(codec, nil) < 0 { fmt.Printf("Could not open codec\n") os.Exit(1) } var err error f, err = os.Open(filename) if err != nil { fmt.Printf("Could not open %s,err = %s\n", filename, err) os.Exit(1) } frame = libavutil.AvFrameAlloc() if frame == nil { fmt.Printf("Could not allocate video frame\n") os.Exit(1) } for { /* read raw data from the input file */ var n int n, err = f.Read(inbuf[:INBUF_SIZE]) if err != nil { break } data_size = uint64(n) if data_size == 0 { break } /* use the parser to split the data into frames */ data = (*byte)(unsafe.Pointer(&inbuf)) for data_size > 0 { ret = parser.AvParserParse2(c, &pkt.Data, (*int32)(unsafe.Pointer(&pkt.Size)), data, int32(data_size), libavutil.AV_NOPTS_VALUE, libavutil.AV_NOPTS_VALUE, 0) if ret < 0 { fmt.Printf("Error while parsing\n") os.Exit(1) } data = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(data)) uintptr(ret))) data_size -= uint64(ret) if pkt.Size != 0 { decode(c, frame, pkt, outfilename) } } } /* flush the decoder */ decode(c, frame, nil, outfilename) f.Close() parser.AvParserClose() libavcodec.AvcodecFreeContext(&c) libavutil.AvFrameFree(&frame) libavcodec.AvPacketFree(&pkt) return 0 } const INBUF_SIZE = 4096 func pgm_save(buf ffcommon.FBuf, wrap, xsize, ysize ffcommon.FInt, filename string) { var f *os.File var i ffcommon.FInt var err error f, err = os.Create(filename) if err != nil { return } f.WriteString(fmt.Sprintf("P5\n%d %d\n%d\n", xsize, ysize, 255)) bytes := []byte{} for i = 0; i < ysize; i { for j := int32(0); j < xsize; j { bytes = append(bytes, *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(buf)) uintptr(i*wrap j)))) } } f.Write(bytes) f.Close() } func decode(dec_ctx *libavcodec.AVCodecContext, frame *libavutil.AVFrame, pkt *libavcodec.AVPacket, filename string) { // var buf [1024]byte var ret ffcommon.FInt ret = dec_ctx.AvcodecSendPacket(pkt) if ret < 0 { fmt.Printf("Error sending a packet for decoding\n") os.Exit(1) } for ret >= 0 { ret = dec_ctx.AvcodecReceiveFrame(frame) if ret == -libavutil.EAGAIN || ret == libavutil.AVERROR_EOF { return } else if ret < 0 { fmt.Printf("Error during decoding %d\n", ret) os.Exit(1) } fmt.Printf("saving frame =\n", dec_ctx.FrameNumber) //fflush(stdout) /* the picture is allocated by the decoder. no need to free it */ pgm_save(frame.Data[0], frame.Linesize[0], frame.Width, frame.Height, fmt.Sprintf("%s-%d.ppm", filename, dec_ctx.FrameNumber)) } } 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 } } main0() }

如何修改视频解码,如何修改视频上的文字内容(1)

栏目热文

视频解码方式怎么选(视频解码网站)

视频解码方式怎么选(视频解码网站)

经常看视频的用户会发现一些视频器上会有两个不同的解码方式——软解和硬解,选择不同的解码方式看看播放效果没有什么不同,那么...

2023-05-22 11:36:04查看全文 >>

制作视频解码(制作视频能赚钱吗)

制作视频解码(制作视频能赚钱吗)

视频的传输,如果是传输全部的图像帧,即按照无损压缩的方式传输,其数据量之巨大对于网络和存储都是难以支撑的。通过对视频进...

2023-05-22 12:00:00查看全文 >>

视频网站怎么设置解码(视频快速解码)

视频网站怎么设置解码(视频快速解码)

IT之家 2 月 6 日消息,去年 8 月,B 站宣布网页端现支持 HEVC 解码,并且表示未来还会支持 AV1 解码。...

2023-05-22 12:12:22查看全文 >>

视频解码格式大全(如何给视频解码)

视频解码格式大全(如何给视频解码)

视频文件格式并非一刀切,不同的文件格式有不同的用途,作为摄像师或视频内容创建者,了解这些差异很有帮助。 无论你是...

2023-05-22 11:44:30查看全文 >>

视频解码方法(视频合成解码)

视频解码方法(视频合成解码)

弱电学习圈VIP群已经建立,欢迎大家进群后讨论技术问题,设计方案,投标、施工,工程合作,产品对接等方面,都可以。其中VI...

2023-05-22 12:21:36查看全文 >>

视频无法正常解码(下载的视频解码不了)

视频无法正常解码(下载的视频解码不了)

视频编解码器,是指一个能够对数字视频进行压缩或者解压缩的程序或者设备。通常这种压缩属于有损数据压缩。历史上,视频信号是以...

2023-05-22 12:02:03查看全文 >>

视频无法正常解码怎么办(视频解码出错怎么解决)

视频无法正常解码怎么办(视频解码出错怎么解决)

您好,“解码通道未用/解码失败”表明目前解码器还未解码对应的编码通道:1、请确认编码分辨率是否超过设备限制。2、确认摄像...

2023-05-22 12:21:30查看全文 >>

视频低版本解码方式(视频怎样重新解码)

视频低版本解码方式(视频怎样重新解码)

Live CheatSheet | 直播技术理论基础与实践概论音视频直播的基本流程都是采集 → 编码推流 → 网络分发 ...

2023-05-22 12:06:02查看全文 >>

电脑卡住关不了咋办(电脑卡住了怎么解决)

电脑卡住关不了咋办(电脑卡住了怎么解决)

以下几个情况你遇到过吗?电脑卡住,怎么操作都没有反应?或者是下班着急回家,电脑半天都关不上?要么系统更新太慢,一直停在9...

2023-05-22 11:52:02查看全文 >>

电脑开机进入主板界面找不到设置(电脑开机显示主板界面就不动了是为什么?)

电脑开机进入主板界面找不到设置(电脑开机显示主板界面就不动了是为什么?)

bios即“Basic Input Output System”的缩略,译成中文的意思即“基本输入输出系统”。它保存着...

2023-05-22 12:11:04查看全文 >>

文档排行