如何在Ubuntu QML應用中進行語言錄音
阿新 • • 發佈:2019-02-01
在QML API中,目前並沒有一個相應的API來進行錄音。我們必須使用Qt C++ API QAudioRecorder來進行錄音的工作。在這篇文章中,我們來介紹如何使用這個API來進行錄音。
首先,我們來建立一個“QML App with C++ plugin (qmake)”模版的應用。注意qmake的專案必須是在15.04及以上的target上才可以執行。
為了錄音,我建立了一個叫做“AudioRecorder”的類:
audiorecorder.h
#ifndef AUDIORECORDER_H #define AUDIORECORDER_H #include <QAudioRecorder> #include <QUrl> class AudioRecorder : public QObject { Q_OBJECT Q_PROPERTY ( bool recording READ recording NOTIFY recordingChanged ) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) public: explicit AudioRecorder(QObject *parent = 0); const bool recording() const; QString name() const; Q_INVOKABLE QStringList supportedAudioCodecs(); Q_INVOKABLE QStringList supportedContainers(); Q_INVOKABLE QUrl path() { return m_path; } signals: void recordingChanged(bool); void nameChanged(QUrl); public slots: void setName(QString name); void setRecording(bool recording ); void record(); void stop(); private: QString getFilePath(const QString filename) const; private: QAudioRecorder * m_audioRecorder; bool m_recording; QString m_name; QUrl m_path; }; #endif // AUDIORECORDER_H
audiorecorder.cpp
在這裡,我們使用了QStandardPath來獲得在Ubuntu手機中可以訪問的檔案目錄。這個QAudioRecorder的API的使用也是非常直接的。 我們的Main.qml的介面也非常簡單:#include <QUrl> #include <QStandardPaths> #include <QDir> #include "audiorecorder.h" AudioRecorder::AudioRecorder(QObject *parent) : QObject(parent) { m_audioRecorder = new QAudioRecorder( this ); QAudioEncoderSettings audioSettings; audioSettings.setCodec("audio/PCM"); audioSettings.setQuality(QMultimedia::HighQuality); m_audioRecorder->setEncodingSettings(audioSettings); // https://forum.qt.io/topic/42541/recording-audio-using-qtaudiorecorder/2 m_audioRecorder->setContainerFormat("wav"); m_recording = false; } const bool AudioRecorder::recording() const { return m_recording; } void AudioRecorder::setRecording(bool recording ) { if (m_recording == recording) return; m_recording = recording; emit recordingChanged(m_recording); } void AudioRecorder::record() { qDebug() << "Entering record!"; if ( m_audioRecorder->state() == QMediaRecorder::StoppedState ) { qDebug() << "recording....! "; m_audioRecorder->record ( ); m_recording = true; qDebug() << "m_recording: " << m_recording; emit recordingChanged(m_recording); } } void AudioRecorder::stop() { qDebug() << "Entering stop!"; if ( m_audioRecorder->state() == QMediaRecorder::RecordingState ) { qDebug() << "Stopping...."; m_audioRecorder->stop(); m_recording = false; emit recordingChanged(m_recording); } } QString AudioRecorder::name() const { return m_name; } void AudioRecorder::setName(QString name) { if (m_name == name) return; m_name = name; emit nameChanged(name); // at the same time update the path m_path = QUrl(getFilePath(name)); // set the path m_audioRecorder->setOutputLocation(m_path); } QStringList AudioRecorder::supportedAudioCodecs() { return m_audioRecorder->supportedAudioCodecs(); } QStringList AudioRecorder::supportedContainers() { return m_audioRecorder->supportedContainers(); } QString AudioRecorder::getFilePath(const QString filename) const { QString writablePath = QStandardPaths:: writableLocation(QStandardPaths::DataLocation); qDebug() << "writablePath: " << writablePath; QString absolutePath = QDir(writablePath).absolutePath(); qDebug() << "absoluePath: " << absolutePath; // We need to make sure we have the path for storage QDir dir(absolutePath); if ( dir.mkdir(absolutePath) ) { qDebug() << "Successfully created the path!"; } QString path = absolutePath + "/" + filename; qDebug() << "path: " << path; return path; }
Main.qml
import QtQuick 2.0 import Ubuntu.Components 1.1 import QtMultimedia 5.0 import AudioRecorder 1.0 /*! \brief MainView with a Label and Button elements. */ MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "audiorecorder.liu-xiao-guo" /* This property enables the application to change orientation when the device is rotated. The default is false. */ //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false width: units.gu(60) height: units.gu(85) Page { title: i18n.tr("AudioRecorder") AudioRecorder { id: audio name: "sample.wav" onRecordingChanged: { console.log("recording: " + recording); } } MediaPlayer { id: player autoPlay: true volume: 1.0 } Column { anchors.fill: parent spacing: units.gu(1) Label { text: "Supported Audio codecs:" } ListView { id: audiocodecs width: parent.width height: audiocodecs.contentHeight model:audio.supportedAudioCodecs() delegate: Text { text: modelData } } Rectangle { width: parent.width height: units.gu(0.1) } Label { text: "Supported Containers:" } ListView { id: audiocontainer width: parent.width height: audiocontainer.contentHeight model:audio.supportedContainers() delegate: Text { text: modelData } } } Row { anchors.bottom: parent.bottom anchors.bottomMargin: units.gu(2) anchors.horizontalCenter: parent.horizontalCenter anchors.margins: units.gu(2) spacing: units.gu(2) Button { id: record text: "Record Audio" enabled: !audio.recording onClicked: { audio.record(); } } Button { id: stop text: "Stop" onClicked: { audio.stop(); player.stop(); } } Button { id: play text: "Play Audio" onClicked: { console.log("path: " + audio.path() ); player.source = audio.path(); player.play(); } } } } }
在QML中,我們直接地使用:
AudioRecorder {
id: audio
name: "sample.wav"
onRecordingChanged: {
console.log("recording: " + recording);
}
}
我們可以通過“Record Audio”按鈕來進行錄音的工作。應用的介面如下:
經過在手機上的實驗,錄音的效果非常好,非常清晰。我們可以使用“Play Audio”按鈕來播放。