#include "settings_page.h" #include #include "encoder/video_encoder.h" #include "encoder/audio_encoder.h" SettingsPage::SettingsPage(Param* param, QWidget* parent) : QDialog(parent) , _param(param) { setFont(QFont("Microsoft Yahei")); _InitUi(); _InitConnect(); } void SettingsPage::_InitConnect() { connect(_applyBtn, &QPushButton::released, [this] { _WriteSettings(); }); connect(_cancelBtn, &QPushButton::released, [this] { this->close(); }); connect(_yesBtn, &QPushButton::released, [this] { _WriteSettings(); this->close(); }); connect(_selDirBtn, &QPushButton::released, [this] { QString selectedDir = QFileDialog::getExistingDirectory(this, "选择输出目录", "./", QFileDialog::ShowDirsOnly); // 若目录路径不为空 if (!selectedDir.isEmpty()) { // 显示选择的目录路径 _fileDirEdit->setText(selectedDir); } }); if (_resetBestBtn) { connect(_resetBestBtn, &QPushButton::released, [this] { _ApplyBestDefaults(); }); } } void SettingsPage::_WriteSettings() { _param->videoParam.bitRate = _videoBitRateBox->value() * 1000; _param->videoParam.fps = _videoFpsBox->value(); _param->videoParam.name = _videoEncoderBox->currentText().toStdString(); _param->videoParam.width = _videoWidthBox ? _videoWidthBox->value() : _param->videoParam.width; _param->videoParam.height = _videoHeightBox ? _videoHeightBox->value() : _param->videoParam.height; _param->audioParam.bitRate = _audioBitRateBox->value() * 1000; if (_audioEncoderBox) { _param->audioParam.name = _audioEncoderBox->currentText().toStdString(); } _param->outputDir = _fileDirEdit->text().toStdString(); // 直播参数为项目内置设置,不从UI写回 } void SettingsPage::_InitUi() { setWindowTitle("Settings"); auto layout = new QVBoxLayout; layout->addWidget(_InitVideoUi()); layout->addWidget(_InitAudioUi()); layout->addWidget(_InitOutputUi()); // 不显示“直播”设置(项目内置配置,不需要在UI中展示) auto hLayout = new QHBoxLayout; _resetBestBtn = new QPushButton("最佳默认"); _applyBtn = new QPushButton("应用"); _cancelBtn = new QPushButton("取消"); _yesBtn = new QPushButton("确定"); hLayout->setAlignment(Qt::AlignRight); hLayout->addWidget(_resetBestBtn); hLayout->addStretch(); hLayout->addWidget(_applyBtn); hLayout->addWidget(_cancelBtn); hLayout->addWidget(_yesBtn); layout->addLayout(hLayout); setLayout(layout); } QGroupBox* SettingsPage::_InitVideoUi() { auto groupBox = new QGroupBox("视频"); auto layout = new QVBoxLayout; _videoBitRateBox = new QSpinBox; _videoBitRateBox->setMinimum(0); _videoBitRateBox->setMaximum(INT_MAX); _videoBitRateBox->setValue(_param->videoParam.bitRate / 1000); _videoFpsBox = new QSpinBox; _videoFpsBox->setMinimum(1); _videoFpsBox->setMaximum(120); _videoFpsBox->setValue(_param->videoParam.fps); // 分辨率设置 _videoWidthBox = new QSpinBox; _videoWidthBox->setMinimum(160); _videoWidthBox->setMaximum(7680); _videoWidthBox->setValue(_param->videoParam.width > 0 ? _param->videoParam.width : 1920); _videoHeightBox = new QSpinBox; _videoHeightBox->setMinimum(120); _videoHeightBox->setMaximum(4320); _videoHeightBox->setValue(_param->videoParam.height > 0 ? _param->videoParam.height : 1080); _videoEncoderBox = new QComboBox; auto&& encoders = Encoder::GetUsableEncoders(); for (auto&& encoder : encoders) { _videoEncoderBox->addItem(encoder.c_str()); } if (_videoEncoderBox->count() == 0) { _videoEncoderBox->addItem("libx264"); } // 如果当前参数名不在列表中,则默认选中第一项 if (_videoEncoderBox->findText(_param->videoParam.name.c_str()) == -1) { _videoEncoderBox->setCurrentIndex(0); } else { _videoEncoderBox->setCurrentText(_param->videoParam.name.c_str()); } layout->addLayout( _CreateDescription("比特率(kB):", "越高的比特率越清晰, 但越占用硬件资源", _videoBitRateBox)); layout->addLayout( _CreateDescription("帧率:", "越高的帧率越流畅, 但越占用硬件资源", _videoFpsBox)); layout->addLayout( _CreateDescription("分辨率-宽:", "输出视频宽度,建议与屏幕或窗口比例一致", _videoWidthBox)); layout->addLayout( _CreateDescription("分辨率-高:", "输出视频高度,建议与屏幕或窗口比例一致", _videoHeightBox)); layout->addLayout(_CreateDescription( "编码器:", "libx264 为软件编码, CPU占用高但兼容性强, 其他为硬件编码, 效果与软件编码相反", _videoEncoderBox)); groupBox->setLayout(layout); return groupBox; } QGroupBox* SettingsPage::_InitAudioUi() { auto groupBox = new QGroupBox("音频"); auto layout = new QVBoxLayout; _audioBitRateBox = new QSpinBox; _audioBitRateBox->setMinimum(0); _audioBitRateBox->setMaximum(INT_MAX); _audioBitRateBox->setValue(_param->audioParam.bitRate / 1000); // 音频编码器选择 _audioEncoderBox = new QComboBox; { auto&& encoders = Encoder::GetUsableEncoders(); for (auto&& encoder : encoders) { _audioEncoderBox->addItem(encoder.c_str()); } if (_audioEncoderBox->count() == 0) { _audioEncoderBox->addItem("aac"); } // 如果当前参数名不在列表中,则默认选中第一项 if (_audioEncoderBox->findText(_param->audioParam.name.c_str()) == -1) { _audioEncoderBox->setCurrentIndex(0); } else { _audioEncoderBox->setCurrentText(_param->audioParam.name.c_str()); } } layout->addLayout( _CreateDescription("比特率(kB):", "越高的比特率越清晰, 但越占用硬件资源", _audioBitRateBox)); layout->addLayout(_CreateDescription( "编码器:", "aac 兼容性最好;opus 音质高但需容器/推流支持;mp3 不建议用于flv", _audioEncoderBox)); groupBox->setLayout(layout); return groupBox; } QGroupBox* SettingsPage::_InitOutputUi() { auto groupBox = new QGroupBox("输出"); auto layout = new QHBoxLayout; _fileDirEdit = new QLineEdit(_param->outputDir.c_str()); _selDirBtn = new QPushButton("选择"); layout->addWidget(_fileDirEdit); layout->addWidget(_selDirBtn); groupBox->setLayout(layout); return groupBox; } QGroupBox* SettingsPage::_InitLiveUi() { auto groupBox = new QGroupBox("直播"); auto layout = new QVBoxLayout; _liveUrlEdit = new QLineEdit(QString::fromStdString(_param->liveUrl)); _liveNameEdit = new QLineEdit(QString::fromStdString(_param->liveName)); layout->addLayout(_CreateDescription("推流地址:", "例如: rtmp://:1935/stream/V1 或 rtsp://...", _liveUrlEdit)); layout->addLayout(_CreateDescription("流名称:", "推流路径中的名称或Key", _liveNameEdit)); groupBox->setLayout(layout); return groupBox; } void SettingsPage::_ApplyBestDefaults() { // 优先选择可用编码器列表的第一项(通常为硬件加速编码器) if (_videoEncoderBox && _videoEncoderBox->count() > 0) { _videoEncoderBox->setCurrentIndex(0); } if (_audioEncoderBox && _audioEncoderBox->count() > 0) { _audioEncoderBox->setCurrentIndex(0); } // 设置为通用的高质量方案:1080p@30fps, 8 Mbps;音频 160 kbps if (_videoWidthBox) _videoWidthBox->setValue(1920); if (_videoHeightBox) _videoHeightBox->setValue(1080); if (_videoFpsBox) _videoFpsBox->setValue(30); if (_videoBitRateBox) _videoBitRateBox->setValue(8000); if (_audioBitRateBox) _audioBitRateBox->setValue(160); } QHBoxLayout* SettingsPage::_CreateDescription(std::string_view text, std::string_view textEx, QWidget* widget) { auto layout = new QHBoxLayout; auto label = new QLabel(text.data()); label->setToolTip(textEx.data()); layout->addWidget(label); layout->addWidget(widget); return layout; }