停止录制后,QAudioRecorder没有释放该文件
我在我的QML应用中有一个简单的AudioRecorder。由于在Qt 5中没有直接可用的QML控件来录制音频,我自定义了一个从 QAudioRecorder 派生的类:
#include <QObject>
#include <QAudioRecorder>
#include <QStandardPaths>
#include <QUrl>
#include <QDir>
#include <qqml.h>
class AudioRecorder : public QAudioRecorder
{
Q_OBJECT
QML_ELEMENT
public:
AudioRecorder(QObject* parent = Q_NULLPTR) : QAudioRecorder(parent)
{
QString d = QStandardPaths::writableLocation(QStandardPaths::StandardLocation::MusicLocation);
if (!d.isEmpty())
setOutputLocation(QUrl::fromLocalFile(d));
}
};
在我的应用中,我有一个简单的按钮,用于启动和停止录音:
// My own QML element
AudioRecorder {
id: audioRecorder
}
Button {
id: recButton
onClicked: {
if (audioRecorder.state === MediaState.StoppedState)
audioRecorder.record()
else if (audioRecorder.state === MediaState.RecordingState)
audioRecorder.stop()
}
}
录音结束后,会出现另一个按钮,可以用来删除创建的音频文件。我使用一个辅助类来删除文件,该类提供了一些从QML直接访问不到的函数:
Button {
id: remButton
visible: audioRecorder.state === MediaState.StoppedState
onClicked: QMLHelper.removeFile(audioRecorder.actualLocation)
}
class QMLHelper : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
public:
QMLHelper(QObject* parent = Q_NULLPTR) : QObject(parent) { Q_UNUSED(parent) };
Q_INVOKABLE bool removeFile(const QString& path)
{
if (!path.isEmpty())
{
QFile f(path);
bool r = f.remove();
qDebug() << r << ": " << r.errorString();
return r;
}
return false;
};
}
当我尝试删除文件时,输出是:
false: 该进程无法访问该文件,因为它正在被另一个进程使用。
为什么在调用 stop() 之后,QAudioRecorder 没有释放该文件?我该如何释放该文件以便删除它?
备注:我在QML的 videoRecorder上也尝试过,这里可以正常工作:
Camera {
id: camera
videoRecorder {
id: vr
}
}
Button {
id: vidButton
visible: camera.videoRecorder.recorderStatus !== CameraRecorder.UnavailableStatus
onClicked: {
if (camera.videoRecorder.recorderState === CameraRecorder.StoppedState)
camera.videoRecorder.record()
else if (camera.videoRecorder.recorderState === CameraRecorder.RecordingState)
camera.videoRecorder.stop()
}
}
Button {
id: vidRemButton
visible: camera.videoRecorder.recorderState === CameraRecorder.StoppedState
onClicked: QMLHelper.removeFile(camera.videoRecorder.actualLocation)
}
输出:
true
解决方案
我通过把 AudioRecorder-项放到 Loader 里面解决了这个问题。删除时,我释放当前的 sourceComponent,并重新实例化一个新的,以释放当前对象的所有资源,正如 文档 中所述。
Loader {
id: audioLoader
sourceComponent: audioComponent
}
Component {
id: audioComponent
AudioRecorder { }
}
Button {
id: remButton
visible: audioLoader.item ? audioLoader.item.state === MediaState.StoppedState : false
onClicked: removeFile()
}
function removeFile() {
var p = audioLoader.item
if (p) {
var prevLoc = p.actualLocation
audioLoader.sourceComponent = undefined
audioLoader.sourceComponent = audioComponent
QMLHelper.removeFile(prevLoc)
}
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。