ffmpeg音视频开发从入门到精通——ffmpeg实现音频抽取

文章目录

    • FFmpeg 实现音频流抽取
      • 1. 包含FFmpeg头文件与命名空间声明
      • 2. 主函数与参数处理
      • 3. 打开输入文件
      • 4. 获取文件信息
      • 5. 查找音频流
      • 6. 分配输出文件上下文
      • 7. 猜测输出文件格式
      • 8. 创建新的音频流
      • 9. 打开输出文件
      • 10. 写入文件头信息
      • 11. 读取并写入音频数据
      • 12. 写入文件尾部信息并释放资源
    • 运行程序
    • 注意事项
    • 抽取音频完整代码

FFmpeg 实现音频流抽取

1. 包含FFmpeg头文件与命名空间声明

使用FFmpeg库前需要包含相应的头文件,并在C++中声明外部C函数的命名空间。

#ifdef __cplusplus
extern "C" {
#endif
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/log.h>
#ifdef __cplusplus
}
#endif

2. 主函数与参数处理

程序入口点,处理命令行参数。

int main(int argc, char *argv[]) {// 参数检查if (argc < 3) {av_log(nullptr, AV_LOG_INFO, "参数必须多于3个\n");exit(-1);}// 输入输出文件路径char *src = argv[1];char *dst = argv[2];// ...
}

3. 打开输入文件

使用avformat_open_input打开输入文件。

ret = avformat_open_input(&pFmtCtx, src, nullptr, nullptr);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "打开输入文件失败\n");exit(-1);
}

4. 获取文件信息

调用avformat_find_stream_info获取多媒体文件的流信息。

if ((ret = avformat_find_stream_info(pFmtCtx, nullptr)) < 0) {av_log(nullptr, AV_LOG_INFO, "获取文件信息失败\n");exit(-1);
}

5. 查找音频流

遍历所有流,找到音频流的索引。

for (int i = 0; i < pFmtCtx->nb_streams; ++i) {if (pFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {idx = i;break;}
}

6. 分配输出文件上下文

使用avformat_alloc_context分配输出文件的格式上下文。

oFmtCtx = avformat_alloc_context();
if (!oFmtCtx) {av_log(nullptr, AV_LOG_ERROR, "分配输出文件上下文失败\n");goto _ERROR;
}

7. 猜测输出文件格式

使用av_guess_format猜测输出文件的格式。

outFmt = av_guess_format(nullptr, dst, nullptr);
oFmtCtx->oformat = outFmt;

8. 创建新的音频流

为输出文件创建一个新的音频流,并复制输入音频流的参数。

outStream = avformat_new_stream(oFmtCtx, nullptr);
avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
outStream->codecpar->codec_tag = 0;

9. 打开输出文件

使用avio_open2打开输出文件准备写入。

ret = avio_open2(&oFmtCtx->pb, dst, AVIO_FLAG_WRITE, nullptr, nullptr);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "打开输出文件失败\n");goto _ERROR;
}

10. 写入文件头信息

调用avformat_write_header写入文件头信息。

ret = avformat_write_header(oFmtCtx, nullptr);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "写入文件头失败\n");goto _ERROR;
}

11. 读取并写入音频数据

读取输入文件的音频数据,转换时间戳,并写入输出文件。

while (av_read_frame(pFmtCtx, &pkt) >= 0) {if (pkt.stream_index == idx) {// 转换时间戳等pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF);pkt.dts = pkt.pts;// 写入输出文件av_interleaved_write_frame(oFmtCtx, &pkt);}av_packet_unref(&pkt);
}

12. 写入文件尾部信息并释放资源

写入文件尾部信息,关闭文件,并释放所有分配的资源。

av_write_trailer(oFmtCtx);
avio_close(oFmtCtx->pb);
avformat_free_context(oFmtCtx);_ERROR:// 清理资源if (pFmtCtx) {avformat_free_context(pFmtCtx);#  avformat_close_input(&pFmtCtx);}if (oFmtCtx) {avformat_free_context(oFmtCtx);# avformat_close_input(&oFmtCtx); // 注意:应使用 avformat_free_context 代替}
}

请注意,错误处理部分应使用avformat_free_context代替avformat_close_input来正确释放oFmtCtx资源。另外,程序中存在一些潜在的内存泄漏和错误处理问题,应进一步优化。

运行程序

程序需要传入至少两个参数:输入文件路径和输出文件路径。例如:

./my_ffmpeg_tool input.mp3 output.aac

注意事项

- 确保FFmpeg开发库已正确安装且可链接。
- 检查程序输出的错误信息以进行调试。
- 程序可能需要适当的读取和写入权限。

抽取音频完整代码

cmake_minimum_required(VERSION 3.27)
project(FFmpeg_exercise)
set(CMAKE_CXX_STANDARD 14)# 定义FFmpeg的安装路径变量
set(FFMPEG_INSTALL_DIR "/usr/local/ffmpeg")# 将FFmpeg的头文件目录添加到包含路径
include_directories(${FFMPEG_INSTALL_DIR}/include)# 定义FFmpeg库的基础名称(根据你的需要调整)
set(FFMPEG_LIBS "avcodec;avformat;avutil") # 用分号分隔库名# 寻找并链接FFmpeg库
foreach(FFMPEG_LIB ${FFMPEG_LIBS})find_library(${FFMPEG_LIB}_LIBRARY NAMES ${FFMPEG_LIB}PATHS ${FFMPEG_INSTALL_DIR}/lib NO_DEFAULT_PATH)list(APPEND FFMPEG_LIBRARIES ${${FFMPEG_LIB}_LIBRARY})
endforeach()add_executable(FFmpeg_exercise # main.cppextra_audic.cpp)
# 链接FFmpeg库
target_link_libraries(FFmpeg_exercise ${FFMPEG_LIBRARIES})
//
// Created by 陈伟峰 on 2024/6/22.
//
#ifdef __cplusplus
extern "C" {
#endif
// 包含FFmpeg的头文件
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/log.h>
#ifdef __cplusplus}
#endif
#include <iostream>int main(int argc,char *argv[]){int ret = -1;int idx = -1;//1.处理一些参数;char *src {nullptr};char *dst {nullptr};AVFormatContext *pFmtCtx {nullptr};AVFormatContext *oFmtCtx {nullptr};AVOutputFormat *outFmt {nullptr};AVStream *inStream {nullptr};AVStream *outStream {nullptr};AVPacket pkt {nullptr};//    设置日志级别av_log_set_level(AV_LOG_DEBUG);if(argc<3){av_log(nullptr,AV_LOG_INFO,"arguments must be more than 3\n");exit(-1);}src = argv[1];dst = argv[2];//2.打开输入多媒体文件ret = avformat_open_input(&pFmtCtx,src,nullptr,nullptr);if (ret<0){av_log(nullptr,AV_LOG_ERROR,"avformat_open_input failed\n");exit(-1);}//3.获取多媒体文件信息if ((ret= avformat_find_stream_info(pFmtCtx,nullptr))<0){av_log(nullptr,AV_LOG_INFO,"avformat_find_stream_info failed\n");exit(-1);}//4.遍历所有流,找到音频流for (int i = 0; i < pFmtCtx->nb_streams; ++i) {if (pFmtCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO){idx = i;av_log(nullptr,AV_LOG_INFO,"find_stream_info Successed!\n");break;}}if (idx<0){av_log(nullptr,AV_LOG_ERROR,"can not find audio stream\n");exit(-1);}// 打开目的文件上下文oFmtCtx = avformat_alloc_context();if(!oFmtCtx){av_log(nullptr,AV_LOG_ERROR,"avformat_alloc_context failed\n");goto _ERROR;}outFmt = av_guess_format(nullptr,dst,nullptr);oFmtCtx->oformat = outFmt;// 为目的文件,创建一个新的音频流outStream = avformat_new_stream(oFmtCtx,nullptr);// 设置输出音频参数inStream = pFmtCtx->streams[idx];avcodec_parameters_copy(outStream->codecpar,inStream->codecpar);outStream->codecpar->codec_tag = 0;// 绑定ret = avio_open2(&oFmtCtx->pb,dst,AVIO_FLAG_WRITE,nullptr,nullptr);if(ret<0){av_log(nullptr,AV_LOG_ERROR,"avio_open2 failed\n");goto _ERROR;}// 写多媒体文件到目的文件ret = avformat_write_header(oFmtCtx,nullptr);if(ret<0){av_log(nullptr,AV_LOG_ERROR, "error:%s",av_err2str(ret));goto _ERROR;}// 读取输入文件中的音频数据while (av_read_frame(pFmtCtx,&pkt)>=0) {if(pkt.stream_index==idx){// 写入输出文件pkt.pts = av_rescale_q_rnd(pkt.pts,inStream->time_base,outStream->time_base,(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));pkt.dts = pkt.pts;pkt.duration = av_rescale_q(pkt.duration,inStream->time_base,outStream->time_base);pkt.stream_index = 0;pkt.pos = -1;av_interleaved_write_frame(oFmtCtx,&pkt);}av_packet_unref(&pkt);}// 写入文件尾av_write_trailer(oFmtCtx);// 释放资源avio_close(oFmtCtx->pb);avformat_free_context(oFmtCtx);_ERROR:if(pFmtCtx){
//        avformat_close_input(&pFmtCtx);avformat_free_context(pFmtCtx);pFmtCtx = nullptr;}if(oFmtCtx){
//        avformat_close_input(&oFmtCtx);avformat_free_context(oFmtCtx);oFmtCtx = nullptr;}
};
  • 执行结果
 ./FFmpeg_exercise demo.mp4 test.aac

image-20240622111917818

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

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

相关文章

vue实现的商品列表网页

一、商品列表效果如下 二、代码&#xff1b; vue实现的商品列表网页 &#xff0c; 图片在vue项目的Public文件夹里的 imgs中 <template><div class"common-layout"><!-- el-container:外层容器。 当子元素中包含 <el-header> 或 <el-foo…

如何修复“AI的原罪”

如何修复“AI的原罪” 上个月&#xff0c;《纽约时报》声称&#xff0c;科技巨头OpenAI和谷歌不顾服务条款和版权法的禁止&#xff0c;将大量YouTube视频转录成文本&#xff0c;并将其用作人工智能模型的额外训练数据&#xff0c;从而进入了版权灰色地带。《纽约时报》还援引Me…

细说MCU输出两路PWM波形及改变占空比的实现方法

目录 一、硬件及工程 二、建立工程 三、代码修改 四、下载运行 五、改变PWM波形占空比 1、定义两个全局变量 2、启动定时器 3、重写TIM3中断回调函数 六、下载并运行 一、硬件及工程 文章依赖的硬件及工程配置参考本文作者的其他文章&#xff1a;细说ARM MCU的串口接…

VC++学习(5)——文本编程,插入符的初始化,图形插入符;文字始终在窗口;字符输入功能,回车换行,删除,左键定位;字体修改,字体平滑变色

目录 引出第五讲 文本编程新建项目输入线的初始化根据字体大小定义插入符大小创建图形插入符文字始终保存在窗口中CString类通过字符串资源 路径层字符输入的功能键盘输入消息鼠标左键消息保存点击位置的坐标 输入回车键的处理删除文字的实现 字符输入功能代码字体的修改模拟卡…

开发中遇到的一个bug

遇到的报错信息是这样的&#xff1a; java: Annotation processing is not supported for module cycles. Please ensure that all modules from cycle [hm-api,hm-common,hm-service] are excluded from annotation processing 翻译过来就是存在循环引用的情况&#xff0c;导…

FFmpeg源码:AV_RB32宏定义分析

一、AV_RB32宏定义的作用 AV_RB32是FFmpeg源码中经常出现的一个宏&#xff0c;其定义如下&#xff1a; #ifndef AV_RB32 # define AV_RB32(p) AV_RB(32, p) #endif 该宏定义有多层。把它简化为函数&#xff0c;其函数声明可以等价于&#xff1a; uint32_t AV_RB32(uint…

【机器学习 复习】 第1章 概述

一、概念 1.机器学习是一种通过先验信息来提升模型能力的方式。 即从数据中产生“模型”( model )的算法&#xff0c;然后对新的数据集进行预测。 2.数据集&#xff08;Dataset&#xff09;&#xff1a;所有数据的集合称为数据集。 训练集&#xff1a;用来训练出一个适合模…

【分布式系列】分布式锁timeout了怎么办?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

ffmpeg windows系统详细教程

视频做预览时黑屏&#xff0c;但有声音问题解决方案。 需要将 .mp4编成H.264格式的.mp4 一般上传视频的站点&#xff0c;如YouTube、Vimeo 等&#xff0c;通常会在用户上传视频时自动对视频进行转码&#xff0c;以确保视频能够在各种设备和网络条件下流畅播放。这些网站通常…

【尚庭公寓SpringBoot + Vue 项目实战】预约看房与租约管理(完结)

【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09;1、业务说明2、接口开发2.1、预约看房管理2.1.1.保存或更新看房预约2.1.2. 查询个人预约…

【Java】已解决java.io.InterruptedIOException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.io.InterruptedIOException异常 在Java中&#xff0c;java.io.InterruptedIOException异常通常与I/O操作被中断有关。这种中断可能由多种因素引起&#xff0c;如线程被中…

Palo Alto GlobalProtect App 6.3 (macOS, Linux, Windows, Andriod) - 端点网络安全客户端

Palo Alto GlobalProtect App 6.3 (macOS, Linux, Windows, Andriod) - 端点网络安全客户端 Palo Alto Networks 远程访问 VPN 客户端软件 请访问原文链接&#xff1a;https://sysin.org/blog/globalprotect-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。…

本地部署Ollama+qwen本地大语言模型Web交互界面

什么是 Ollama WebUI&#xff1f; Ollama WebUI 已经更名为 Open WebUI. Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 WebUI&#xff0c;旨在完全离线操作。它支持各种 LLM 运行程序&#xff0c;包括 Ollama 和 OpenAI 兼容的 API。 Ollama WebUI 是一个革命性的 L…

python数据分析-糖尿病数据集数据分析预测

一、研究背景和意义 糖尿病是美国最普遍的慢性病之一&#xff0c;每年影响数百万美国人&#xff0c;并对经济造成重大的经济负担。糖尿病是一种严重的慢性疾病&#xff0c;其中个体失去有效调节血液中葡萄糖水平的能力&#xff0c;并可能导致生活质量和预期寿命下降。。。。 …

matlab 路面点云标线提取

目录 一、算法原理二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 算法来自本人自创。实现效果如下图所示,具体实现原理看代码即可。 二、代码实现 clc; cle…

与Vatee万腾平台同行,共创智能未来

在科技日新月异的今天&#xff0c;智能化已成为推动社会进步的重要力量。Vatee万腾平台&#xff0c;作为这一浪潮中的佼佼者&#xff0c;正以其独特的创新力和前瞻的视野&#xff0c;引领我们迈向智能未来。与Vatee万腾平台同行&#xff0c;我们不仅能享受到科技带来的便捷与舒…

DPDK与传统收发报文的区别

1.去除中断 传统的收发报文方式都必须采用硬中断来做通讯&#xff0c;每次硬中断大约消耗100微秒&#xff0c;这还不算因为终止上下文所带来的Cache Miss。 DPDK采用轮询模式驱动(PMD)。 PMD由用户空间的特定的驱动程序提供的API组成&#xff0c;用于对设备和它们相应的…

Java也能做OCR!SpringBoot 整合 Tess4J 实现图片文字识别

文章目录 1. 环境准备1.1 安装 Tesseract OCR 引擎1.2 引入 Tess4J 依赖 2. 创建 Spring Boot 项目2.1 初始化项目2.2 目录结构 3. 编写 OCR 功能代码3.1 创建服务层3.2 创建控制器层 4. 配置 Tesseract 语言包5. 运行和测试5.1 启动 Spring Boot 应用5.2 使用 Postman 或 cURL…

(三十)Flask之wtforms库【剖析源码上篇】

每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者 &#x1f525;&#x1f525;本文已收录于Flask框架从入门到实战专栏&#xff1a;《Flask框架从入…

如何用 Google Chrome 浏览器浏览经过 XSLT 渲染的 XML 文件

对于经过XSLT渲染的XML文件&#xff0c;本来&#xff0c;可以直接用 IE (Internet Explorer) 打开&#xff0c;就能看到渲染之后的样子&#xff0c;很方便。但是后来&#xff0c;微软把 IE 换成了 Microsoft Edge&#xff0c;按理说这是比 IE 更先进的浏览器&#xff0c;可是偏…