FFMPEG提取音频流数据

news2024/11/14 2:24:46

  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 --相关流,一般填-1
		decoder_ret --流解码器,不清楚则填NULL
		flags --暂未定义,填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 --格式短参名,不清楚则填NULL
		filename --输出格式的目标名字
		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 转换 为输出流基准时间时间戳cq
				av_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+=-lavutil

CFLAGS=`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 --上下文关联指针,不用可直接填NULL
     level --输出类型: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 --流下标,一般填0
     url  --媒体文件名
     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 --相关流,一般填-1
		decoder_ret --流解码器,不清楚则填NULL
		flags --暂未定义,填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://www.coloradmin.cn/o/1932564.html

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

相关文章

全局 loading

好久不见&#xff01; 做项目中一直想用一个统一的 loading 状态控制全部的接口加载&#xff0c;但是一直不知道怎么处理&#xff0c;最近脑子突然灵光了一下想到了一个办法。 首先设置一个全局的 loading 状态&#xff0c;优先想到的就是 Pinia 然后因为页面会有很多接口会…

减分猫-12123货车驾驶证(学法减分)专用题目及答案 #知识分享#媒体

想要顺利通过驾驶考试&#xff0c;掌握一些常考题目和答案是非常有必要的。今天&#xff0c;我就为大家带来了这样一份资料——20道驾驶考试题目和答案解析&#xff0c;让你考试更有底气&#xff01;这些题目和答案不仅包括了考试中的重点和难点内容&#xff0c;还有针对每道题…

leetcode力扣_二分查找

69.x的平方根 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。注意&#xff1a;不允许使用任何内置指数函数和算符&#xff0c;例如 pow(x, 0.5) 或者 x ** 0.5 。 示例 1&…

神经网络构造

目录 一、神经网络骨架&#xff1a;二、卷积操作&#xff1a;三、卷积层&#xff1a;四、池化层&#xff1a;五、激活函数&#xff08;以ReLU为例&#xff09;&#xff1a; 一、神经网络骨架&#xff1a; import torch from torch import nn#神经网络 class CLH(nn.Module):de…

微信小程序 vant-weapp的 SwipeCell 滑动单元格 van-swipe-cell 滑动单元格不显示 和 样式问题 滑动后删除样式不显示

在微信小程序开发过程中 遇到个坑 此处引用 swipeCell 组件 刚开始是组件不显示 然后又遇到样式不生效 首先排除问题 是否在.json文件中引入了组件 {"usingComponents": {"van-swipe-cell": "vant/weapp/swipe-cell/index","van-cell-gro…

视频共享融合赋能平台LntonCVS视频监控业务平台技术方案详细介绍

LntonCVS国标视频综合管理平台是一款智慧物联应用平台&#xff0c;核心技术基于视频流媒体&#xff0c;采用分布式和负载均衡技术开发&#xff0c;提供广泛兼容、安全可靠、开放共享的视频综合服务。该平台功能丰富&#xff0c;包括视频直播、录像、回放、检索、云存储、告警上…

【C++开源】GuiLite:超轻量UI框架-入门

开发环境说明 使用visual Studio 2022进行开发 下载源码 从如下的网址进行源码和示例代码的下载: GitHub源码网址为:idea4good/GuiLite示例代码路径为:idea4good/GuiLiteExample使用方法 GuiLite是一个仅有头文件的一个库,使用的时候直接include到自己的UIcode.cpp文件…

Golang面试题整理(持续更新...)

文章目录 Golang面试题总结一、基础知识1、defer相关2、rune 类型3、context包4、Go 竞态、内存逃逸分析5、Goroutine 和线程的区别6、Go 里面并发安全的数据类型7、Go 中常用的并发模型8、Go 中安全读写共享变量方式9、Go 面向对象是如何实现的10、make 和 new 的区别11、Go 关…

Elasticsearch 企业级实战 01:Painless 脚本如何调试?

在企业级应用中&#xff0c;Elasticsearch 常常被用来处理复杂的数据查询和操作。 Painless 是 Elasticsearch 的内置脚本语言&#xff0c;虽然强大&#xff0c;但调试起来并不容易。 本文将详细介绍如何在实战中有效调试 Painless 脚本&#xff0c;以提高开发和运维效率。 本文…

打印室预约小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;附近打印店管理&#xff0c;文件打印管理&#xff0c;当前预约管理&#xff0c;预约历史管理&#xff0c;打印记录管理 开发系统&#xff1a;Windows 架构模式&#xff1a;SSM JD…

微分段Microsegmentation简介

目录 微分段Microsegmentation简介什么是微分段&#xff1f;微分段的防范措施微分段的防护层级 基于网络的微分段微分段基本工作机制微分段的角色VxLAN的额外字段 业务链分组与传输策略场景1&#xff1a;三层报文本地转发场景场景2&#xff1a;三层报文跨设备转发场景 微分段的…

微信小程序与本地MySQL数据库通信

微信小程序与本地MySQL数据库通信 因为本地MySQL服务器没有域名&#xff0c;也没有进行相应的请求操作封装&#xff0c;因此微信小程序没办法和数据库通信。 但是对于开发人员来说&#xff0c;没有数据库&#xff0c;那还能干撒&#xff1f;虽然我尝试过用json-server&#x…

Android音视频—OpenGL 与OpenGL ES简述,渲染视频到界面基本流程

文章目录 OpenGL 简述特点和功能主要组件OpenGL ES当前状态 OpenGL ES 在 Android 上进行视频帧渲染总体流程 OpenGL 简述 OpenGL&#xff08;Open Graphics Library&#xff09;是一个跨平台的、语言无关的应用程序编程接口&#xff08;API&#xff09;&#xff0c;用于开发生…

关于 Redis 中分布式锁

什么是分布式锁 在一个分布式系统中&#xff0c;也会涉及到多个节点访问同一个公共资源的情况。此时就需要通过锁来做互斥控制&#xff0c;避免出现类似于“线程安全”的问题。 而 Java 中的 synchronized 或者 C 中的 std::mutex&#xff0c;这样的锁都只能在当前进程中生效…

allure_pytest:AttributeError: ‘str‘ object has no attribute ‘iter_parents‘

踩坑记录 问题描述&#xff1a; 接口自动化测试时出现报错&#xff0c;报错文件是allure_pytest库 问题分析&#xff1a; 自动化测试框架是比较成熟的代码&#xff0c;报错也不是自己写的文件&#xff0c;而是第三方库&#xff0c;首先推测是allure_pytest和某些库有版本不兼…

Hadoop3:RPC通信原理及简单案例实现

一、场景介绍 我们知道&#xff0c;Hadoop中存在多种服务&#xff0c;那么&#xff0c;服务之间是如何通信的了&#xff1f; 比如&#xff0c;DN和NN之间如何通信&#xff1f; 这里&#xff0c;实际上是通过RPC实现进程间通信的了。 RPC属于Java网络编程范畴 需要编写客户端和…

Apache POI 使用Java处理Excel数据 进阶

1.POI入门教程链接 http://t.csdnimg.cn/Axn4Phttp://t.csdnimg.cn/Axn4P建议&#xff1a;从入门看起会更好理解POI对Excel数据的使用和处理 记得引入依赖&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactI…

Java中锁的全面详解(深刻理解各种锁)

一.Monitor 1. Java对象头 以32位虚拟机位例 对于普通对象,其对象头的存储结构为 总长为64位,也就是8个字节, 存在两个部分 Kclass Word: 其实也就是表示我们这个对象属于什么类型,也就是哪个类的对象.而对于Mark Word.查看一下它的结构存储 64位虚拟机中 而对于数组对象,我…

阿里云开源 Qwen2-Audio 音频聊天和预训练大型音频语言模型

Qwen2-Audio由阿里巴巴集团Qwen团队开发&#xff0c;它能够接受各种音频信号输入&#xff0c;对语音指令进行音频分析或直接文本回复。与以往复杂的层次标签不同&#xff0c;Qwen2-Audio通过使用自然语言提示简化了预训练过程&#xff0c;并扩大了数据量。 喜好儿网 Qwen2-Au…

六边形动态特效404单页HTML源码

源码介绍 动态悬浮的六边形,旁边404文字以及跳转按钮,整体看着像科技二次元画风,页面简约美观,可以做网站错误页或者丢失页面,将下面的代码放到空白的HTML里面,然后上传到服务器里面,设置好重定向即可 效果预览 完整源码 <!DOCTYPE html> <html><head…