当前位置: 首页 > news >正文

QProcess 调用 ffmpeg来处理音频

项目场景:

在文章 qt 实现音视频的分贝检测系统中,实现的是边播放变解析音频数据来统计音频的分贝大小,并不满足实际项目的需求,有的视频声音正常,有的视频声音就偏低,即使放到最大音量声音也是比较小,本文的目的是直接通过对本地视频进行检测,拿出关键指标,来进行对音频处理

关键依赖:ffmpeg

因为依赖于ffmpeg的能力,所以第一步要安装ffmpeg环境,自行百度

步骤1,检测max_volume 值是否小于0dB

 ffmpeg -i 1.mp3  -filter_complex volumedetect -c:v copy -f null /dev/null

在这里插入图片描述
其中检测的关键指标就是 max_volume, 本次检测和处理的目标就是把 max_volume的值给提高到0dB;

步骤2,如何区分是音频文件还是视频文件

可以有多种方法,1可以通过后缀名来区分; 2 因为代码是用qt写的,可以用qt来实现,代码如下

QFileInfo f(1.mp3”);
if(f.completeSuffix() == "mp3" || f.completeSuffix() == "aac" || 
f.completeSuffix() == "amr" || f.completeSuffix() == "wav" || f.completeSuffix() == "wma" )
QMediaPlayer p;
p.audioAvailable()

步骤3,处理音频,使max_volume的值接近0dB

音频文件用以下指令

ffmpeg -i 1.mp3-af  "volume=5.8dB"  out.mp3

如果是视频文件,用以下指令:(保持视频信息不变,当然还设计到音频的编码格式)

ffmpeg -i 1.mp3-af  "volume=5.8dB" -c:v copy -c:a aac out.mp3

输出如下
在这里插入图片描述
在这里插入图片描述

程序设计思路

通过QProcess 调用 ffmpeg指令,检测max_volume小于0的文件,拿到文件列表,再通过ffmpeg指令来提高音频。关键代码如下:

dbdetectthread.h

#ifndef DBDETECTTHREAD_H
#define DBDETECTTHREAD_H#include <QObject>
#include <QThread>
#include <QProcess>
#include <QStringList>class DbDetectThread : public QThread
{Q_OBJECT
public:explicit DbDetectThread(QObject *parent = nullptr);void setList(const QStringList &list);virtual void run();
signals:void sigPath(const QString &p, float db);void sigMsg(const QString &p);void sigEnd();public slots:void readStandardOutput();void readStandardError();void processFinished(int exitCode, QProcess::ExitStatus exitStatus);void threadFinished(); //线程退出private:QProcess *pCmdProcess;QStringList pathlist;QString curFile;
};#endif // DBDETECTTHREAD_H

dbdetectthread.cpp

#include "dbdetectthread.h"
#include <QDebug>
DbDetectThread::DbDetectThread(QObject *parent): QThread{parent}
{qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
}void DbDetectThread::setList(const QStringList &list)
{pathlist = list;
}//ffmpeg -i 2.wav -filter_complex volumedetect -c:v copy -f null /dev/null//需要计算分贝相差值
//ffmpeg  -i 2.wav -filter:a "volume=80dB" output2.wavvoid DbDetectThread::run()
{pCmdProcess = new QProcess();    //不要加thisconnect(pCmdProcess, &QProcess::readyReadStandardOutput, this, &DbDetectThread::readStandardOutput);connect(pCmdProcess, &QProcess::readyReadStandardError, this, &DbDetectThread::readStandardError);connect(pCmdProcess, QOverload<int , QProcess::ExitStatus >::of(&QProcess::finished), this, &DbDetectThread::processFinished);connect(this, &QThread::finished, this, &DbDetectThread::threadFinished);QStringList arguments;//arguments << "-i" << "C:/Users/wmm/Desktop/DbDetect/voice/input.mp4" << "-c:v" << "h264" << "-c:a" << "aac" << "C:/Users/wmm/Desktop/DbDetect/voice/output.mp4";//arguments << "-i" << "input.mp4" << "-c:v" << "h264" << "-c:a" << "aac" << "output.mp4";//arguments << "-i" << p << "-filter_complex"<< "volumedetect" <<  "-c:v" << "copy" << "-f" << "null" << "/dev/null";//QString cmd = QString("ffmpeg -i %1 -filter_complex volumedetect -c:v copy -f null /dev/null").arg(p);//QString cmd = QString("ffmpeg -i C:/Users/wmm/Desktop/DbDetect/voice/input.mp4 -filter_complex volumedetect -c:v copy -f null /dev/null");//QString cmd = "ping www.baidu.com -w 500";//QString result;foreach(auto p, pathlist){curFile = p;qDebug() << "start detect " << curFile;QString cmd = QString("ffmpeg -i %1 -filter_complex volumedetect -c:v copy -f null /dev/null").arg(p);pCmdProcess->start(cmd/*,arguments*/);pCmdProcess->waitForFinished();sleep(1);}}void DbDetectThread::readStandardOutput() {qDebug() << "Standard output: " << pCmdProcess->readAllStandardOutput();
}void DbDetectThread::readStandardError() {QString errorMessage = QString::fromUtf8(pCmdProcess->readAllStandardError());QStringList errlist = errorMessage.split("\r\n");//qDebug() << errlist.size();//qDebug() << errlist;//    float num = 3.1415926;
//    QString str = QString::number(num, 'f', 2);foreach (auto p, errlist) {if(p.contains("max_volume")){qDebug() << p;int pos = p.indexOf("max_volume");int pos2 = p.indexOf("dB",pos);QString val = p.mid(pos+11,pos2-11-pos);qDebug() <<val;float fval = val.toFloat();qDebug() << fval;if(fval <0){qDebug() << "小于0";emit sigPath(curFile,fval);}else{qDebug() << "不小于0";}}}// 对 errorMessage 进行解析和处理...//qDebug() << "Standard error: " << pCmdProcess->readAllStandardError();
}void DbDetectThread::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {qDebug() << "Process finished with exit code" << exitCode << "and exit status" << exitStatus << ((QProcess*)QObject::sender())->arguments();emit sigMsg(QString("%1 检测完成,exitCode = %2, exitStatus = %3 ").arg(curFile).arg(exitCode).arg(exitStatus));
}void DbDetectThread::threadFinished()
{qDebug() << __func__;emit sigEnd();pCmdProcess->deleteLater();
}

dbprocessthread.h

#ifndef DBPROCESSTHREAD_H
#define DBPROCESSTHREAD_H#include <QObject>
#include <QThread>
#include <QProcess>
#include <QMap>
#include <QMediaPlayer>
class DbProcessThread : public QThread
{Q_OBJECT
public:explicit DbProcessThread(QObject *parent = nullptr);void setOutputDir(const QString &dir);void setMap(const QMap<QString,float> &map);virtual void run();
signals:void sigPath(const QString &p, float db);void sigMsg(const QString &p);void sigEnd();public slots:void readStandardOutput();void readStandardError();void processFinished(int exitCode, QProcess::ExitStatus exitStatus);void threadFinished(); //线程退出private:QProcess *pCmdProcess;QMediaPlayer  mediaPlayer;QMap<QString,float> m_needProcessMap;QString m_outputDir;QString m_curSrcFile;QString m_curDesFile;
};#endif // DBPROCESSTHREAD_H

dbprocessthread.cpp

#include "dbprocessthread.h"
#include <QDebug>
#include <QFileInfo>
DbProcessThread::DbProcessThread(QObject *parent): QThread{parent}
{}void DbProcessThread::setOutputDir(const QString &dir)
{m_outputDir = dir;
}void DbProcessThread::setMap(const QMap<QString, float> &map)
{m_needProcessMap = map;
}void DbProcessThread::run()
{pCmdProcess = new QProcess();    //不要加thisconnect(pCmdProcess, &QProcess::readyReadStandardOutput, this, &DbProcessThread::readStandardOutput);connect(pCmdProcess, &QProcess::readyReadStandardError, this, &DbProcessThread::readStandardError);connect(pCmdProcess, QOverload<int , QProcess::ExitStatus >::of(&QProcess::finished), this, &DbProcessThread::processFinished);connect(this, &QThread::finished, this, &DbProcessThread::threadFinished);QMapIterator<QString, float> i(m_needProcessMap);while (i.hasNext()) {i.next();QFileInfo f(i.key());qDebug() << f.fileName() << m_outputDir+"/" + f.fileName();m_curSrcFile = i.key();m_curDesFile = m_outputDir+"/" + f.fileName();QStringList arguments;//arguments << "-i" << i.key() << "-c:v" << "h264" << "-c:a" << "aac" << m_outputDir+"/" + f.fileName();arguments << "-i" << i.key() << "-af" << QString("volume=%1dB").arg(qAbs(i.value())) << "-c:v copy" << " -c:a aac "  << m_outputDir+"/" + f.fileName();qDebug() << arguments;emit sigMsg(QString("正在处理...%1").arg(m_curSrcFile));if(f.completeSuffix() == "mp3" || f.completeSuffix() == "aac" || f.completeSuffix() == "amr" || f.completeSuffix() == "wav"\|| f.completeSuffix() == "wma" ){pCmdProcess->start(QString("ffmpeg -i %1 -af \"volume=%2dB\"  %3").arg(i.key()).arg(qAbs(i.value())).arg(m_outputDir+"/" + f.fileName())/*,arguments*/);}else {pCmdProcess->start(QString("ffmpeg -i %1 -af \"volume=%2dB\" -c:v copy  %3").arg(i.key()).arg(qAbs(i.value())).arg(m_outputDir+"/" + f.fileName())/*,arguments*/);}//pCmdProcess->start(QString("ffmpeg -i %1 -af \"volume=%2dB\" -c:v copy -c:a aac %3").arg(i.key()).arg(qAbs(i.value())).arg(m_outputDir+"/" + f.fileName())/*,arguments*/);pCmdProcess->waitForFinished();msleep(500);}}void DbProcessThread::readStandardOutput() {qDebug() << "Standard output: " << pCmdProcess->readAllStandardOutput();
}void DbProcessThread::readStandardError() {qDebug() << "Standard error: " << pCmdProcess->readAllStandardError();
}void DbProcessThread::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {qDebug() << "Process finished with exit code" << exitCode << "and exit status" << exitStatus << ((QProcess*)QObject::sender())->arguments();emit sigMsg(QString("%1 处理完成,文件保存为%2,exitCode = %3, exitStatus = %4 ").arg(m_curSrcFile).arg(m_curDesFile).arg(exitCode).arg(exitStatus));
}void DbProcessThread::threadFinished()
{qDebug() << __func__;emit sigEnd();pCmdProcess->deleteLater();
}

效果如图:
在这里插入图片描述
代码上传到此 https://download.csdn.net/download/u011942101/88299291

相关文章:

QProcess 调用 ffmpeg来处理音频

项目场景&#xff1a; 在文章 qt 实现音视频的分贝检测系统中&#xff0c;实现的是边播放变解析音频数据来统计音频的分贝大小&#xff0c;并不满足实际项目的需求&#xff0c;有的视频声音正常&#xff0c;有的视频声音就偏低&#xff0c;即使放到最大音量声音也是比较小&…...

“深入探究SpringMVC的工作原理与入门实践“

目录 引言1. 什么是SpringMVC?1.1. 模型1.2. 视图1.3. 控制器 2. SpringMVC的工作流程2.1. 客户端发送请求2.2. DispatcherServlet的处理2.3. 处理器映射器的使用2.4. 处理器的执行2.5. 视图解析器的使用2.6. 视图的渲染 3. SpringMVC的核心组件4. 弹簧MVC总结 引言 SpringMV…...

【Node.js】Node.js安装详细步骤和创建Express项目演示

Node.js是一个开源的、跨平台的JavaScript运行环境&#xff0c;用于在服务器端运行JavaScript代码。它提供了一个简单的API&#xff0c;可以用于开发各种网络和服务器应用程序。 以下是Node.js的安装和使用的详细步骤和代码示例&#xff1a; 1、下载Node.js 访问Node.js官方…...

栈和队列OJ

一、括号的匹配 题目介绍&#xff1a; 思路&#xff1a; 如果 c 是左括号&#xff0c;则入栈 push&#xff1b;否则通过哈希表判断括号对应关系&#xff0c;若 stack 栈顶出栈括号 stack.pop() 与当前遍历括号 c 不对应&#xff0c;则提前返回 false。栈 stack 为空&#xff1…...

Bootstrap的CSS类积累学习

要看哪个的介绍&#xff0c;搜索关键词就行了。 001-container 这是Bootstrap中定义的一个CSS类&#xff0c;它用于创建一个具有固定宽度的容器。比如&#xff0c;container类将<div>元素包装成一个固定宽度的容器。详情见&#xff1a;https://blog.csdn.net/wenhao_ir…...

Scala的集合操作之可变数组和不可变数组,可变List集合与不可变List集合,可变Set与不可变Set操作,可变和不可变Map集合和元组操作

Scala的集合操作之&#xff0c;可变数组和不可变数组&#xff0c;可变List集合与不可变List集合 不可变数组 /* traversable/ˈtrvəsəbl/adj.能越过的&#xff1b;可否认的*/ object Test01_ImmutableArray {def main(args: Array[String]): Unit {// 1. 创建数组val arr:…...

优化Docker权限管理:配置Docker用户组

Docker 利用 Linux 的用户和组权限来管理对 Docker 守护进程的访问权限。一般情况下&#xff0c;只有 root 用户和属于 docker 用户组的用户才被允许访问 Docker 守护进程。在 Linux 系统上使用 Docker 时&#xff0c;如果您尚未配置 docker 用户组&#xff0c;那么作为非 root…...

python+opencv读取rtsp流

前言 在使用yolov5做物体检测中&#xff0c;需要拉取视频流。分解任务第一步则是需要使用opencv读取rtsp流&#xff0c;只要拿到每一帧图片在进行推理显示即可。 代码 import cv2 def read_rtsp():cap cv2.VideoCapture(rtsp://admin:Vrc123456192.168.2.226:554)fourcc c…...

linux入门---动静态库的加载

目录标题 为什么会有动态库和静态库静态库的实现动态库的实现动静态库的加载 为什么会有动态库和静态库 我们来模拟一个场景&#xff0c;首先创建两个头文件 根据文件名便可以得知add.h头文件中存放的是加法函数的声明&#xff0c;sub.h头文件中存放的是减法函数的声明&#…...

计算机竞赛 基于深度学习的人脸专注度检测计算系统 - opencv python cnn

文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的人脸专注度…...

【Yolov5+Deepsort】训练自己的数据集(3)| 目标检测追踪 | 轨迹绘制 | 报错分析解决

&#x1f4e2;前言&#xff1a;本篇是关于如何使用YoloV5Deepsort训练自己的数据集&#xff0c;从而实现目标检测与目标追踪&#xff0c;并绘制出物体的运动轨迹。本章讲解的为第三部分内容&#xff1a;数据集的制作、Deepsort模型的训练以及动物运动轨迹的绘制。本文中用到的数…...

docker desktop如何一键进入容器内部

对着对应的容器 点击 view files...

多机单目标跟踪Cross-Drone Transformer Network for Robust Single Object Tracking

1. 摘要 无人机已被广泛用于各种应用&#xff0c;如空中摄影和军事安全&#xff0c;因为与固定摄像机相比&#xff0c;无人机具有高机动性和广阔的视野。多架无人机跟踪系统可以通过收集不同视角的互补视频片段来提供丰富的目标信息&#xff0c;特别是当目标在某些视角下被遮挡…...

手写Mybatis:第7章-SQL执行器的定义和实现

文章目录 一、目标&#xff1a;SQL执行的定义和实现二、设计&#xff1a;SQL执行的定义和实现三、实现&#xff1a;SQL执行的定义和实现3.1 工程结构3.2 SQL执行实现的关系图3.3 执行器的定义和实现3.3.1 Executor 接口3.3.2 BaseExecutor 抽象基类3.3.3 SimpleExecutor 简单执…...

C语言基础知识理论版(很详细)

文章目录 前述一、数据1.1 数据类型1.2 数据第一种数据&#xff1a;常量第二种数据&#xff1a;变量第三种数据&#xff1a;表达式1、算术运算符及算术表达式2、赋值运算符及赋值表达式3、自增、自减运算符4、逗号运算符及其表达式&#xff08;‘顺序求值’表达式&#xff09;5…...

CG MAGIC分享3d Max中的Corona渲染器材质如何成转换VRay材质?

大家无论是使用Corona渲染器还是Vray渲染器时&#xff0c;进行材质问题时&#xff0c;都会遇到转化材质问题。 如何将CR转换成VR或者将VR转换CR材质呢&#xff1f; 对于这两者之间转换最好最好的方法只能是材质转换器。 CG MAGIC小编&#xff0c;梳理了两种方法&#xff0c;大…...

电脑入门:路由器常见问题排错步骤

HiPER系列路由器使用中Ping LAN口不通的诊断步骤 准备工作: 在可以ping通的时候记录下路由器LAN口的MAC地址: 命令hiper% show interface ethernet/1 mac Mac : 0022aa419d1e 以下步骤在ping不通路由器的时候依次操作,并记下结果: 步骤一:观察设备各端口…...

mac电脑识别不出来u盘?mac识别不了u盘怎么办

有些用户反馈说本来想要拷贝文件&#xff0c;但是将U盘插入mac系统后竟然不能识别&#xff0c;这时候我们需要用到NTFS For Mac软件。 其实mac系统只提供了它自身磁盘格式(mac os 扩展)等的读写权限&#xff0c;只提供了读的权限给NTFS、FAT32给硬盘和U盘&#xff0c;我们99%使…...

【系统编程】线程池以及API接口简介

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…...

Verilog零基础入门(边看边练与测试仿真)-笔记

文章目录 第一讲第二讲第三讲第四讲 第一讲 1、testbench 没有端口&#xff0c;所以没括号 2、testbench 输入端 之后要变动 所以定义为reg 3、#10 &#xff1a;过10个时间单位 &#xff1b;’timescale 1ns/10ps 即 1ns 的时间单位 10ps的时间精度 4、reg 型变量赋值的时候 用…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

职坐标物联网全栈开发全流程解析

物联网全栈开发涵盖从物理设备到上层应用的完整技术链路&#xff0c;其核心流程可归纳为四大模块&#xff1a;感知层数据采集、网络层协议交互、平台层资源管理及应用层功能实现。每个模块的技术选型与实现方式直接影响系统性能与扩展性&#xff0c;例如传感器选型需平衡精度与…...

JS设计模式(5): 发布订阅模式

解锁JavaScript发布订阅模式&#xff1a;让代码沟通更优雅 在JavaScript的世界里&#xff0c;我们常常会遇到这样的场景&#xff1a;多个模块之间需要相互通信&#xff0c;但是又不想让它们产生过于紧密的耦合。这时候&#xff0c;发布订阅模式就像一位优雅的信使&#xff0c;…...

Android多媒体——音/视频数据播放(十八)

在媒体数据完成解码并准备好之后,播放流程便进入了最终的呈现阶段。为了确保音视频内容能够顺利输出,系统需要首先对相应的播放设备进行初始化。只有在设备初始化成功后,才能真正开始音视频的同步渲染与播放。这一过程不仅影响播放的启动速度,也直接关系到播放的稳定性和用…...