【FFmpeg学习】视频变慢处理

2024-02-15 17:36

本文主要是介绍【FFmpeg学习】视频变慢处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

视频慢动作处理是个比较常用的操作,可以在播放的时候处理,这里我们考虑把视频修改为慢动作,使用ffmpeg命令,可以这样

ffmpeg -i test.mp4 -vf "setpts=5*PTS" -an test_slow3.mp4

这里把视频放慢了5倍,生成的文件大小也变大了几倍。

怎么用程序来实现呢,参考一下GPT给出的code,

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}// 慢速播放的速度因子
const double SLOWDOWN_FACTOR = 2.0;int main(int argc, char* argv[]) {if (argc < 3) {std::cout << "Usage: " << argv[0] << " input_file output_file" << std::endl;return 1;}const std::string inputFileName = argv[1];const std::string outputFileName = argv[2];av_register_all();AVFormatContext* inputFormatContext = nullptr;if (avformat_open_input(&inputFormatContext, inputFileName.c_str(), nullptr, nullptr) != 0) {std::cerr << "Failed to open input file: " << inputFileName << std::endl;return 1;}if (avformat_find_stream_info(inputFormatContext, nullptr) < 0) {std::cerr << "Failed to retrieve input stream information" << std::endl;avformat_close_input(&inputFormatContext);return 1;}AVFormatContext* outputFormatContext = nullptr;if (avformat_alloc_output_context2(&outputFormatContext, nullptr, nullptr, outputFileName.c_str()) < 0) {std::cerr << "Failed to allocate output format context" << std::endl;avformat_close_input(&inputFormatContext);return 1;}for (unsigned int i = 0; i < inputFormatContext->nb_streams; ++i) {AVStream* inputStream = inputFormatContext->streams[i];AVStream* outputStream = avformat_new_stream(outputFormatContext, nullptr);if (!outputStream) {std::cerr << "Failed to allocate output stream" << std::endl;avformat_close_input(&inputFormatContext);avformat_free_context(outputFormatContext);return 1;}if (avcodec_parameters_copy(outputStream->codecpar, inputStream->codecpar) < 0) {std::cerr << "Failed to copy codec parameters" << std::endl;avformat_close_input(&inputFormatContext);avformat_free_context(outputFormatContext);return 1;}outputStream->time_base = inputStream->time_base;}if (!(outputFormatContext->oformat->flags & AVFMT_NOFILE)) {if (avio_open(&outputFormatContext->pb, outputFileName.c_str(), AVIO_FLAG_WRITE) < 0) {std::cerr << "Failed to open output file: " << outputFileName << std::endl;avformat_close_input(&inputFormatContext);avformat_free_context(outputFormatContext);return 1;}}if (avformat_write_header(outputFormatContext, nullptr) < 0) {std::cerr << "Failed to write output file header" << std::endl;avformat_close_input(&inputFormatContext);avformat_free_context(outputFormatContext);return 1;}AVPacket packet;while (av_read_frame(inputFormatContext, &packet) >= 0) {AVStream* outputStream = outputFormatContext->streams[packet.stream_index];// 慢速播放的时间戳调整packet.pts *= static_cast<int64_t>(SLOWDOWN_FACTOR);packet.dts *= static_cast<int64_t>(SLOWDOWN_FACTOR);packet.duration = static_cast<int>(packet.duration * SLOWDOWN_FACTOR);av_interleaved_write_frame(outputFormatContext, &packet);av_packet_unref(&packet);}av_write_trailer(outputFormatContext);avformat_close_input(&inputFormatContext);avformat_free_context(outputFormatContext);return 0;
}

这个代码执行后并没有实现变慢,参考一下,进行修改后可以实现慢动作处理,如下


int slow() {std::string filename = "test.mp4";     // 输入MP4文件名std::string outputFilename = "test_slow.mp4";  // 输出图片文件名AVFormatContext* ofmt_ctx = nullptr;avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, outputFilename.c_str());const AVOutputFormat* ofmt = ofmt_ctx->oformat;AVFormatContext* formatContext = nullptr;if (avformat_open_input(&formatContext, filename.c_str(), nullptr, nullptr) != 0) {std::cerr << "Error opening input file" << std::endl;return -1;}if (avformat_find_stream_info(formatContext, nullptr) < 0) {std::cerr << "Error finding stream information" << std::endl;avformat_close_input(&formatContext);return -1;}const AVCodec* codec = nullptr;int videoStreamIndex = -1;for (unsigned int i = 0; i < formatContext->nb_streams; i++) {if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoStreamIndex = i;codec = avcodec_find_decoder(formatContext->streams[i]->codecpar->codec_id);//AVStream* out_stream = avformat_new_stream(ofmt_ctx, NULL);avcodec_parameters_copy(out_stream->codecpar, formatContext->streams[i]->codecpar);out_stream->codecpar->codec_tag = 0;break;}}avio_open(&ofmt_ctx->pb, outputFilename.c_str(), AVIO_FLAG_WRITE);avformat_write_header(ofmt_ctx, NULL);AVPacket packet;av_init_packet(&packet);// 计算目标时间戳int64_t targetTimestamp = targetSecond * AV_TIME_BASE;// 查找目标时间戳所对应的帧AVFrame* frame = av_frame_alloc();bool foundTargetFrame = false;int count = 0;while (av_read_frame(formatContext, &packet) >= 0) {if (packet.stream_index == videoStreamIndex) {AVStream* inputStream = formatContext->streams[packet.stream_index];AVStream* outputStream = ofmt_ctx->streams[packet.stream_index];// 计算新的时间戳cout << "1, pts=" << packet.pts << endl;packet.pts = av_rescale_q_rnd(packet.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF);packet.dts = av_rescale_q_rnd(packet.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF);packet.duration = av_rescale_q(packet.duration, inputStream->time_base, outputStream->time_base);packet.pos = -1;cout << "2, pts=" << packet.pts << endl;// 慢速播放的时间戳调整packet.pts *= 5;packet.dts *= 5;packet.duration *= 5;//          av_log(NULL, AV_LOG_INFO, "...av_write_frame(ofmt_ctx, packet);\n");int ret = av_write_frame(ofmt_ctx, &packet);if (ret < 0) {std::cerr << "Error av_write_frame" << std::endl;}count++;}av_packet_unref(&packet);}av_write_trailer(ofmt_ctx);return 1;
}

通过pts的修改来实现

这篇关于【FFmpeg学习】视频变慢处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/712060

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言