FFMPEG提取音频流数据

  FFmpeg是一套开源的计算机程序,主要用于记录、转换数字音频、视频,并能将其转化为流。它提供了录制、转换以及流化音视频的完整解决方案,被誉为多媒体业界的“瑞士军刀”。

1.使用ffmpeg命令实现音频流数据提取

[wbyq@wbyq ffmpeg]$ ffmpeg -i 1.mp4 -acodec copy -vn test.aac
  • acodec: 指定音频编码器,copy 指明只拷贝,不做编解码。
  • vn: v 代表视频,n 代表 no 也就是无视频的意思。

2.调用ffmpeg库使用音频流数据提取

  从一个视频中抽取音频流数据操作步骤:
  (1)打开音视频原文件avformat_open_input()
  (2)读取音视频流数据包,获取流信息avformat_find_stream_info()
    该函数不会影响正常文件信息,一些媒体文件在没有标头信息必须要调用该函数;
    若要输出当前媒体流信息,可调到av_dump_format() ;输出流信息,若不需要查看,则可不调用该函数;
    从媒体文件中查找要解析的流数据av_find_best_stream() ;调用成功返回解析的流下标;
  (3)创建一个输出媒体上下文件指针avformat_alloc_context()
  (4)根据媒体文件类型注册格式av_guess_format()
  (5)创建一个流数据avformat_new_stream()
  (6)将源媒体文件流数据拷贝到目的媒体文件中avcodec_parameters_copy()
  (7)打开目的媒体文件avio_open(),将多媒体头数据写入到目标文件avformat_write_header()
  (8)循环从源媒体文件中读取流数据包av_read_frame() ;判断读取的流数据是否和查找解析的流数据一致,若一致的话将数据包写入大目标媒体文件中av_interleaved_write_frame() ,该函数可以按dts顺序写入,写入完后释放pack包av_packet_unref() ;在写入数据包之前,需要设置dts、pts、duration、stream_index、pos 参数;
  (9)写入多媒体尾数据av_write_trailer
  (10)释放资源,自此,流数据抽取成功;
    avformat_free_context()
    avforamt_close_input()

  整体流程图如下所示:
在这里插入图片描述

3.整体代码实现

#include <stdio.h>
#include <libavutil/log.h>//日志文件处理
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
int main(int argc,char **argv)
{/*函数功能:抽取音频流数据*///1.设置日志信息等级av_log_set_level(AV_LOG_INFO);//请求输入参数:./app <源文件> <目标文件>if(argc!=3){av_log(NULL,AV_LOG_ERROR,"运行格式:./app <源文件> <目标文件>\n");return 0;}const char *src=argv[1];const char *dest=argv[2];//2.打开文件AVFormatContext *pfmt_ctx=NULL;//上下文指针int ret;ret=avformat_open_input(&pfmt_ctx,src,NULL, NULL);if(ret!=0){av_log(NULL,AV_LOG_ERROR,"打开媒体文件失败,err=%d,%s\n",ret,av_err2str(ret));return 0;}//读取流数据包,获取流信息avformat_find_stream_info(pfmt_ctx, NULL);//输出流信息av_dump_format(pfmt_ctx,0,src,0);/*3.查找音频流数据ic --上下文指针type --媒体文件类型        AVMEDIA_TYPE_VIDEO(视频) AVMEDIA_TYPE_AUDIO(音频)wanted_stream_nb --流编号,-1表示自动选择related_stream --相关流,一般填-1decoder_ret --流解码器,不清楚则填NULLflags --暂未定义,填0即可返回值:成功返回一个非负整数,表示对应流编号失败返回负数*/int index=-1;index=av_find_best_stream(pfmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1,NULL,0);if(index<0){av_log(pfmt_ctx,AV_LOG_ERROR,"查找音频流数据失败err=%d,%s\n",index,av_err2str(index));goto _fil;}av_log(pfmt_ctx,AV_LOG_INFO,"index=%d\n",index);/*4.创建输出流上下文指针*/AVFormatContext *ofmatctx=avformat_alloc_context();if(ofmatctx==NULL){av_log(NULL,AV_LOG_ERROR,"创建输出流上下文件指针失败\n");goto _fil;}/*5.根据类型注册输出格式short_name --格式短参名,不清楚则填NULLfilename --输出格式的目标名字mime_type --MIME类型,不清楚则填NULL该函数可以根据short_name、filename、mime_type的任意一个实现格式注册,成功返回AVOutputFormat失败返回NULL*/AVOutputFormat *ofmt=av_guess_format(NULL,dest,NULL);if(ofmt==NULL){av_log(NULL,AV_LOG_ERROR,"注册输出格式失败\n");goto _fil2;}//6.将输出流信息写入到输出流上下文指针ofmatctx->oformat=ofmt;//7.创建一个新的流数据AVStream *ostream=avformat_new_stream(ofmatctx, NULL);if(ostream==NULL){av_log(ofmatctx,AV_LOG_ERROR,"创建数据流失败\n");goto _fil2;}//8.将输入媒体文件中的音频流数据拷贝到输出媒体文件中AVStream *istream=pfmt_ctx->streams[index];//输入流数据avcodec_parameters_copy(ostream->codecpar, istream->codecpar);ostream->codecpar->codec_tag=0;//填0,表示编解码器有系统选择//将输出媒体文件打开,便于后续写数据ret=avio_open(&ofmatctx->pb, dest, AVIO_FLAG_WRITE);if(ret<0){av_log(ofmatctx,AV_LOG_ERROR,"输出媒体文件打开失败err=%s\n",av_err2str(ret));goto _fil2;}//9.写多媒体文件头到目标文件ret=avformat_write_header(ofmatctx,NULL);if(ret<0){av_log(ofmatctx,AV_LOG_ERROR,"写入多媒体头数据失败,ret=%s\n",av_err2str(ret));}//循环写入音频流数据AVPacket pkt;while(av_read_frame(pfmt_ctx, &pkt)==0)//从源文件中读取流数据{if(pkt.stream_index==index)//判断读取的流数据是否为需要的音频流{/*PTS:(Presentation Time Stamp)显示时间戳         PTS主要用于度量解码后的视频帧什么时候被显示出来。DTS:(Decode Time Stamp)解码时间戳 DTS主要是标识读入内存中的数据流在什么时候开始送入解码器中进行解码。音频流数据,没有视频,所以PTS和DTS一致av_rescale_q_rnd 函数:实现时间戳pts从输入流基准时间时间戳bq 转换 为输出流基准时间时间戳cqav_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq,enum AVRounding rnd)计算方式:a*bq/cq rnd  --表示计算处理方式,AV_ROUND_PASS_MINMAX表示限制最大最小值;AV_ROUND_NEAR_INF表示四舍五入处理方式*/pkt.pts=av_rescale_q_rnd(pkt.pts,istream->time_base,ostream->time_base, AV_ROUND_PASS_MINMAX|AV_ROUND_NEAR_INF);pkt.dts=pkt.pts;//计算音频时长pkt.duration=av_rescale_q(pkt.duration,istream->time_base,ostream->time_base);pkt.stream_index=0;//流下标pkt.pos=-1;//相对位置//根据dts递增顺序正确交织写入数据到到媒体文件av_interleaved_write_frame(ofmatctx,&pkt);av_packet_unref(&pkt);//释放pkt包}}//写入多媒体文件尾数据av_write_trailer(ofmatctx);_fil2:if(!ofmatctx){avformat_free_context(ofmatctx);//释放流指针}
_fil:if(!pfmt_ctx){avformat_close_input(&pfmt_ctx);//关闭媒体文件}}

4.程序编译Makefile

obj=getaudio.o 
CC=gcc#CFLAGS=-I/home/wbyq/src_pack/ffmpeg-5.1.4/_install/include 
#CFLAGS+=-L/home/wbyq/src_pack/ffmpeg-5.1.4/_install/lib 
#CFLAGS+=-lavutilCFLAGS=`pkg-config --libs libavformat libavutil libavcodec --cflags`app:$(obj)$(CC) $^ -o $@ $(CFLAGS)

5.相关函数介绍

5.1日志信息输出

  ffmpeg中提供了日志打印函av_log,在输出调试信息时,可以先通过设置日志等级来决定输出的调试信息。

/*
leve可填写的参数:AV_LOG_DEBUG、AV_LOG_INFO、AV_LOG_WARNING、AV_LOG_ERROR等
*/
void av_log_set_level(int level);
/*
打印日志信息
形参:avcl --上下文关联指针,不用可直接填NULLlevel --输出类型:AV_LOG_DEBUG、AV_LOG_INFO、AV_LOG_WARNING、AV_LOG_ERROR等后需参数和printf一致
*/
void av_log(void* avcl, int level, const char *fmt, ...);

5.2 打开媒体文件

/*
形参:ps --打开成功返回一个AVFormatContext 上下文指针filename  --要打开的文件名fmt  --格式,填NULL可有系统根据文件名自行判断options  --可选参数,一般填NULL
返回值:成功返回0,失败返回<0
*/
int avformat_open_input(AVFormatContext **ps, const char *filename,const AVInputFormat *fmt, AVDictionary **options)

5.3 获取流信息

/*
形参:ic --上下文指针options  --可选参数,一般填NULL
返回值:成功>=0,失败返回<0
*/
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)

5.4 输出流信息

/*
形参:ic --上下文指针index --流下标,一般填0url  --媒体文件名is_output --0表示输入媒体文件,1表示输出媒体文件
*/
void av_dump_format(AVFormatContext *ic, int index,const char *url, int is_output)

5.6 查找音视频流数据

/*
形参:ic --上下文指针type --媒体文件类型        AVMEDIA_TYPE_VIDEO(视频) AVMEDIA_TYPE_AUDIO(音频)wanted_stream_nb --流编号,-1表示自动选择related_stream --相关流,一般填-1decoder_ret --流解码器,不清楚则填NULLflags --暂未定义,填0即可
返回值:成功返回一个非负整数,表示对应流编号失败返回负数
*/
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,int wanted_stream_nb, int related_stream,const AVCodec **decoder_ret, int flags)

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

JavaEE初阶 - 文件操作和IO(一)

认识文件树形结构组织 和 目录 &#xff08;N叉树&#xff09;文件路径&#xff08;Path&#xff09;其他知识Java中操作文件File概述属性构造方法方法代码实例&#xff08;一&#xff09;代码实例&#xff08;二&#xff09;代码实例&#xff08;三&#xff09;代码实例&#…

Redis三种常用的缓存读写策略

Cache Aside Pattern&#xff08;旁路缓存模式&#xff09; 现在基本都用这个模式 Cache Aside Pattern 中服务端需要同时维系 db 和 cache&#xff0c;并且是以 db 的结果为准。 读写步骤&#xff1a; 写&#xff1a; 先更新 db&#xff0c;然后直接删除 cache 。 读 : …

电脑系统重装数据被格式化,那些文件还有办法恢复吗?

在日常使用电脑的过程中&#xff0c;系统重装或格式化操作是常见的维护手段&#xff0c;尤其是在遇到系统崩溃、病毒感染或需要升级系统时。然而&#xff0c;这一操作往往伴随着数据丢失的风险&#xff0c;尤其是当C盘&#xff08;系统盘&#xff09;和D盘&#xff08;或其他数…

LabVIEW鼠标悬停在波形图上的曲线来自动显示相应点的坐标

步骤 创建事件结构&#xff1a; 打开LabVIEW&#xff0c;创建一个新的VI。 在前面板上添加一个Waveform Graph控件。 在后面板上添加一个While Loop和一个事件结构&#xff08;Event Structure&#xff09;。 配置事件结构&#xff0c;选择Waveform Graph作为事件源&#xf…

【作业】 贪心算法1

Tips:三题尚未完成。 #include <iostream> #include <algorithm> using namespace std; int a[110]; int main(){int n,r,sum0;cin>>n>>r;for(int i0;i<n;i){cin>>a[i];}sort(a0,an);for(int i0;i<n;i){if(i>r){a[i]a[i-r]a[i];}suma[…

ActiveMQ配置延迟投递和定时投递教程

配置activemq.xml中的<broker>标签添加schedulerSupport"true" schedulerSupport"true"更改完成重启生效 四大属性解释 Property nametypedescriptionAMQ_SCHEDULED_DELAYlong延迟投递的时间AMQ_SCHEDULED_PERIODlong重复投递的时间间隔AMQ_SCHEDU…

动手学深度学习——5.卷积神经网络

1.卷积神经网络特征 现在&#xff0c;我们将上述想法总结一下&#xff0c;从而帮助我们设计适合于计算机视觉的神经网络架构。 平移不变性&#xff08;translation invariance&#xff09;&#xff1a;不管检测对象出现在图像中的哪个位置&#xff0c;神经网络的前面几层应该对…

阿里云国际站:海外视频安全的DRM加密

随着科技的进步&#xff0c;视频以直播或录播的形式陆续开展海外市场&#xff0c;从而也衍生出内容安全的问题&#xff0c;阿里云在这方面提供了完善的内容安全保护机制&#xff0c;适用于不同的场景&#xff0c;如在视频安全提供DRM加密。 由图可以了解到阿里云保护直播安全的…

吴恩达大模型系列课程《Prompt Compression and Query Optimization》中文学习打开方式

Prompt Compression and Query Optimization GPT-4o详细中文注释的Colab观看视频1 浏览器下载插件2 打开官方视频 GPT-4o详细中文注释的Colab 中文注释链接&#xff1a;https://github.com/Czi24/Awesome-MLLM-LLM-Colab/tree/master/Courses/Prompt-Compression-and-Query-Op…

鼠标录制工具怎么挑选?9款电脑鼠标录制工具分享(2024)

你知道鼠标录制工具吗&#xff1f;鼠标录制工具通过记录和回放用户的操作&#xff0c;帮助自动化重复性任务&#xff0c;提高工作效率和精确性。它可以帮助用户简化很多繁琐的操作步骤&#xff0c;非常适合运用在电脑自动化任务、游戏自动化中&#xff0c;给大家整理了2024年9款…

【学习笔记】einsum(爱因斯坦求和)

文章目录 einsum&#xff08;爱因斯坦求和&#xff09;基本语法对角线操作矩阵乘法向量点积张量积 总结 einsum&#xff08;爱因斯坦求和&#xff09; einsum 是 Python 中 NumPy 库的一个函数&#xff0c;它提供了一种非常灵活的方式来进行多维数组的对角线操作、矩阵乘法、向…

【芯片设计- RTL 数字逻辑设计入门 番外篇 12 -- SoC 设计中的 ECO】

请阅读【ARM AMBA AXI 总线 文章专栏导读】 请阅读【芯片设计 RTL 数字逻辑设计扫盲 】 转自&#xff1a;简单了解SoC设计中的ECO — 快乐的芯片工程师 文章目录 ECO 概述Pre-Mask ECO&#xff08;预掩模ECO&#xff09;芯片设计前端与后端的区别 Post-Mask ECO&#xff08;后…

Linux+InternStudio 关卡(test)

任务地址&#xff1a; https://github.com/InternLM/Tutorial/blob/camp3/docs/L0/Linux/task.md 文档 https://github.com/InternLM/Tutorial/blob/camp3/docs/L0/Linux/readme.md 任务 ssh连接 端口映射 gradio页面 笔记&#xff1a; 1.端口映射阶段&#xff1a;输入密…

[经验] 陏唐英雄之薜刚反唐 #知识分享#其他#媒体

陏唐英雄之薜刚反唐 1、陏 陏是一种古代汉字&#xff0c;它的拼音为du&#xff0c;意思是田地里的小路。这个字的形状非常特殊&#xff0c;由一个“阝”字部和一个“多”字部组成。在古代&#xff0c;人们用来描述田地中间的窄路或是用来分隔不同农田之间的小路。陏这个字在日…

[python]pycharm设置清华源

国内镜像源有以下几个&#xff0c;因为都是国内的&#xff0c;基本速度差不了太多。 清华&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里云&#xff1a;http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣&…

uni-app:文字竖直排列,并且在父级view中水平竖直对齐

一、效果 二、代码 <template><view class"parent"><text class"child">这是竖直排列的文字</text></view> </template> <script>export default {data() {return {}},methods: {},}; </script> <sty…

Apache Flink 入门

零、概述 Apache Flink 是一个高性能的开源分布式流处理框架&#xff0c;专注于实时数据流的处理。 它设计用于处理无界和有界数据流&#xff0c;在内存级速度下提供高效的有状态计算。 Flink 凭借其独特的Checkpoint机制和Exactly-Once语义&#xff0c;确保数据处理的准确性…

首个WebAgent在线评测框架和流程数据管理平台来了,GPT-4、Qwen登顶闭源和开源榜首!

在当今科技迅速发展的时代&#xff0c;大型语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;正以前所未有的速度改变着我们与数字世界的互动方式。基于LLM的智能代理&#xff08;LLM Agent&#xff09;&#xff0c;从简单的信息搜索到复杂的网页操作&…

couldn‘t read native报错!Typora中使用Pandoc导出Word失败的解决方法

couldn‘t read native报错&#xff01;Typora中使用Pandoc导出Word失败的解决方法 一、问题描述 在Typora中使用Pandoc将markdown文件导出为word文件时&#xff0c;发生如下图所示错误: 在网上找了资料以后&#xff0c;发现是因为md文件里面有表格&#xff0c;如果把表格删掉…

【Harmony】SCU暑期实训鸿蒙开发学习日记Day2

目录 Git 参考文章 常用操作 ArkTS的网络编程 Http编程 发送请求 GET POST 处理响应 JSON数据解析 处理响应头 错误处理 Web组件 用生命周期钩子实现登录验证功能 思路 代码示例 解读 纯记录学习日记&#xff0c;杂乱&#xff0c;误点的师傅可以掉了&#x1…