feat: 支持手动指定日志目录和调试音频目录

- 新增 app.log_dir 配置项,支持通过设置页面或命令行 (-l/--log-dir) 指定日志目录
- 调试音频目录 (audio.debug_dir) 已正确传入 StreamingAudioWriter
- 设置页面新增"通用设置"分组,包含日志目录选择
- 未设置时使用系统默认 AppDataLocation 路径

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Alvin Young 2026-06-11 14:00:23 +08:00
parent 801dbe1ec2
commit f4b7149435
5 changed files with 56 additions and 10 deletions

View File

@ -65,6 +65,9 @@ void ConfigManager::loadDefaults() {
{
QMutexLocker locker(&mutex_);
config_ = QVariantMap{
{"app", QVariantMap{
{"log_dir", ""}
}},
{"stt", QVariantMap{
{"model_path", ""},
{"model_type", "sense_voice"},

View File

@ -15,14 +15,10 @@ int main(int argc, char* argv[])
app.setApplicationVersion("0.1.0");
app.setOrganizationName("Impress");
// 初始化日志文件
QString logDir = QStandardPaths::writableLocation(
// 默认日志目录(配置加载后可能被覆盖)
QString defaultLogDir = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation);
QDir().mkpath(logDir);
QString logFilePath = logDir + "/app.log";
impress::Logger::init(logFilePath);
LOG_INFO("Main", QString("应用启动,日志文件: %1").arg(logFilePath));
QDir().mkpath(defaultLogDir);
// 命令行参数
QCommandLineParser parser;
@ -32,6 +28,7 @@ int main(int argc, char* argv[])
parser.addOptions({
{{"c", "config"}, "指定配置文件路径", "path"},
{{"m", "model"}, "指定模型路径", "path"},
{{"l", "log-dir"}, "指定日志文件目录", "path"},
});
parser.process(app);
@ -39,8 +36,7 @@ int main(int argc, char* argv[])
auto* configManager = app.configManager();
QString configPath = parser.value("config");
if (configPath.isEmpty()) {
// 使用默认配置目录
configPath = logDir + "/config.json";
configPath = defaultLogDir + "/config.json";
}
if (QFile::exists(configPath)) {
@ -50,6 +46,20 @@ int main(int argc, char* argv[])
LOG_INFO("Main", "使用默认配置");
}
// 确定日志目录:命令行 > 配置 > 默认 AppDataLocation
QString effectiveLogDir = parser.value("log-dir");
if (effectiveLogDir.isEmpty()) {
effectiveLogDir = configManager->get("app.log_dir").toString();
}
if (effectiveLogDir.isEmpty()) {
effectiveLogDir = defaultLogDir;
}
QDir().mkpath(effectiveLogDir);
QString logFilePath = effectiveLogDir + "/app.log";
impress::Logger::init(logFilePath);
LOG_INFO("Main", QString("日志目录: %1").arg(effectiveLogDir));
// 命令行覆盖模型路径
QString modelPath = parser.value("model");
if (!modelPath.isEmpty()) {

View File

@ -48,6 +48,23 @@ void SettingsPage::setupUI() {
contentLayout->setContentsMargins(12, 8, 12, 8);
contentLayout->setSpacing(12);
// 通用设置
auto* appGroup = new QGroupBox("通用设置", contentWidget);
auto* appLayout = new QFormLayout(appGroup);
appLayout->setSpacing(8);
appLayout->setContentsMargins(10, 12, 10, 12);
auto* logDirRow = new QHBoxLayout();
logDirEdit_ = new QLineEdit(this);
logDirEdit_->setPlaceholderText("日志文件保存路径(为空时使用系统默认路径)");
logDirBtn_ = new QPushButton("浏览...", this);
connect(logDirBtn_, &QPushButton::clicked, this, &SettingsPage::onBrowseLogDir);
logDirRow->addWidget(logDirEdit_);
logDirRow->addWidget(logDirBtn_);
appLayout->addRow("日志目录:", logDirRow);
contentLayout->addWidget(appGroup);
// STT 设置
auto* sttGroup = new QGroupBox("STT 推理设置", contentWidget);
auto* sttLayout = new QFormLayout(sttGroup);
@ -221,6 +238,7 @@ void SettingsPage::setupUI() {
}
void SettingsPage::loadFromConfig() {
logDirEdit_->setText(configManager_->get("app.log_dir").toString());
modelPathEdit_->setText(configManager_->get("stt.model_path").toString());
tokensPathEdit_->setText(configManager_->get("stt.tokens_path").toString());
modelTypeCombo_->setCurrentText(configManager_->get("stt.model_type").toString());
@ -252,6 +270,7 @@ void SettingsPage::loadFromConfig() {
void SettingsPage::saveToConfig() {
// 批量写入所有配置,只发射一次 configChanged 信号
QMap<QString, QVariant> batch;
batch["app.log_dir"] = logDirEdit_->text();
batch["stt.model_path"] = modelPathEdit_->text();
batch["stt.tokens_path"] = tokensPathEdit_->text();
batch["stt.model_type"] = modelTypeCombo_->currentText();
@ -338,6 +357,14 @@ void SettingsPage::onBrowseAudioDebugDir() {
}
}
void SettingsPage::onBrowseLogDir() {
QString path = QFileDialog::getExistingDirectory(this, "选择日志目录", "",
QFileDialog::ShowDirsOnly);
if (!path.isEmpty()) {
logDirEdit_->setText(path);
}
}
void SettingsPage::onSaveConfig() {
saveToConfig();
if (configManager_->save()) {

View File

@ -32,6 +32,7 @@ private slots:
void onBrowseModelPath();
void onBrowseTokensPath();
void onBrowseAudioDebugDir();
void onBrowseLogDir();
void onSaveConfig();
void onResetConfig();
@ -45,6 +46,10 @@ private:
ConfigManager* configManager_;
// 通用设置
QLineEdit* logDirEdit_;
QPushButton* logDirBtn_;
// STT 设置
QLineEdit* modelPathEdit_;
QPushButton* browseBtn_;

View File

@ -161,9 +161,10 @@ void STTTestPage::startAudioCapture() {
int deviceIdx = deviceCombo_->currentIndex() - 1;
audioSampleRate_ = configManager_->get("stt.sample_rate").toInt();
bool debugEnabled = configManager_->get("stt.debug_save_audio").toBool();
QString debugDir = configManager_->get("audio.debug_dir").toString();
// 启动流式录制器
if (!streamingWriter_->start(audioSampleRate_, debugEnabled)) {
if (!streamingWriter_->start(audioSampleRate_, debugEnabled, debugDir)) {
QMessageBox::critical(this, "错误", "无法启动流式录制器");
return;
}