Qt AudioSource录制无数据:buffer.size()与processedUSecs()均为0
问题排查与解决方法
核心问题:缺少Qt事件循环
QAudioSource 依赖 Qt 的事件循环处理音频数据的采集和写入操作,控制台应用默认不会启动事件循环,导致音频数据无法写入 QBuffer,因此 buffer.size() 和 processedUSecs() 都为0。
具体修复步骤
- 启动Qt事件循环:在控制台应用中手动创建
QCoreApplication对象并调用exec(),确保事件循环正常运行,这是音频数据能被写入的前提。 - 修复格式检查逻辑:如果指定格式不被设备支持,直接回退到设备的首选格式,避免使用无效格式导致录制失败。
- 替换阻塞式sleep:用Qt的
QTimer实现定时读取,避免阻塞事件循环影响音频采集。 - 优化Buffer使用:不要频繁启停录制,定时读取数据后重置Buffer,保持录制的连续性。
修复后的示例代码
#include <QCoreApplication> #include <QAudioSource> #include <QAudioDevice> #include <QMediaDevices> #include <QBuffer> #include <QTimer> #include <iostream> #include <cassert> bool hasInitialisedAudio = false; QAudioSource* source = nullptr; QBuffer* buffer = nullptr; double calculateRMS(const char* data, qint64 size) { // 实现你的RMS计算逻辑 return 0.0; } void readAudioData() { if (!source || !buffer) return; source->stop(); buffer->seek(0); std::cout << "Recorded a buffer of size " << buffer->size() << " during " << source->processedUSecs() / 1000000.0 << " seconds." << std::endl; double RMS = calculateRMS(buffer->data().constData(), buffer->size()); // 重置Buffer并重启录制 buffer->buffer().clear(); buffer->seek(0); source->start(buffer); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); buffer = new QBuffer(); buffer->open(QBuffer::ReadWrite); QAudioFormat format; format.setSampleRate(8000); format.setChannelCount(1); format.setSampleFormat(QAudioFormat::UInt8); QAudioDevice info = QMediaDevices::defaultAudioInput(); if (!info.isFormatSupported(format)) { std::cout << "Default format not supported, using preferred format" << std::endl; format = info.preferredFormat(); } source = new QAudioSource(format); assert(source->state() == QAudio::StoppedState); source->setVolume(1); source->start(buffer); if (source->error() != QAudio::NoError || source->state() != QAudio::ActiveState) { std::cout << "An error has occurred while recording audio" << std::endl; return 1; } hasInitialisedAudio = true; // 每10秒触发一次数据读取 QTimer* timer = new QTimer(); QObject::connect(timer, &QTimer::timeout, readAudioData); timer->start(10000); return a.exec(); // 启动事件循环 }
额外注意事项
- 项目的
.pro文件需添加多媒体模块:QT += multimedia - 长时间录制时,建议将数据写入文件而非内存Buffer,避免内存溢出
- 程序退出时记得释放
QAudioSource、QBuffer、QTimer等动态分配的对象
内容的提问来源于stack exchange,提问作者user22925547
相关产品推荐
相关产品推荐

