Qt 5 中 QAudioRecorder 停止后如何释放录音文件?
结论
state 变为 StoppedState 说明录音器已停止录制,但输出文件可能还没完成收尾,因此暂时无法删除。先查看录音器的 status 是否为 QMediaRecorder::FinalizingStatus,等它退出该状态后再删除。如果收尾完成后文件仍被占用,可以等录音器对象销毁后再试。具体后端可能会在对象释放时才关闭文件句柄。
示例在 StoppedState 时立即显示删除按钮,因此用户可能会在文件仍处于收尾阶段时尝试删除。
等待录音收尾
在 C++ 中监听 statusChanged,等状态不再是 FinalizingStatus 后再执行删除逻辑:
connect(recorder, &QMediaRecorder::statusChanged,
this, [this, recorder](QMediaRecorder::Status status) {
if (recorder->state() == QMediaRecorder::StoppedState &&
status != QMediaRecorder::FinalizingStatus) {
// 此处再通知界面允许删除,或执行删除操作。
}
});
在 QML 中,也可以根据录音器暴露的 status 属性及其状态变化来控制删除按钮。具体属性名称取决于应用暴露给 QML 的类型。如果没有这个属性,可以在 C++ 中监听状态变化,再通知 QML。
如果收尾完成后仍无法删除,可以销毁并重新创建录音器,再删除文件。例如,把录音器设为可销毁的对象,停止录音并确认收尾完成后调用 deleteLater(),等对象销毁后再尝试删除。如果必须保留同一个录音器对象,先确认目标 Qt 版本和音频后端是否会在对象存活期间继续持有文件句柄。
检查实际文件路径
actualLocation 是 QUrl。传给辅助函数时,建议先转换成本地文件路径,避免把 file:///... 形式的 URL 当作普通路径传入:
onClicked: QMLHelper.removeFile(audioRecorder.actualLocation.toLocalFile())
也可以让辅助函数直接接收 QUrl:
Q_INVOKABLE bool removeFile(const QUrl &url)
{
const QString path = url.toLocalFile();
if (path.isEmpty())
return false;
QFile file(path);
const bool removed = file.remove();
qDebug() << removed << ":" << file.errorString();
return removed;
}
额外检查
示例中的 r 是 bool,不能调用 r.errorString()。错误文本应从 QFile 对象读取,例如 file.errorString()。这和文件被占用的原因无关,但可以避免错误日志本身出错。
如果 FinalizingStatus 已结束、录音器对象也已销毁,但文件仍无法删除,请确认 actualLocation 指向预期的本地文件,并检查是否有其他程序或对象同时打开了它。文件句柄何时关闭可能受 Qt 版本和多媒体后端影响。
备注:内容仅供参考。
