ffmpeg更改视频的帧率
note
视频帧率调整
帧率(fps-frame per second)
例如:原来帧率为30,调整后为1 现象:原来是每秒有30张图像,调整后每秒1张图像,看着图像很慢
实现:在每秒的时间区间里,取一张图像
version
#define LIBAVFILTER_VERSION_MINOR 12
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_MINOR 31
#define LIBAVCODEC_VERSION_MICRO 102
code
void CFfmpegOps::ChangeVideoFPS(const char *in_mp4, const char *out_mp4)
{AVFormatContext *in_fmt_ctx = nullptr;const AVInputFormat *in_fmt = nullptr;AVFormatContext *out_fmt_ctx = nullptr;const AVOutputFormat *out_fmt = nullptr;int ret = -1;int video_stream_index = 0;const AVCodec *decoder = nullptr;AVCodecContext *decoder_ctx = nullptr;const AVCodec* encoder = nullptr;AVCodecContext* encoder_ctx = nullptr;AVStream* in_avstream = nullptr;AVStream* out_avstream = nullptr;const AVFilter * avfilter_buffer_src = nullptr; // 源,video buffer可设置的参数有AVFilterContext* avfilter_ctx_buffer_src = nullptr;const AVFilter * avfilter_fps = nullptr; // 中间节点,video fps可设置的参数包含fpsAVFilterContext* avfilter_ctx_fps = nullptr;const AVFilter* avfilter_buffer_sink = nullptr; // 终,video buffersink可设置的参数只有pixel formatsAVFilterContext* avfilter_ctx_buffer_sink = nullptr;AVFilterGraph* avfiltergraph = nullptr;AVPacket* avpacket_src = nullptr;AVFrame* avframe_src = nullptr;AVFrame* avframe_dest = nullptr;AVPacket* avpacket_dest = nullptr;AVRational pixel_aspect = {.num = 1, .den = 1};ret = avformat_open_input(&in_fmt_ctx, in_mp4, nullptr, nullptr);if (ret < 0){printf("avformat_open_input error(%s)\n", GetFfmpegERR(ret));goto END;}in_fmt = in_fmt_ctx->iformat;ret = avformat_find_stream_info(in_fmt_ctx, nullptr);if (ret < 0){printf("avformat_find_stream_info error(%s)\n", GetFfmpegERR(ret));goto END;}ret = av_find_best_stream(in_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);if (ret < 0){printf("av_find_best_stream error(%s)\n", GetFfmpegERR(ret));goto END;}video_stream_index = ret;in_avstream = in_fmt_ctx->streams[video_stream_index];decoder = avcodec_find_decoder(in_avstream->codecpar->codec_id);if (!decoder){printf("avcodec_find_decoder error\n");goto END;}decoder_ctx = avcodec_alloc_context3(decoder);if (!decoder_ctx){printf("avcodec_alloc_context3 error\n");goto END;}ret = avcodec_parameters_to_context(decoder_ctx, in_avstream->codecpar);if (ret < 0){printf("avcodec_parameters_to_context error(%s)\n", GetFfmpegERR(ret));goto END;}ret = avcodec_open2(decoder_ctx, decoder, nullptr);if (ret < 0){printf("avcodec_open2 error(%s)\n", GetFfmpegERR(ret));goto END;}avfiltergraph = avfilter_graph_alloc();if (!avfiltergraph){printf("avfilter_graph_alloc error\n");goto END;}avfilter_buffer_src = avfilter_get_by_name("buffer"); // buffer对应video,abuffer对应audioif (!avfilter_buffer_src){printf("avfilter_get_by_name error\n");goto END;}printf("avfilter_buffer_src->desc:%s\n", avfilter_buffer_src->description);avfilter_ctx_buffer_src = avfilter_graph_alloc_filter(avfiltergraph, avfilter_buffer_src, avfilter_buffer_src->name);if (!avfilter_ctx_buffer_src){printf("avfilter_graph_alloc_filter error\n");goto END;}// 设置avfilter_ctx_buffer_src的可选参数// 参照libavfilter/buffersrc.c文件中对video buffer的可选参数描述ret = av_opt_set(avfilter_ctx_buffer_src, "width", std::to_string(in_avstream->codecpar->width).c_str(), AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}ret = av_opt_set(avfilter_ctx_buffer_src, "height", std::to_string(in_avstream->codecpar->height).c_str(), AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}ret = av_opt_set(avfilter_ctx_buffer_src, "pix_fmt", av_get_pix_fmt_name((AVPixelFormat)(in_avstream->codecpar->format)), AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}ret = av_opt_set_q(avfilter_ctx_buffer_src,"time_base", in_avstream->time_base,AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}ret = av_opt_set_q(avfilter_ctx_buffer_src,"frame_rate", in_avstream->r_frame_rate,AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}ret = av_opt_set_q(avfilter_ctx_buffer_src,"pixel_aspect", pixel_aspect,AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}// 上面已经设置过参数,初始化就不传参了ret = avfilter_init_str(avfilter_ctx_buffer_src, nullptr);if (ret < 0){printf("avfilter_init_str error(%s)\n", GetFfmpegERR(ret));goto END;}avfilter_fps = avfilter_get_by_name("fps");if (!avfilter_fps){printf("avfilter_get_by_name error\n");goto END;}printf("avfilter_fps->desc:%s\n", avfilter_fps->description);avfilter_ctx_fps = avfilter_graph_alloc_filter(avfiltergraph, avfilter_fps, avfilter_fps->name);if (!avfilter_ctx_fps){printf("avfilter_graph_alloc_filter error\n");goto END;}ret = av_opt_set(avfilter_ctx_fps, "fps", "1",AV_OPT_SEARCH_CHILDREN);if (ret < 0){printf("av_opt_set error(%s)\n", GetFfmpegERR(ret));goto END;}ret = avfilter_init_str(avfilter_ctx_fps, nullptr);if (ret < 0){printf("avfilter_init_str error(%s)\n", GetFfmpegERR(ret));goto END;}avfilter_buffer_sink = avfilter_get_by_name("buffersink");if (!avfilter_buffer_sink){printf("avfilter_get_by_name error\n");goto END;}printf("avfilter_buffer_sink->desc:%s\n", avfilter_buffer_sink->description);avfilter_ctx_buffer_sink = avfilter_graph_alloc_filter(avfiltergraph, avfilter_buffer_sink, avfilter_buffer_sink->name);if (!avfilter_ctx_buffer_sink){printf("avfilter_graph_alloc_filter error\n");goto END;}ret = avfilter_init_str(avfilter_ctx_buffer_sink, nullptr);if (ret < 0){printf("avfilter_init_str error(%s)\n", GetFfmpegERR(ret));goto END;}// 把avfilter组成链// avfilter_link的作用,在src和dest之间新建AVFilterLink实例// srcpad:src的输出通道编号// destpad:dest的输入通道编号ret = avfilter_link(avfilter_ctx_buffer_src, 0, avfilter_ctx_fps, 0);if (ret != 0){printf("avfilter_link error(%s)\n", GetFfmpegERR(ret));goto END;}ret = avfilter_link(avfilter_ctx_fps, 0, avfilter_ctx_buffer_sink, 0);if (ret != 0){printf("avfilter_link error(%s)\n", GetFfmpegERR(ret));goto END;}ret = avfilter_graph_config(avfiltergraph, nullptr);if (ret < 0){printf("avfilter_graph_config error(%s)\n", GetFfmpegERR(ret));goto END;}ret = avformat_alloc_output_context2(&out_fmt_ctx, nullptr, nullptr, out_mp4);if (ret < 0){printf("avformat_alloc_output_context2 error(%s)\n", GetFfmpegERR(ret));goto END;}out_fmt = out_fmt_ctx->oformat;encoder = avcodec_find_encoder(decoder->id);if (!encoder){printf("avcodec_find_encoder error\n");goto END;}encoder_ctx = avcodec_alloc_context3(encoder);if (!encoder_ctx){printf("avcodec_alloc_context3 error\n");goto END;}encoder_ctx->pix_fmt = (AVPixelFormat)(av_buffersink_get_format(avfilter_ctx_buffer_sink));encoder_ctx->width = av_buffersink_get_w(avfilter_ctx_buffer_sink);encoder_ctx->height = av_buffersink_get_h(avfilter_ctx_buffer_sink);encoder_ctx->time_base = av_buffersink_get_time_base(avfilter_ctx_buffer_sink);encoder_ctx->framerate = av_buffersink_get_frame_rate(avfilter_ctx_buffer_sink);encoder_ctx->gop_size = decoder_ctx->gop_size;encoder_ctx->max_b_frames = decoder_ctx->max_b_frames;if (out_fmt->flags & AVFMT_GLOBALHEADER){encoder_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;}ret = avcodec_open2(encoder_ctx, encoder, nullptr);if (ret < 0){printf("avcodec_open2 error(%s)\n", GetFfmpegERR(ret));goto END;}out_avstream = avformat_new_stream(out_fmt_ctx, encoder);if (!out_avstream){printf("avformat_new_stream error\n");goto END;}out_avstream->time_base = av_buffersink_get_time_base(avfilter_ctx_buffer_sink);out_avstream->r_frame_rate = av_buffersink_get_frame_rate(avfilter_ctx_buffer_sink);out_avstream->avg_frame_rate = av_buffersink_get_frame_rate(avfilter_ctx_buffer_sink);ret = avcodec_parameters_from_context(out_avstream->codecpar, encoder_ctx);if (ret < 0){printf("avcodec_parameters_from_context error(%s)\n", GetFfmpegERR(ret));goto END;}ret = avio_open(&(out_fmt_ctx->pb), out_mp4, AVIO_FLAG_WRITE);if (ret < 0){printf("avio_open error(%s)\n", GetFfmpegERR(ret));goto END;}// 调用avformat_write_header后,out_avstream的时间基发生了变化(10->102400),容器要求?ret = avformat_write_header(out_fmt_ctx, nullptr);if (ret < 0){printf("avformat_write_header error(%s)\n", GetFfmpegERR(ret));goto END;}avpacket_src = av_packet_alloc();if (!avpacket_src){printf("av_packet_alloc error\n");goto END;}avpacket_dest = av_packet_alloc();if (!avpacket_dest){printf("av_packet_alloc error\n");goto END;}avframe_src = av_frame_alloc();if (!avframe_src){printf("av_frame_alloc error\n");goto END;}avframe_dest = av_frame_alloc();if (!avframe_dest){printf("av_frame_alloc error\n");goto END;}while (1){// 从输入文件读取压缩视频帧ret = av_read_frame(in_fmt_ctx, avpacket_src);if (ret < 0){printf("av_read_frame error(%s)\n", GetFfmpegERR(ret));break;}if (avpacket_src->stream_index != video_stream_index){av_packet_unref(avpacket_src);continue;}// 把压缩视频帧发送给解码器ret = avcodec_send_packet(decoder_ctx, avpacket_src);if (ret != 0){printf("avcodec_send_packet error(%s)\n", GetFfmpegERR(ret));}else{// 接收解码器的输出视频帧ret = avcodec_receive_frame(decoder_ctx, avframe_src);if (ret != 0){printf("avcodec_receive_frame error(%s)\n", GetFfmpegERR(ret));}else{// 把视频帧交给avfilterret = av_buffersrc_write_frame(avfilter_ctx_buffer_src, avframe_src);if (ret != 0){printf("av_buffersrc_write_frame error(%s)\n", GetFfmpegERR(ret));}else{// 从avfilter获取视频帧ret = av_buffersink_get_frame(avfilter_ctx_buffer_sink, avframe_dest);if (ret < 0){printf("av_buffersink_get_frame error(%s)\n", GetFfmpegERR(ret));}else{// 把视频帧交给编码器ret = avcodec_send_frame(encoder_ctx, avframe_dest);if (ret != 0){printf("avcodec_send_frame error(%s)\n", GetFfmpegERR(ret));}else{// 从编码器获取压缩视频帧ret = avcodec_receive_packet(encoder_ctx, avpacket_dest);if (ret != 0){printf("avcodec_receive_packet error(%s)\n", GetFfmpegERR(ret));}else{av_packet_rescale_ts(avpacket_dest, encoder_ctx->time_base, out_avstream->time_base);// 写入到输出文件ret = av_write_frame(out_fmt_ctx, avpacket_dest);if (ret < 0){printf("av_write_frame error(%s)\n", GetFfmpegERR(ret));}}}}}}}}ret = av_write_trailer(out_fmt_ctx);if (ret < 0){printf("av_write_trailer error(%s)\n", GetFfmpegERR(ret));goto END;}END:if (avframe_dest){av_frame_free(&avframe_dest);avframe_dest = nullptr;}if (avframe_src){av_frame_free(&avframe_src);avframe_src = nullptr;}if (avpacket_src){av_packet_free(&avpacket_src);avpacket_src = nullptr;}if (avpacket_dest){av_packet_free(&avpacket_dest);avpacket_dest = nullptr;}if (avfilter_ctx_buffer_sink){avfilter_free(avfilter_ctx_buffer_sink);avfilter_ctx_buffer_sink = nullptr;}if (avfilter_ctx_fps){avfilter_free(avfilter_ctx_fps);avfilter_ctx_fps = nullptr;}if (avfilter_ctx_buffer_src){avfilter_free(avfilter_ctx_buffer_src);avfilter_ctx_buffer_src = nullptr;}if (avfiltergraph){avfilter_graph_free(&avfiltergraph);avfiltergraph = nullptr;}if (encoder_ctx){avcodec_free_context(&encoder_ctx);encoder_ctx = nullptr;}if (decoder_ctx){avcodec_free_context(&decoder_ctx);decoder_ctx = nullptr;}if (out_fmt_ctx){avformat_free_context(out_fmt_ctx);out_fmt_ctx = nullptr;}if (in_fmt_ctx){avformat_free_context(in_fmt_ctx);in_fmt_ctx = nullptr;}
}
performance
相关文章:

ffmpeg更改视频的帧率
note 视频帧率调整 帧率(fps-frame per second) 例如:原来帧率为30,调整后为1 现象:原来是每秒有30张图像,调整后每秒1张图像,看着图像很慢 实现:在每秒的时间区间里,取一张图像…...

设计模式13-单件模式
设计模式13-单件模式 写在前面对象性能模式典型模式1. 单例模式(Singleton Pattern)2. 享元模式(Flyweight Pattern)3. 原型模式(Prototype Pattern)4. 对象池模式(Object Pool Pattern…...

怎么给PDF文件加密码?关于PDF文件加密的四种方法推荐
怎么给PDF文件加密码?给PDF文件加上密码是保护文件安全的一种重要方法,特别是当需要在不受授权的访问下保护敏感信息时。这个过程不仅仅是简单地设置密码,而是涉及到对文档内容和访问控制的深思熟虑。加密PDF文件可以有效防止未经授权的用户查…...

GoFly快速开发框架基于Go语言和Vue3开发后台管理附件管理插件包
说明 为了给客户提供更好的交互体验,框架把附件管理独立打包成插件包,这样附件管理接可以做个不通需求的附件管理插件包来满足不同甲方客户需求。 目前附件插件包有2个:一个基础包、一个高级包 附件插件包功能 1.基础包 统一管理业务系统…...

matlab实验:实验六MATLAB 数值计算与符号运算
题目1:(线性方程组数值求解) 1. 用不同的方法求解下面方程:(方程原式参考 P369 实验 10,第 1 题) 第 1 种,左除和求逆函数(inv) 第 2 种 , 用 符 号 运 算 的…...
基于STM32设计的老人摔倒检测系统(4G+华为云IOT)(193)
文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】整体构架【3】上位机开发思路【4】供电方式1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】课题研究的意义【5】国内外技术发展现状【6】课题研究思…...
PyTorch和TensorFlow概念及对比
PyTorch和TensorFlow是两个流行的深度学习框架,用于构建和训练机器学习和深度学习模型。它们各自有一些独特的特点和优点: 一 、PyTorch 动态计算图: PyTorch使用动态计算图(Dynamic Computation Graph),…...

github的Codespaces是什么
目录 github的Codespaces是什么 一、定义与功能 二、特点与优势 三、工作原理 四、使用场景与限制 github的Codespaces是什么 GitHub的Codespaces是一个基于云的即时开发环境,它利用容器技术为开发者提供一个完全配置好的开发环境,以便他们能够直接在浏览器或通过Visua…...

Unity UGUI 之 图集
本文仅作学习笔记与交流,不作任何商业用途 本文包括但不限于unity官方手册,唐老狮,麦扣教程知识,引用会标记,如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本,请注意分别 1.什么是图集 精灵图…...
rust日常提问
rust 如何为类 添加一个函数 举例说明 在 Rust 中,我们通常使用 struct(结构体)来创建类似其他语言中的类(class)。Rust 中的结构体可以拥有关联函数(associated functions),这些函数…...

Vue3与Element-plus配合 直接修改表格中的一项数据——控制输入框的显示与隐藏
利用控制与隐藏输入框,直接修改表格中的每一项数据。 <!-- 表格模块 --> <div><el-table :data"tablelist" style"width: 100%"><el-table-column align"center" prop"deposit" label"接单押金">&l…...

设计模式--创建型
实现 #include <iostream> #include <memory>// 抽象产品类 class Product {public:virtual ~Product() {}virtual void Operation() const 0; };// 具体产品 类A class ConcreteProductA : public Product {public:virtual void Operation() const override {st…...

Vue3时间选择器datetimerange在数据库存开始时间和结束时间
♥️作者:小宋1021 🤵♂️个人主页:小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油!…...
鼠标移入事件 mouseover
<template><div><div mouseover"handleMouseOver">区域1</div></div> </template><script> export default {methods: {handleMouseOver() {console.log(鼠标悬停在区域1);}} } </script>...

UE4 自动换行——按排序关键字1.2.3.
要自动换行的字符串举例:“有效节点为:1.demo-worker-02 2.demo-worker-01 3.demo-master-01” 1.获取相邻两位字符串,组合后与关键字比较 2.当两位字符串与关键字相等,附加一次换行 3.其他例如 1)2)3)、(1)(2)(3)、<1><2><…...
Object.entries()解析出来的数组顺序乱了,健是string类型
现象: 从后端哪里拿到了一长串数据 const obj {"2023-07-01":10,"2023-09-18":2,"2023-10-10":3,"2024-01-10":1,"2024-01-12":1,"2024-02-20":4,"2024-07-01":4,... }; 比如上面的数据有一年的 并…...
SSM(Spring + Spring MVC + MyBatis)框架面试三道题
以下是三道关于SSM(Spring Spring MVC MyBatis)框架的面试题,由简单到困难进行排列: 1. 简答题:请简述Spring框架的核心特性。 答案: Spring框架的核心特性主要包括以下几个方面: 控制反转…...

ctfshow-web入门-php特性(web132-web136)
目录 1、web132 2、web133 3、web134 4、web135 5、web136 1、web132 存在 robots.txt 访问 /admin 需要传三个参数,并且需要满足: if($code mt_rand(1,0x36D) && $password $flag || $username "admin"){if($code admin){ech…...

通信原理-实验六:实验测验
实验六 实验测验 一:测验内容和要求 测试需要完成以下几个步骤: 配置好以下网络图;占总分10%(缺少一个扣一分)根据下面图配置好对应的IP和网关以及路由等相关配置,保证设备之间连通正常;占总…...

意得辑润色新用户注册直减15%
ABSJU202 优惠了很多...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...