zhuizhu 7 месяцев назад
Родитель
Сommit
98fe34fad7

+ 4 - 0
LearningSmartClient.pro

@@ -22,6 +22,7 @@ SOURCES += \
     api/roomapi.cpp \
     api/userapi.cpp \
     appevent.cpp \
+    config/networkconfig.cpp \
     main.cpp \
     mainwindow.cpp \
     network/networkaccessmanager.cpp \
@@ -64,6 +65,7 @@ HEADERS += \
     api/roomapi.h \
     api/userapi.h \
     appevent.h \
+    config/networkconfig.h \
     mainwindow.h \
     network/networkaccessmanager.h \
     network/request.h \
@@ -169,4 +171,6 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
 RESOURCES += \
     resources/shared.qrc
 
+DISTFILES += \
+
 

+ 111 - 0
config/networkconfig.cpp

@@ -0,0 +1,111 @@
+#include "networkconfig.h"
+#include <QDebug>
+#include <QCoreApplication>
+#include <QStandardPaths>
+
+NetworkConfig& NetworkConfig::instance()
+{
+    static NetworkConfig instance;
+    static bool initialized = false;
+    if (!initialized) {
+        instance.initDefaults();
+        initialized = true;
+    }
+    return instance;
+}
+
+void NetworkConfig::resetToDefaults()
+{
+    initDefaults();
+}
+
+void NetworkConfig::setServerConfig(const ServerConfig& config)
+{
+    m_serverConfig = config;
+}
+
+void NetworkConfig::setStreamConfig(const StreamConfig& config)
+{
+    m_streamConfig = config;
+}
+
+void NetworkConfig::setRtmpConfig(const StreamConfig& config)
+{
+    m_streamConfig = config;
+}
+
+void NetworkConfig::setRecordConfig(const RecordConfig& config)
+{
+    m_recordConfig = config;
+}
+
+QString NetworkConfig::getRtmpUrl(const QString& streamName) const
+{
+    if (streamName.isEmpty()) {
+        return m_streamConfig.getRtmpUrl();
+    }
+    return QString("rtmp://%1:%2/%3/%4")
+        .arg(m_streamConfig.host)
+        .arg(m_streamConfig.port)
+        .arg(m_streamConfig.app)
+        .arg(streamName);
+}
+
+QString NetworkConfig::getRtmpStreamUrl() const
+{
+    return m_streamConfig.getRtmpUrl();
+}
+
+
+
+bool NetworkConfig::isValid() const
+{
+    // 检查服务器配置
+    if (m_serverConfig.host.isEmpty() || m_serverConfig.port <= 0 || m_serverConfig.port > 65535) {
+        return false;
+    }
+    
+    // 检查RTMP配置
+    if (m_streamConfig.host.isEmpty() || m_streamConfig.port <= 0 || m_streamConfig.port > 65535) {
+        return false;
+    }
+    
+    if (m_streamConfig.app.isEmpty() || m_streamConfig.streamKey.isEmpty()) {
+        return false;
+    }
+    
+    // 检查录制配置
+    if (m_recordConfig.videoBitRate <= 0 || m_recordConfig.videoFrameRate <= 0 ||
+        m_recordConfig.videoQuality < 0 || m_recordConfig.videoQuality > 100 ||
+        m_recordConfig.audioBitRate <= 0) {
+        return false;
+    }
+    
+    return true;
+}
+
+void NetworkConfig::initDefaults()
+{
+    // 服务器配置默认值
+    m_serverConfig.host = "106.55.186.74";  // 使用项目中的生产服务器
+    m_serverConfig.port = 8200;
+    m_serverConfig.useHttps = false;
+    m_serverConfig.apiPath = "/api";
+    
+    // 流媒体配置 (默认使用RTMP协议)
+    m_streamConfig.protocol = StreamProtocol::RTSP;
+    m_streamConfig.host = "127.0.0.1"; // 使用项目中的生产服务器
+    m_streamConfig.port = 554;
+    m_streamConfig.app = "stream";
+    m_streamConfig.streamKey = "V1";
+    
+    // 录制配置默认值
+    m_recordConfig.outputDir = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
+    if (m_recordConfig.outputDir.isEmpty()) {
+        m_recordConfig.outputDir = QCoreApplication::applicationDirPath() + "/recordings";
+    }
+    m_recordConfig.videoBitRate = 8000000;   // 8Mbps
+    m_recordConfig.videoFrameRate = 30;
+    m_recordConfig.videoQuality = 100;
+    m_recordConfig.audioBitRate = 128000;    // 128kbps
+}

+ 156 - 0
config/networkconfig.h

@@ -0,0 +1,156 @@
+#pragma once
+
+#include <QString>
+#include <QStandardPaths>
+#include <QDir>
+
+/**
+ * @brief 网络配置管理类
+ * 
+ * 统一管理项目中所有的网络配置,包括:
+ * - HTTP API 基础URL
+ * - RTMP 推流服务器配置
+ * - WebSocket 连接配置
+ * - 其他网络相关配置
+ */
+class NetworkConfig
+{
+public:
+    /**
+     * @brief 网络服务器配置结构
+     */
+    struct ServerConfig {
+        QString host = "127.0.0.1";           // 服务器主机地址
+        int port = 8200;                      // 服务器端口
+        bool useHttps = false;                // 是否使用HTTPS
+        QString apiPath = "/api";              // API路径前缀
+        
+        QString getBaseUrl() const {
+            QString protocol = useHttps ? "https" : "http";
+            return QString("%1://%2:%3").arg(protocol, host).arg(port);
+        }
+        
+        QString getWebSocketUrl() const {
+            QString protocol = useHttps ? "wss" : "ws";
+            return QString("%1://%2:%3").arg(protocol, host).arg(port);
+        }
+    };
+    
+    /**
+     * @brief 流媒体协议枚举
+     */
+    enum class StreamProtocol {
+        RTMP,       // Real-Time Messaging Protocol
+        SRT,        // Secure Reliable Transport
+        WebRTC,     // Web Real-Time Communication
+        RTSP,       // Real Time Streaming Protocol
+        UDP,        // User Datagram Protocol
+        TCP         // Transmission Control Protocol
+    };
+    
+    /**
+     * @brief 通用流媒体配置结构
+     */
+    struct StreamConfig {
+        StreamProtocol protocol = StreamProtocol::RTMP;  // 流媒体协议
+        QString host = "127.0.0.1";                     // 服务器地址
+        int port = 1935;                                // 端口
+        QString app = "stream";                         // 应用名/路径
+        QString streamKey = "V1";                       // 推流密钥/流名称
+        
+        QString getStreamUrl() const {
+            switch (protocol) {
+                case StreamProtocol::RTMP:
+                    return QString("rtmp://%1:%2/%3/%4").arg(host).arg(port).arg(app).arg(streamKey);
+                case StreamProtocol::SRT:
+                    return QString("srt://%1:%2?streamid=%3/%4").arg(host).arg(port).arg(app).arg(streamKey);
+                case StreamProtocol::RTSP:
+                    return QString("rtsp://%1:%2/%3/%4").arg(host).arg(port).arg(app).arg(streamKey);
+                case StreamProtocol::UDP:
+                    return QString("udp://%1:%2").arg(host).arg(port);
+                case StreamProtocol::TCP:
+                    return QString("tcp://%1:%2").arg(host).arg(port);
+                case StreamProtocol::WebRTC:
+                    return QString("webrtc://%1:%2/%3/%4").arg(host).arg(port).arg(app).arg(streamKey);
+                default:
+                    return QString("rtmp://%1:%2/%3/%4").arg(host).arg(port).arg(app).arg(streamKey);
+            }
+        }
+        
+        // 保持向后兼容的RTMP方法
+        QString getRtmpUrl() const {
+            return QString("rtmp://%1:%2/%3/%4").arg(host).arg(port).arg(app).arg(streamKey);
+        }
+    };
+    
+    /**
+     * @brief 录制配置结构
+     */
+    struct RecordConfig {
+        QString outputDir;                    // 录制输出目录
+        int videoBitRate = 8000000;          // 视频比特率 (8Mbps)
+        int videoFrameRate = 30;             // 视频帧率
+        int videoQuality = 100;              // 视频质量
+        int audioBitRate = 128000;           // 音频比特率 (128kbps)
+    };
+
+public:
+    /**
+     * @brief 获取配置管理器单例
+     */
+    static NetworkConfig& instance();
+    
+    /**
+     * @brief 重置为默认配置
+     */
+    void resetToDefaults();
+    
+    // 获取配置
+    const ServerConfig& serverConfig() const { return m_serverConfig; }
+    const StreamConfig& streamConfig() const { return m_streamConfig; }
+    const RecordConfig& recordConfig() const { return m_recordConfig; }
+    
+    // 向后兼容的RTMP配置访问方法
+    const StreamConfig& rtmpConfig() const { return m_streamConfig; }
+    
+    // 设置配置
+    void setServerConfig(const ServerConfig& config);
+    void setStreamConfig(const StreamConfig& config);
+    void setRecordConfig(const RecordConfig& config);
+    
+    // 向后兼容的RTMP配置设置方法
+    void setRtmpConfig(const StreamConfig& config);
+    
+    // 便捷方法
+    QString getApiBaseUrl() const { return m_serverConfig.getBaseUrl(); }
+    QString getWebSocketBaseUrl() const { return m_serverConfig.getWebSocketUrl(); }
+    QString getStreamUrl() const { return m_streamConfig.getStreamUrl(); }
+    
+    // 向后兼容的RTMP方法
+    QString getRtmpUrl(const QString& streamName = QString()) const;
+    QString getRtmpStreamUrl() const;
+    
+    /**
+     * @brief 检查网络配置是否有效
+     */
+    bool isValid() const;
+
+private:
+    NetworkConfig() = default;
+    ~NetworkConfig() = default;
+    NetworkConfig(const NetworkConfig&) = delete;
+    NetworkConfig& operator=(const NetworkConfig&) = delete;
+    
+    /**
+     * @brief 初始化默认配置
+     */
+    void initDefaults();
+
+private:
+    ServerConfig m_serverConfig;
+    StreamConfig m_streamConfig;
+    RecordConfig m_recordConfig;
+};
+
+// 便捷的全局访问宏
+#define NetworkConfigInstance NetworkConfig::instance()

+ 3 - 2
libs/AVPlayer/avplayerwidget.cpp

@@ -4,6 +4,7 @@
 
 #include "av_player.h"
 #include "vframe.h"
+#include "../../config/networkconfig.h"
 #include <QtConcurrent>
 #include <QApplication>
 #include <QDebug>
@@ -32,7 +33,7 @@ AVPlayerWidget::AVPlayerWidget(QWidget *parent)
     m_volumeSlider->setValue(50);
     
     // 设置默认测试URL
-    m_urlEdit->setText("rtmp://106.55.186.74:1935/stream/V1/");
+    m_urlEdit->setText(NetworkConfig::instance().getStreamUrl());
 }
 
 AVPlayerWidget::~AVPlayerWidget()
@@ -274,7 +275,7 @@ void AVPlayerWidget::setPlayRoomId(const QString &id)
     // 以当前URL为基准,去掉最后一节后拼接房间ID,避免硬编码服务器地址
     QString base = m_urlEdit->text().trimmed();
     if (base.isEmpty()) {
-        base = "rtmp://106.55.186.74:1935/stream/V1/";
+        base = NetworkConfig::instance().getStreamUrl();
     }
     // rtmp://106.55.186.74:1935/stream/V1/0198da41-cdb6-78e3-879d-2ea32d58f73f
     int lastSlash = base.lastIndexOf('/');

+ 2 - 1
libs/_AvRecorder/ui/av_recorder.cpp

@@ -8,6 +8,7 @@
 #include <QTimer>
 
 #include <capturer/finder.h>
+#include "../../../config/networkconfig.h"
 
 using namespace avrecorder::video;
 
@@ -29,7 +30,7 @@ AvRecorder::AvRecorder(QWidget* parent)
     m_settingsParam.videoParam.width = 1920;
     m_settingsParam.videoParam.height = 1080;
     m_settingsParam.outputDir = ".";
-    m_settingsParam.liveUrl = "rtmp://127.0.0.1:1935/stream/V1";
+    m_settingsParam.liveUrl = NetworkConfig::instance().getStreamUrl().toStdString();
     m_settingsParam.liveName = "stream";
 
     // 1. 视频预览区

+ 92 - 78
network/networkaccessmanager.cpp

@@ -1,4 +1,5 @@
 #include "networkaccessmanager.h"
+#include "../config/networkconfig.h"
 #include "appevent.h"
 
 #include <QBuffer>
@@ -12,11 +13,6 @@
 #include <QUrlQuery>
 #include <QtConcurrent>
 
-// 基础URL配置
-static QString base_url("http://106.55.186.74:8200");
-
-// static QString base_url("http://127.0.0.1:8200");
-
 static const QString messageVal = "msg";
 
 static NetworkAccessManager* namInstance = nullptr;
@@ -143,13 +139,13 @@ RequestClient::Ptr RequestClient::create(const QString& baseURL, const RequestCl
 
 RequestClient::Ptr RequestClient::globalInstance()
 {
-    static RequestClient::Ptr instance = create(base_url, {"", true});
+    static RequestClient::Ptr instance = create(NetworkConfigInstance.getApiBaseUrl(), {"", true});
     return instance;
 }
 
 RequestClient::Ptr RequestClient::baseGlobalInstance()
 {
-    static RequestClient::Ptr instance = create(base_url, {"", false});
+    static RequestClient::Ptr instance = create(NetworkConfigInstance.getApiBaseUrl(), {"", false});
     return instance;
 }
 
@@ -243,17 +239,20 @@ QFuture<HttpResponse> RequestClient::getAsync(const QString& url, const QVariant
 {
     auto promise = std::make_shared<QPromise<HttpResponse>>();
     auto future = promise->future();
-    
-    QMetaObject::invokeMethod(QCoreApplication::instance(), [this, url, params, promise]() {
-        try {
-            auto result = get(url, params);
-            promise->addResult(result);
-            promise->finish();
-        } catch (...) {
-            promise->finish();
-        }
-    }, Qt::QueuedConnection);
-    
+
+    QMetaObject::invokeMethod(
+        QCoreApplication::instance(),
+        [this, url, params, promise]() {
+            try {
+                auto result = get(url, params);
+                promise->addResult(result);
+                promise->finish();
+            } catch (...) {
+                promise->finish();
+            }
+        },
+        Qt::QueuedConnection);
+
     return future;
 }
 
@@ -261,17 +260,20 @@ QFuture<HttpResponse> RequestClient::postAsync(const QString& url, const QJsonDo
 {
     auto promise = std::make_shared<QPromise<HttpResponse>>();
     auto future = promise->future();
-    
-    QMetaObject::invokeMethod(QCoreApplication::instance(), [this, url, data, promise]() {
-        try {
-            auto result = post(url, data);
-            promise->addResult(result);
-            promise->finish();
-        } catch (...) {
-            promise->finish();
-        }
-    }, Qt::QueuedConnection);
-    
+
+    QMetaObject::invokeMethod(
+        QCoreApplication::instance(),
+        [this, url, data, promise]() {
+            try {
+                auto result = post(url, data);
+                promise->addResult(result);
+                promise->finish();
+            } catch (...) {
+                promise->finish();
+            }
+        },
+        Qt::QueuedConnection);
+
     return future;
 }
 
@@ -279,17 +281,20 @@ QFuture<HttpResponse> RequestClient::putAsync(const QString& url, const QJsonDoc
 {
     auto promise = std::make_shared<QPromise<HttpResponse>>();
     auto future = promise->future();
-    
-    QMetaObject::invokeMethod(QCoreApplication::instance(), [this, url, data, promise]() {
-        try {
-            auto result = put(url, data);
-            promise->addResult(result);
-            promise->finish();
-        } catch (...) {
-            promise->finish();
-        }
-    }, Qt::QueuedConnection);
-    
+
+    QMetaObject::invokeMethod(
+        QCoreApplication::instance(),
+        [this, url, data, promise]() {
+            try {
+                auto result = put(url, data);
+                promise->addResult(result);
+                promise->finish();
+            } catch (...) {
+                promise->finish();
+            }
+        },
+        Qt::QueuedConnection);
+
     return future;
 }
 
@@ -297,17 +302,20 @@ QFuture<HttpResponse> RequestClient::deleteAsync(const QString& url)
 {
     auto promise = std::make_shared<QPromise<HttpResponse>>();
     auto future = promise->future();
-    
-    QMetaObject::invokeMethod(QCoreApplication::instance(), [this, url, promise]() {
-        try {
-            auto result = deleteResource(url);
-            promise->addResult(result);
-            promise->finish();
-        } catch (...) {
-            promise->finish();
-        }
-    }, Qt::QueuedConnection);
-    
+
+    QMetaObject::invokeMethod(
+        QCoreApplication::instance(),
+        [this, url, promise]() {
+            try {
+                auto result = deleteResource(url);
+                promise->addResult(result);
+                promise->finish();
+            } catch (...) {
+                promise->finish();
+            }
+        },
+        Qt::QueuedConnection);
+
     return future;
 }
 
@@ -315,17 +323,20 @@ QFuture<HttpResponse> RequestClient::uploadAsync(const QString& url, QHttpMultiP
 {
     auto promise = std::make_shared<QPromise<HttpResponse>>();
     auto future = promise->future();
-    
-    QMetaObject::invokeMethod(QCoreApplication::instance(), [this, url, multiPart, promise]() {
-        try {
-            auto result = upload(url, multiPart);
-            promise->addResult(result);
-            promise->finish();
-        } catch (...) {
-            promise->finish();
-        }
-    }, Qt::QueuedConnection);
-    
+
+    QMetaObject::invokeMethod(
+        QCoreApplication::instance(),
+        [this, url, multiPart, promise]() {
+            try {
+                auto result = upload(url, multiPart);
+                promise->addResult(result);
+                promise->finish();
+            } catch (...) {
+                promise->finish();
+            }
+        },
+        Qt::QueuedConnection);
+
     return future;
 }
 
@@ -354,17 +365,20 @@ QFuture<bool> RequestClient::downloadAsync(const QString& url, const QString& sa
 {
     auto promise = std::make_shared<QPromise<bool>>();
     auto future = promise->future();
-    
-    QMetaObject::invokeMethod(QCoreApplication::instance(), [this, url, saveFilePath, promise]() {
-        try {
-            auto result = download(url, saveFilePath);
-            promise->addResult(result);
-            promise->finish();
-        } catch (...) {
-            promise->finish();
-        }
-    }, Qt::QueuedConnection);
-    
+
+    QMetaObject::invokeMethod(
+        QCoreApplication::instance(),
+        [this, url, saveFilePath, promise]() {
+            try {
+                auto result = download(url, saveFilePath);
+                promise->addResult(result);
+                promise->finish();
+            } catch (...) {
+                promise->finish();
+            }
+        },
+        Qt::QueuedConnection);
+
     return future;
 }
 
@@ -372,7 +386,7 @@ QNetworkReply* RequestClient::sendGetRequest(const QString& url, const QVariantM
 {
     m_networkManager->setTransferTimeout(m_timeout);
 
-    QString base = m_baseUrl.isEmpty() ? base_url : m_baseUrl;
+    QString base = m_baseUrl.isEmpty() ? NetworkConfig::instance().getApiBaseUrl() : m_baseUrl;
     QUrl fullUrl(base + url);
 
     if (!params.isEmpty()) {
@@ -395,7 +409,7 @@ QNetworkReply* RequestClient::sendPostRequest(const QString& url, const QJsonDoc
 {
     m_networkManager->setTransferTimeout(m_timeout);
 
-    QString base = m_baseUrl.isEmpty() ? base_url : m_baseUrl;
+    QString base = m_baseUrl.isEmpty() ? NetworkConfig::instance().getApiBaseUrl() : m_baseUrl;
     QUrl fullUrl(base + url);
 
     QBuffer* buffer = new QBuffer;
@@ -417,7 +431,7 @@ QNetworkReply* RequestClient::sendPutRequest(const QString& url, const QJsonDocu
 {
     m_networkManager->setTransferTimeout(m_timeout);
 
-    QString base = m_baseUrl.isEmpty() ? base_url : m_baseUrl;
+    QString base = m_baseUrl.isEmpty() ? NetworkConfig::instance().getApiBaseUrl() : m_baseUrl;
     QUrl fullUrl(base + url);
 
     QBuffer* buffer = new QBuffer;
@@ -438,7 +452,7 @@ QNetworkReply* RequestClient::sendDeleteRequest(const QString& url)
 {
     m_networkManager->setTransferTimeout(m_timeout);
 
-    QString base = m_baseUrl.isEmpty() ? base_url : m_baseUrl;
+    QString base = m_baseUrl.isEmpty() ? NetworkConfig::instance().getApiBaseUrl() : m_baseUrl;
     QUrl fullUrl(base + url);
 
     QNetworkRequest request(fullUrl);
@@ -452,7 +466,7 @@ QNetworkReply* RequestClient::sendUploadRequest(const QString& url, QHttpMultiPa
 {
     m_networkManager->setTransferTimeout(m_timeout);
 
-    QString base = m_baseUrl.isEmpty() ? base_url : m_baseUrl;
+    QString base = m_baseUrl.isEmpty() ? NetworkConfig::instance().getApiBaseUrl() : m_baseUrl;
     QUrl fullUrl(base + url);
 
     QNetworkRequest request(fullUrl);

+ 3 - 2
widgets/recorderwidget.cpp

@@ -7,6 +7,7 @@
 #include <QStandardPaths>
 #include <QOpenGLFunctions>
 #include <QPainter>
+#include "../config/networkconfig.h"
 
 // 静态实例指针
 RecorderWidget* RecorderWidget::s_instance = nullptr;
@@ -46,7 +47,7 @@ RecorderWidget::RecorderWidget(QWidget *parent)
     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
     // 初始化默认设置
-    m_settings.liveUrl = "rtmp://106.55.186.74:1935/stream/V1";
+    m_settings.liveUrl = NetworkConfig::instance().getStreamUrl();
     m_settings.liveName = "0198da41-cdb6-78e3-879d-2ea32d58f73f";
     m_settings.outputDir = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation).toStdString();
     m_settings.videoBitRate = 8000000;
@@ -435,7 +436,7 @@ bool RecorderWidget::startStreaming()
     }
     
     // 推流地址
-    QString streamUrl = QString::fromStdString(m_settings.liveUrl + "/" + m_settings.liveName);
+    QString streamUrl = m_settings.liveUrl + "/" + QString::fromStdString(m_settings.liveName);
     strcpy_s(m_recorderSetting.output, streamUrl.toUtf8().constData());
     
     // 音频设备设置:优先使用外部指定,否则选默认

+ 1 - 1
widgets/recorderwidget.h

@@ -33,7 +33,7 @@ class RecorderWidget : public QWidget
 
 public:
     struct Settings {
-        std::string liveUrl = "rtmp://127.0.0.1:1935/stream/V1";
+        QString liveUrl; // 将通过NetworkConfig动态获取
         std::string liveName = "stream";
         std::string outputDir = ".";
         int videoBitRate = 8000000;  // 8Mbps