From 89d4a4c0baaa9a2ef39cc81a36275bb07cc51262 Mon Sep 17 00:00:00 2001 From: zhangjiarui Date: Thu, 30 Jul 2026 13:52:44 +0800 Subject: [PATCH 1/2] fix(camera): keep shutter audio stream active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace QSound with QSoundEffect for shutter playback. Keep a muted\nlooping effect active while shutter sound is enabled to prevent the\naudio backend from entering idle suspension.\n\n使用 QSoundEffect 播放快门音。快门音开启时保持静音循环音效运行,\n避免音频后端空闲挂起。\n\nLog: 修复快门音空闲后首次播放音量偏小的问题\nPMS: https://pms.uniontech.com/bug-view-369937.html\nInfluence: 关闭后重新开启或长时间未拍照后,首次快门声音量保持正常。 --- src/src/Settings.cpp | 4 ++ src/src/Settings.h | 2 + src/src/mainwindow.cpp | 12 ++--- src/src/videowidget.cpp | 103 +++++++++++++++++++++++++++++++++++++--- src/src/videowidget.h | 22 +++++++-- 5 files changed, 124 insertions(+), 19 deletions(-) diff --git a/src/src/Settings.cpp b/src/src/Settings.cpp index 4009d21a..4832b402 100644 --- a/src/src/Settings.cpp +++ b/src/src/Settings.cpp @@ -227,6 +227,10 @@ QVariant Settings::getBackOption(const QString &opt) void Settings::onValueChanged(const QString & key, const QVariant & value) { + if (key == QLatin1String("photosetting.audiosetting.soundswitchbtn")) { + emit shutterSoundEnabledChanged(value.toBool()); + } + if (key.startsWith("outsetting.resolutionsetting.resolution")) { if (m_updatingResolution) return; diff --git a/src/src/Settings.h b/src/src/Settings.h index 77c0472f..1584fa4c 100644 --- a/src/src/Settings.h +++ b/src/src/Settings.h @@ -148,6 +148,8 @@ public slots: */ void flashLightChanged(bool bLight); + void shutterSoundEnabledChanged(bool enabled); + /** * @brief videoFormatChanged 录制视频格式 * @param format 视频格式 diff --git a/src/src/mainwindow.cpp b/src/src/mainwindow.cpp index 862e633d..d2cfde8b 100644 --- a/src/src/mainwindow.cpp +++ b/src/src/mainwindow.cpp @@ -1726,6 +1726,8 @@ void CMainWindow::initUI() connect(m_takePhotoSettingArea, &takePhotoSettingAreaWidget::sngSetFilterName, this, &CMainWindow::onSetFilterName); connect(m_takePhotoSettingArea, &takePhotoSettingAreaWidget::sigExposureChanged, m_videoPre, &videowidget::onExposureChanged); connect(&dc::Settings::get(), SIGNAL(flashLightChanged(bool)), this, SLOT(onSetFlash(bool))); + connect(&Settings::get(), &Settings::shutterSoundEnabledChanged, + m_videoPre, &videowidget::setShutterSoundEnabled); //切换镜像 connect(&Settings::get(), SIGNAL(mirrorModeChanged(bool)), this, SLOT(onMirrorStateChanged(bool))); connect(&Settings::get(), &Settings::delayTimeChanged, this, [ = ](const QString & str) { @@ -1816,10 +1818,7 @@ void CMainWindow::initUI() break; } - if (soundphoto) - set_takeing_photo_sound(1); - else - set_takeing_photo_sound(0); + m_videoPre->setShutterSoundEnabled(soundphoto); m_videoPre->setGridType(gridType); m_videoPre->setInterval(nDelayTime); @@ -2222,10 +2221,7 @@ void CMainWindow::onSettingsDlgClose() break; } - if (soundphoto) - set_takeing_photo_sound(1); - else - set_takeing_photo_sound(0); + m_videoPre->setShutterSoundEnabled(soundphoto); m_videoPre->setInterval(nDelayTime); m_videoPre->setContinuous(nContinuous); diff --git a/src/src/videowidget.cpp b/src/src/videowidget.cpp index 308b5d7e..a0d6781c 100644 --- a/src/src/videowidget.cpp +++ b/src/src/videowidget.cpp @@ -84,7 +84,21 @@ videowidget::videowidget(DWidget *parent) m_pNormalItem->setZValue(0); m_bActive = false; //是否录制中 - m_takePicSound = new QSound(":/resource/Camera.wav"); + m_takePicSound = new QSoundEffect(this); + m_takePicSound->setSource(QUrl("qrc:/resource/Camera.wav")); + m_takePicSound->setLoopCount(1); + m_takePicSound->setVolume(1.0); + connect(m_takePicSound, &QSoundEffect::statusChanged, + this, &videowidget::onShutterSoundStatusChanged); + + m_shutterSoundKeepalive = new QSoundEffect(this); + m_shutterSoundKeepalive->setSource(QUrl("qrc:/resource/Camera.wav")); + m_shutterSoundKeepalive->setLoopCount(QSoundEffect::Infinite); + m_shutterSoundKeepalive->setMuted(true); + connect(m_shutterSoundKeepalive, &QSoundEffect::statusChanged, + this, &videowidget::onShutterSoundKeepaliveStatusChanged); + connect(m_shutterSoundKeepalive, &QSoundEffect::playingChanged, + this, &videowidget::onShutterSoundKeepalivePlayingChanged); m_countTimer = new QTimer(this); m_flashTimer = new QTimer(this); m_recordingTimer = new QTimer(this); @@ -908,11 +922,87 @@ void videowidget::showRecTime() m_recordingTime->setText(strTime); } +void videowidget::setShutterSoundEnabled(bool enabled) +{ + set_takeing_photo_sound(enabled ? 1 : 0); + + if (m_shutterSoundEnabled == enabled) { + return; + } + + m_shutterSoundEnabled = enabled; + if (!enabled) { + m_shutterSoundPending = false; + m_takePicSound->stop(); + m_shutterSoundKeepalive->stop(); + return; + } + + ensureShutterSoundKeepalive(); +} + +void videowidget::ensureShutterSoundKeepalive() +{ + if (!m_shutterSoundEnabled || m_shutterSoundKeepalive->isPlaying() + || m_shutterSoundKeepalive->status() != QSoundEffect::Ready) { + return; + } + + m_shutterSoundKeepalive->setMuted(true); + m_shutterSoundKeepalive->setLoopCount(QSoundEffect::Infinite); + m_shutterSoundKeepalive->play(); +} + +void videowidget::playPendingShutterSound() +{ + if (!m_shutterSoundPending || !m_shutterSoundEnabled + || !m_shutterSoundKeepalive->isPlaying() + || m_takePicSound->status() != QSoundEffect::Ready) { + return; + } + + m_shutterSoundPending = false; + m_takePicSound->play(); +} + +void videowidget::onShutterSoundStatusChanged() +{ + if (m_takePicSound->status() == QSoundEffect::Error) { + m_shutterSoundPending = false; + return; + } + + playPendingShutterSound(); +} + +void videowidget::onShutterSoundKeepaliveStatusChanged() +{ + if (m_shutterSoundKeepalive->status() == QSoundEffect::Error) { + m_shutterSoundPending = false; + return; + } + + ensureShutterSoundKeepalive(); +} + +void videowidget::onShutterSoundKeepalivePlayingChanged() +{ + ensureShutterSoundKeepalive(); + playPendingShutterSound(); +} + void videowidget::flash() { qDebug() << __func__; - if (get_sound_of_takeing_photo()) - m_takePicSound->play(); + if (get_sound_of_takeing_photo()) { + if (m_shutterSoundKeepalive->isPlaying() + && m_takePicSound->status() == QSoundEffect::Ready) { + m_takePicSound->play(); + } else { + m_shutterSoundPending = true; + ensureShutterSoundKeepalive(); + } + } #ifndef __mips__ if (!get_wayland_status()) { @@ -1845,8 +1935,12 @@ videowidget::~videowidget() delete m_flashLabel; m_flashLabel = nullptr; + m_takePicSound->stop(); + m_shutterSoundKeepalive->stop(); delete m_takePicSound; m_takePicSound = nullptr; + delete m_shutterSoundKeepalive; + m_shutterSoundKeepalive = nullptr; delete m_pNormalView; m_pNormalView = nullptr; @@ -1854,9 +1948,6 @@ videowidget::~videowidget() delete m_pNormalScene; m_pNormalScene = nullptr; - delete m_takePicSound; - m_takePicSound = nullptr; - delete m_pGridLayout; m_pGridLayout = nullptr; diff --git a/src/src/videowidget.h b/src/src/videowidget.h index 317038cb..ea5fe586 100644 --- a/src/src/videowidget.h +++ b/src/src/videowidget.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -371,6 +371,8 @@ public slots: */ void updateValidDevices(); + void setShutterSoundEnabled(bool enabled); + private slots: /** * @brief ReceiveMajorImage 处理视频帧 mips、wayland下使用 @@ -394,10 +396,17 @@ private slots: */ void flash(); + void ensureShutterSoundKeepalive(); + void playPendingShutterSound(); + void onShutterSoundStatusChanged(); + void onShutterSoundKeepaliveStatusChanged(); + void onShutterSoundKeepalivePlayingChanged(); + /** - * @brief slotresolutionchanged 分辨率改变槽函数 - * @param 分辨率字符串(如:1920*1080) - */ + * @brief slotresolutionchanged 分辨率改变槽函数 + * @param 分辨率字符串(如:1920*1080) + */ + void slotresolutionchanged(const QString &); /** @@ -529,7 +538,10 @@ private slots: DLabel *m_recordingTime; //录制时长 QString m_videoFormat; //录制视频格式 - QSound *m_takePicSound; //拍照声音 + QSoundEffect *m_takePicSound; //拍照声音 + QSoundEffect *m_shutterSoundKeepalive; + bool m_shutterSoundEnabled = false; + bool m_shutterSoundPending = false; QString m_savePicFolder; //图片文件夹路径 QString m_saveVdFolder; //视频文件夹路径 QTimer *m_countTimer; //倒计时定时器 From 91718b4fe3fc71172c9965386537023ff896a7a8 Mon Sep 17 00:00:00 2001 From: zhangjiarui Date: Thu, 30 Jul 2026 17:02:41 +0800 Subject: [PATCH 2/2] Revert "fix(camera): keep shutter audio stream active" This reverts commit 89d4a4c0baaa9a2ef39cc81a36275bb07cc51262. --- src/src/Settings.cpp | 4 -- src/src/Settings.h | 2 - src/src/mainwindow.cpp | 12 +++-- src/src/videowidget.cpp | 103 +++------------------------------------- src/src/videowidget.h | 22 ++------- 5 files changed, 19 insertions(+), 124 deletions(-) diff --git a/src/src/Settings.cpp b/src/src/Settings.cpp index 4832b402..4009d21a 100644 --- a/src/src/Settings.cpp +++ b/src/src/Settings.cpp @@ -227,10 +227,6 @@ QVariant Settings::getBackOption(const QString &opt) void Settings::onValueChanged(const QString & key, const QVariant & value) { - if (key == QLatin1String("photosetting.audiosetting.soundswitchbtn")) { - emit shutterSoundEnabledChanged(value.toBool()); - } - if (key.startsWith("outsetting.resolutionsetting.resolution")) { if (m_updatingResolution) return; diff --git a/src/src/Settings.h b/src/src/Settings.h index 1584fa4c..77c0472f 100644 --- a/src/src/Settings.h +++ b/src/src/Settings.h @@ -148,8 +148,6 @@ public slots: */ void flashLightChanged(bool bLight); - void shutterSoundEnabledChanged(bool enabled); - /** * @brief videoFormatChanged 录制视频格式 * @param format 视频格式 diff --git a/src/src/mainwindow.cpp b/src/src/mainwindow.cpp index d2cfde8b..862e633d 100644 --- a/src/src/mainwindow.cpp +++ b/src/src/mainwindow.cpp @@ -1726,8 +1726,6 @@ void CMainWindow::initUI() connect(m_takePhotoSettingArea, &takePhotoSettingAreaWidget::sngSetFilterName, this, &CMainWindow::onSetFilterName); connect(m_takePhotoSettingArea, &takePhotoSettingAreaWidget::sigExposureChanged, m_videoPre, &videowidget::onExposureChanged); connect(&dc::Settings::get(), SIGNAL(flashLightChanged(bool)), this, SLOT(onSetFlash(bool))); - connect(&Settings::get(), &Settings::shutterSoundEnabledChanged, - m_videoPre, &videowidget::setShutterSoundEnabled); //切换镜像 connect(&Settings::get(), SIGNAL(mirrorModeChanged(bool)), this, SLOT(onMirrorStateChanged(bool))); connect(&Settings::get(), &Settings::delayTimeChanged, this, [ = ](const QString & str) { @@ -1818,7 +1816,10 @@ void CMainWindow::initUI() break; } - m_videoPre->setShutterSoundEnabled(soundphoto); + if (soundphoto) + set_takeing_photo_sound(1); + else + set_takeing_photo_sound(0); m_videoPre->setGridType(gridType); m_videoPre->setInterval(nDelayTime); @@ -2221,7 +2222,10 @@ void CMainWindow::onSettingsDlgClose() break; } - m_videoPre->setShutterSoundEnabled(soundphoto); + if (soundphoto) + set_takeing_photo_sound(1); + else + set_takeing_photo_sound(0); m_videoPre->setInterval(nDelayTime); m_videoPre->setContinuous(nContinuous); diff --git a/src/src/videowidget.cpp b/src/src/videowidget.cpp index a0d6781c..308b5d7e 100644 --- a/src/src/videowidget.cpp +++ b/src/src/videowidget.cpp @@ -84,21 +84,7 @@ videowidget::videowidget(DWidget *parent) m_pNormalItem->setZValue(0); m_bActive = false; //是否录制中 - m_takePicSound = new QSoundEffect(this); - m_takePicSound->setSource(QUrl("qrc:/resource/Camera.wav")); - m_takePicSound->setLoopCount(1); - m_takePicSound->setVolume(1.0); - connect(m_takePicSound, &QSoundEffect::statusChanged, - this, &videowidget::onShutterSoundStatusChanged); - - m_shutterSoundKeepalive = new QSoundEffect(this); - m_shutterSoundKeepalive->setSource(QUrl("qrc:/resource/Camera.wav")); - m_shutterSoundKeepalive->setLoopCount(QSoundEffect::Infinite); - m_shutterSoundKeepalive->setMuted(true); - connect(m_shutterSoundKeepalive, &QSoundEffect::statusChanged, - this, &videowidget::onShutterSoundKeepaliveStatusChanged); - connect(m_shutterSoundKeepalive, &QSoundEffect::playingChanged, - this, &videowidget::onShutterSoundKeepalivePlayingChanged); + m_takePicSound = new QSound(":/resource/Camera.wav"); m_countTimer = new QTimer(this); m_flashTimer = new QTimer(this); m_recordingTimer = new QTimer(this); @@ -922,87 +908,11 @@ void videowidget::showRecTime() m_recordingTime->setText(strTime); } -void videowidget::setShutterSoundEnabled(bool enabled) -{ - set_takeing_photo_sound(enabled ? 1 : 0); - - if (m_shutterSoundEnabled == enabled) { - return; - } - - m_shutterSoundEnabled = enabled; - if (!enabled) { - m_shutterSoundPending = false; - m_takePicSound->stop(); - m_shutterSoundKeepalive->stop(); - return; - } - - ensureShutterSoundKeepalive(); -} - -void videowidget::ensureShutterSoundKeepalive() -{ - if (!m_shutterSoundEnabled || m_shutterSoundKeepalive->isPlaying() - || m_shutterSoundKeepalive->status() != QSoundEffect::Ready) { - return; - } - - m_shutterSoundKeepalive->setMuted(true); - m_shutterSoundKeepalive->setLoopCount(QSoundEffect::Infinite); - m_shutterSoundKeepalive->play(); -} - -void videowidget::playPendingShutterSound() -{ - if (!m_shutterSoundPending || !m_shutterSoundEnabled - || !m_shutterSoundKeepalive->isPlaying() - || m_takePicSound->status() != QSoundEffect::Ready) { - return; - } - - m_shutterSoundPending = false; - m_takePicSound->play(); -} - -void videowidget::onShutterSoundStatusChanged() -{ - if (m_takePicSound->status() == QSoundEffect::Error) { - m_shutterSoundPending = false; - return; - } - - playPendingShutterSound(); -} - -void videowidget::onShutterSoundKeepaliveStatusChanged() -{ - if (m_shutterSoundKeepalive->status() == QSoundEffect::Error) { - m_shutterSoundPending = false; - return; - } - - ensureShutterSoundKeepalive(); -} - -void videowidget::onShutterSoundKeepalivePlayingChanged() -{ - ensureShutterSoundKeepalive(); - playPendingShutterSound(); -} - void videowidget::flash() { qDebug() << __func__; - if (get_sound_of_takeing_photo()) { - if (m_shutterSoundKeepalive->isPlaying() - && m_takePicSound->status() == QSoundEffect::Ready) { - m_takePicSound->play(); - } else { - m_shutterSoundPending = true; - ensureShutterSoundKeepalive(); - } - } + if (get_sound_of_takeing_photo()) + m_takePicSound->play(); #ifndef __mips__ if (!get_wayland_status()) { @@ -1935,12 +1845,8 @@ videowidget::~videowidget() delete m_flashLabel; m_flashLabel = nullptr; - m_takePicSound->stop(); - m_shutterSoundKeepalive->stop(); delete m_takePicSound; m_takePicSound = nullptr; - delete m_shutterSoundKeepalive; - m_shutterSoundKeepalive = nullptr; delete m_pNormalView; m_pNormalView = nullptr; @@ -1948,6 +1854,9 @@ videowidget::~videowidget() delete m_pNormalScene; m_pNormalScene = nullptr; + delete m_takePicSound; + m_takePicSound = nullptr; + delete m_pGridLayout; m_pGridLayout = nullptr; diff --git a/src/src/videowidget.h b/src/src/videowidget.h index ea5fe586..317038cb 100644 --- a/src/src/videowidget.h +++ b/src/src/videowidget.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -371,8 +371,6 @@ public slots: */ void updateValidDevices(); - void setShutterSoundEnabled(bool enabled); - private slots: /** * @brief ReceiveMajorImage 处理视频帧 mips、wayland下使用 @@ -396,17 +394,10 @@ private slots: */ void flash(); - void ensureShutterSoundKeepalive(); - void playPendingShutterSound(); - void onShutterSoundStatusChanged(); - void onShutterSoundKeepaliveStatusChanged(); - void onShutterSoundKeepalivePlayingChanged(); - /** - * @brief slotresolutionchanged 分辨率改变槽函数 - * @param 分辨率字符串(如:1920*1080) - */ - + * @brief slotresolutionchanged 分辨率改变槽函数 + * @param 分辨率字符串(如:1920*1080) + */ void slotresolutionchanged(const QString &); /** @@ -538,10 +529,7 @@ private slots: DLabel *m_recordingTime; //录制时长 QString m_videoFormat; //录制视频格式 - QSoundEffect *m_takePicSound; //拍照声音 - QSoundEffect *m_shutterSoundKeepalive; - bool m_shutterSoundEnabled = false; - bool m_shutterSoundPending = false; + QSound *m_takePicSound; //拍照声音 QString m_savePicFolder; //图片文件夹路径 QString m_saveVdFolder; //视频文件夹路径 QTimer *m_countTimer; //倒计时定时器