ffmpeg封装和解封装介绍-(6)完成重封装mp4文件并截断10s~20s的视频并生成10s视频文件

源文件:

#include <iostream>
#include <thread>
using namespace std;
extern "C" { //指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include <libavformat/avformat.h>
}
//预处理指令导入库
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
void PrintErr(int err)
{char buf[1024] = { 0 };av_strerror(err, buf, sizeof(buf) - 1);cerr << endl;
}
#define CERR(err) if(err!=0){ PrintErr(err);getchar();return -1;}int main(int argc, char* argv[])
{//打开媒体文件const char* url = "v1080.mp4";/// 解封装//解封装输入上下文AVFormatContext* ic = nullptr;//初始化格式上下文IC//*Open an input streamand read the header.The codecs are not opened.
//* The stream must be closed with avformat_close_input().auto re = avformat_open_input(&ic, url,NULL,       //封装器格式 null 自动探测 根据后缀名或者文件头NULL        //参数设置,rtsp需要设置);CERR(re);//获取媒体信息 无头部格式re = avformat_find_stream_info(ic, NULL);CERR(re);//打印封装信息av_dump_format(ic, 0, url,0 //0表示上下文是输入 1 输出);AVStream* as = nullptr; //音频流AVStream* vs = nullptr; //视频流for (int i = 0; i < ic->nb_streams; i++){//音频if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){as = ic->streams[i];cout << "=====音频=====" << endl;cout << "sample_rate:" << as->codecpar->sample_rate << endl;}else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){vs = ic->streams[i];cout << "=========视频=========" << endl;cout << "width:" << vs->codecpar->width << endl;cout << "height:" << vs->codecpar->height << endl;}}/// 解封装/开始编码到文件中//编码器上下文const char* out_url = "test_mux.mp4";AVFormatContext* ec = nullptr;re = avformat_alloc_output_context2(&ec, NULL, NULL,out_url         //根据文件名推测封装格式);CERR(re);//再output文件的上下文ec中添加视频流、音频流auto mvs = avformat_new_stream(ec, NULL);  //视频流auto mas = avformat_new_stream(ec, NULL);  //音频流//打开输出IOre = avio_open(&ec->pb, out_url, AVIO_FLAG_WRITE);CERR(re);//设置编码音视频流参数//ec->streams[0];//mvs->codecpar;//视频参数if (vs){mvs->time_base = vs->time_base;// 时间基数与原视频一致//从解封装复制参数avcodec_parameters_copy(mvs->codecpar, vs->codecpar);}if (as){mas->time_base = as->time_base;//从解封装复制参数avcodec_parameters_copy(mas->codecpar, as->codecpar);}//写入文件头re = avformat_write_header(ec, NULL);CERR(re);//打印输出上下文av_dump_format(ec, 0, out_url, 1);/// 截取10 ~ 20 秒之间的音频视频 取多不取少// 假定 9 11秒有关键帧 我们取第9秒double begin_sec = 10.0;    //截取开始时间double end_sec = 20.0;      //截取结束时间long long begin_pts = 0;long long begin_audio_pts = 0;  //音频的开始时间long long end_pts = 0;//换算成pts 换算成输入ic的pts,以视频流为准if (vs && vs->time_base.num > 0){//sec /timebase = pts// pts =  sec/(num/den) = sec* (den/num)  double t = (double)vs->time_base.den / (double)vs->time_base.num;//den分母/num分子begin_pts = begin_sec * t;end_pts = end_sec * t;}if (as && as->time_base.num > 0)begin_audio_pts = begin_sec * ((double)as->time_base.den / (double)as->time_base.num);//seek输入媒体 移动到第十秒的关键帧位置if (vs)re = av_seek_frame(ic, vs->index, begin_pts,AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD); //向后关键帧CERR(re);AVPacket pkt;for (;;){re = av_read_frame(ic, &pkt);if (re != 0){PrintErr(re);break;}AVStream* in_stream = ic->streams[pkt.stream_index];AVStream* out_stream = nullptr;long long offset_pts = 0; //偏移pts,用于截断的开头pts运算if (vs && pkt.stream_index == vs->index){cout << "视频:";//超过第20秒退出,只存10~20秒if (pkt.pts > end_pts){av_packet_unref(&pkt);break;}out_stream = ec->streams[0];offset_pts = begin_pts;}else if (as && pkt.stream_index == as->index){cout << "音频:";out_stream = ec->streams[1];offset_pts = begin_audio_pts;}cout << pkt.pts << " : " << pkt.dts << " :" << pkt.size << endl;//重新计算pts dts duration//`a * bq(输入basetime) / cq(输出basetime)`if (out_stream){pkt.pts = av_rescale_q_rnd(pkt.pts - offset_pts, in_stream->time_base,out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.dts = av_rescale_q_rnd(pkt.dts - offset_pts, in_stream->time_base,out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);}pkt.pos = -1;//写入音视频帧 会清理pktre = av_interleaved_write_frame(ec,&pkt);if (re != 0){PrintErr(re);}//av_packet_unref(&pkt);//this_thread::sleep_for(100ms);}//写入结尾 包含文件偏移索引re = av_write_trailer(ec);if (re != 0)PrintErr(re);avformat_close_input(&ic);avio_closep(&ec->pb);avformat_free_context(ec);ec = nullptr;return 0;
}

运行结果:

成功生产力另一个mp4文件,内容为我们重新封装的音视频流,和解封装之前的视频一样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/852892.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java语言+前端框架html+Thymeleaf +后端框架springboot开发的UWB智能定位系统源码 UWB三维可视化人员定位系统源码

Java语言前端框架htmlThymeleaf 后端框架springboot开发的UWB智能定位系统源码 UWB三维可视化人员定位系统源码 UWB定位系统基于B/S架构的软件和嵌入式硬件都具有很好的扩展性和兼容性&#xff0c;可以与其他系统接口&#xff08;比如&#xff1a;围界、AB门、高压电网、报警、…

对抗式生成模仿学习(GAIL)

目录 1 预先基础知识 1.1 对抗生成网络&#xff08;GAN&#xff09; 1.1.1 基本概念 1.1.2 损失函数 1.1.2.1 固定G&#xff0c;求解令损失函数最大的D 1.1.2.2 固定D&#xff0c;求解令损失函数最小的G 1.2 对抗式生成模仿学习特点 2 对抗式生成模仿学习&#xff08;…

【CS.PL】Lua 编程之道: 简介与环境设置 - 进度8%

1 初级阶段 —— 简介与环境设置 文章目录 1 初级阶段 —— 简介与环境设置1.1 什么是 Lua&#xff1f;特点?1.2 Lua 的应用领域1.3 安装 Lua 解释器1.3.1 安装1.3.2 Lua解释器的结构 1.4 Lua执行方式1.4.0 程序段1.4.1 使用 Lua REPL&#xff08;Read-Eval-Print Loop&#x…

计算机专业在未来的发展与抉择

目录 前言 计算机专业的发展历史 计算机专业的前景 计算机专业的挑战 如何判断自己是否适合计算机专业 计算机行业的未来发展态势 作为过来人和从业者 前言 随着2024年高考落幕&#xff0c;数百万高三学生又将面临人生中的重要抉择&#xff1a;选择大学专业。在这个关键…

鸿蒙Arkts上传图片并获取接口返回信息

需求&#xff1a; 选择相册图片后&#xff0c;将文件上传到服务器&#xff0c;接口会返回图片地址。 问题&#xff1a; 1、鸿蒙自带的文件上传返回值只会返回上传状态&#xff0c;不会返回接口返回信息。 类似问题 HarmonyOS上传文件以及权限授权_harmonyos中axios上传文件…

古诗词的魅力

目录&#xff1a; 一、换一种说法 二、宋词的男女对白 1、女问男答 2、男问女答 一、换一种说法 “独上高楼&#xff0c;望尽天涯路”的满心期盼。 “春风得意马蹄疾&#xff0c;一日看尽长安花"的志得意满。 “山重水复疑无路&#xff0c;柳暗花明又一村”的苦尽甘…

【Gradio】Building With Blocks 控制布局

默认情况下&#xff0c;块中的组件垂直排列。让我们看看如何重新排列组件。在底层&#xff0c;这种布局结构使用了网页开发的 flexbox 模型。 行 在 with gr.Row 子句中的元素将全部水平显示。例如&#xff0c;要并排显示两个按钮&#xff1a; with gr.Blocks() as demo:with g…

JAVA云HIS医院管理系统源码 云HIS运维平台源码 SaaS模式支撑电子病历4级,HIS与电子病历系统均拥有自主知识产权

JAVA云HIS医院管理系统源码 云HIS运维平台源码 SaaS模式支撑电子病历4级&#xff0c;HIS与电子病历系统均拥有自主知识产权 系统简介&#xff1a; SaaS模式Java版云HIS系统&#xff0c;在公立二甲医院应用三年&#xff0c;经过多年持续优化和打磨&#xff0c;系统运行稳定、功…

Unity C#中校对两个列表内数据是否正确

Unity C#中校对两个列表内数据是否正确 using System.Collections.Generic; using UnityEngine;public class ListComparer : MonoBehaviour {// 示例列表public List<string> list1 new List<string> { "apple", "banana", "cherry&qu…

SSH密钥认证:实现远程服务器免密登录的两种方法|Linux scp命令详解:高效实现文件与目录的远程传输

简介&#xff1a; 服务器之间经常需要有一些跨服务器的操作&#xff0c;此时就需要我们在一台服务器上登录到另外一台服务器&#xff0c;若是人为操作时我们都可以每次输入密码进行远程登录&#xff0c;但要是程序需要跨服务器时&#xff0c;每次输入密码就不现实了&#xff0c…

最新Sublime Text软件安装包分享(汉化版本)

Sublime Text 是一款广受欢迎的跨平台文本编辑器&#xff0c;专为代码、标记和散文编辑而设计。它以其简洁的用户界面、强大的功能和高性能而著称&#xff0c;深受开发者和写作者的喜爱。 一、下载地址 链接&#xff1a;https://pan.baidu.com/s/1kErSkvc7WnML7fljQZlcOg?pwdk…

docker 拉取镜像拉取超时的解决方法

错误提示&#xff1a; error pulling image configuration: download failed after attempts6: dial tcp 67.228.102.32:443: connect: connection refused latest: Pulling from freeradius/freeradius-server a8b1c5f80c2d: Retrying in 1 second 37ffe8884f09: Retryin…

Makefile并发执行

引言 最近在编译项目代码的时候&#xff0c;发现全量编译一次代码需要十分钟&#xff0c;加了多核编译参数之后&#xff0c;还会出现各种错误&#xff0c;导致编译失败。于是我就想改造下makefile文件&#xff0c;使其能够多核编译&#xff0c;经过改造之后&#xff0c;效果显…

解决:安装MySQL 5.7 的时候报错:unknown variable ‘mysqlx_port=0.0‘

目录 1. 背景2. 解决步骤 1. 背景 吐槽1&#xff0c;没被收购之前可以随便下载&#xff0c;现在下载要注册登录吐槽2&#xff0c;5.7安装到初始化数据库的时候就会报错&#xff0c;而8.x的可以一镜到底&#xff0c;一开始以为是国区的特色问题&#xff0c;google了一圈&#x…

[Algorithm][贪心][最长递增子序列][递增的三元子序列][最长连续递增序列][买卖股票的最佳时机][买卖股票的最佳时机Ⅱ]详细讲解

目录 1.最长递增子序列1.题目链接2.算法原理详解3.代码实现 2.递增的三元子序列1.题目链接2.算法原理详解3.题目链接 3.最长连续递增序列1.题目链接2.算法原理详解3.代码实现 4.买卖股票的最佳时机1.题目链接2.算法原理详解3.代码实现 5.买卖股票的最佳时机 II1.题目链接2.算法…

厂里资讯之总体架构介绍以及环境搭建

本项目是本人根据黑马程序员的微服务项目黑马头条进行包装改造&#xff0c;作为实习简历上面的项目&#xff0c;为了进一步熟悉深挖这个项目&#xff0c;写了这一系列的博客来加深自己对项目的理解。 概述 项目背景 本项目主要着手于使用户获取学校最新最热的资讯&#xff0c…

Django自定义CSS

创建一个CSS文件&#xff08;例如admin_custom.css&#xff09;&#xff0c;并在其中添加针对你希望修改的字段的CSS规则。在你的Django项目的settings.py文件中&#xff0c;添加自定义CSS文件的路径到STATICFILES_DIRS。 # settings.py STATICFILES_DIRS [ os.path.join(BA…

论文阅读(一种新的稀疏PCA求解方式)Sparse PCA: A Geometric Approach

这是一篇来自JMLR的论文&#xff0c;论文主要关注稀疏主成分分析&#xff08;Sparse PCA&#xff09;的问题&#xff0c;提出了一种新颖的几何解法&#xff08;GeoSPCA&#xff09;。 该方法相比传统稀疏PCA的解法的优点&#xff1a;1&#xff09;更容易找到全局最优&#xff…

JavaScript同一性校验

入门版 /*** validCommon* 同一性校验: 满足返回true&#xff0c;不满足返回false。* * param arr: 数组。* param fields: 字段域。* * return bolean: 布尔类型* */ function validCommon (arr, ...fields) {let obj {}return arr.every((item, index) > {return fields…

使用 ML.NET CLI 自动进行模型训练

ML.NET CLI 可为 .NET 开发人员自动生成模型。 若要单独使用 ML.NET API(不使用 ML.NET AutoML CLI),需要选择训练程序(针对特定任务的机器学习算法的实现),以及要应用到数据的数据转换集(特征工程)。 每个数据集的最佳管道各不相同,从所有选择中选择最佳算法增加了复…