From 76a25aaa97fd64ca7a930f69b8cd490b5c45c673 Mon Sep 17 00:00:00 2001 From: Dan Rossi Date: Mon, 29 Jun 2026 16:11:08 +1000 Subject: [PATCH 1/8] - fixes Windows cmake install path config --- cmake/windows/defaults.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/windows/defaults.cmake b/cmake/windows/defaults.cmake index c6ec842..bea3ef3 100644 --- a/cmake/windows/defaults.cmake +++ b/cmake/windows/defaults.cmake @@ -8,9 +8,10 @@ set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL TRUE) include(buildspec) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + cmake_path(SET ALLUSERSPROFILE_PATH $ENV{ALLUSERSPROFILE}) set( CMAKE_INSTALL_PREFIX - "$ENV{ALLUSERSPROFILE}/obs-studio/plugins" + "${ALLUSERSPROFILE_PATH}/obs-studio/plugins" CACHE STRING "Default plugin installation directory" FORCE From 152a1ccfdf0f143b65b07392459adb7cdf4b7dba Mon Sep 17 00:00:00 2001 From: Dan Rossi Date: Mon, 29 Jun 2026 16:14:16 +1000 Subject: [PATCH 2/8] - add Windows build readme --- WINDOWS.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 WINDOWS.md diff --git a/WINDOWS.md b/WINDOWS.md new file mode 100644 index 0000000..3bc3013 --- /dev/null +++ b/WINDOWS.md @@ -0,0 +1,37 @@ +## Windows Build Instructions + +### Build Setup + +```powershell +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + choco install -y git + choco install -y cmake --installargs 'ADD_CMAKE_TO_PATH=System' + choco install visualstudio2026buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" + choco install rustup +``` + +During the rustup installation choose the `nightly` variant. + +Locate "Visual Studio Installer". Click "Modify". Choose "Desktop Development with C++". Check C++ ATL For x64 + +### Build the OBS fork + +```powershell +cd obs-studio +cmake -G "Visual Studio 18 2026" -A x64 --preset windows-x64 +cmake --build --preset windows-x64 +``` + +### Build the obs-moq plugin and install + +```powershell +cd obs +cmake -G "Visual Studio 18 2026" -A x64 --preset windows-x64 -DMOQ_LOCAL="../moq" +cmake --build --preset windows-x64 --target install +``` + +## Debugging Moq Plugin + +```powershell + $env:RUST_LOG="debug"; $env:RUST_BACKTRACE=1; $env:OBS_LOG_LEVEL="debug"; Set-Location "build_x64\rundir\RelWithDebInfo\bin\64bit"; & .\obs64.exe --verbose +``` From 3087800386bbeb82d613fa4c64a879c3961eef20 Mon Sep 17 00:00:00 2001 From: Dan Rossi Date: Mon, 29 Jun 2026 18:47:51 +1000 Subject: [PATCH 3/8] - Update readme for macOS build --- README.md | 85 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index d5c3be3..1528db3 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,24 @@ ## Features -* **Protocol:** Media over QUIC (MoQ) -* **Video Codecs:** H.264, HEVC (H.265), AV1 -* **Audio Codecs:** AAC, Opus -* **Low Latency:** Leverages QUIC for efficient and low-latency media transport. +- **Protocol:** Media over QUIC (MoQ) +- **Video Codecs:** H.264, HEVC (H.265), AV1 +- **Audio Codecs:** AAC, Opus +- **Low Latency:** Leverages QUIC for efficient and low-latency media transport. ## Installation ### Setup Prerequisites: -* CMake 3.20+ -* C++ Compiler (Clang/GCC/MSVC) -* OBS Studio development libraries (libobs) -* [Fork of OBS-Studio](https://github.com/brianmed/obs-studio) just to show MoQ in the UI. + +- CMake 3.20+ +- C++ Compiler (Clang/GCC/MSVC) +- OBS Studio development libraries (libobs) +- [Fork of OBS-Studio](https://github.com/brianmed/obs-studio) just to show MoQ in the UI. 1. Clone the repos: + ```bash git clone https://github.com/moq-dev/obs.git moq-obs git clone https://github.com/brianmed/obs-studio.git obs-studio @@ -28,16 +30,30 @@ Prerequisites: git clone https://github.com/moq-dev/moq.git moq ``` -2. Build the OBS fork: +2. Build the OBS fork: + ```bash cd obs-studio - # Replace with your platform + # Configure for Windows + cmake -G "Visual Studio 18 2026" -A x64 --preset windows-x64 + # Configure for macos cmake --preset macos - cmake --build --preset macos + + # Build for Windows + cmake --build --preset windows-x64 + + # Build for macOS + cd build_macos + xcodebuild \ + -configuration RelWithDebInfo \ + -scheme obs-studio \ + -parallelizeTargets \ + -destination "generic/platform=macOS,name=Any Mac" ``` 3. Configure the plugin: + ```bash cd moq-obs @@ -50,11 +66,12 @@ Prerequisites: ### Build 1. Build the plugin: + ```bash just build ``` -2. Copy the plugin to the OBS Studio plugins directory and run it: +2. Copy the plugin to the OBS Studio plugins directory and run it: ```bash # macOS only: @@ -63,6 +80,7 @@ just run ``` On linux you'll have to do: + ```bash cp build_x86_64/obs-moq.so ~/.config/obs-studio/plugins/obs-moq/bin/64bit/obs-moq.so # TODO: add Linux command to `just run` @@ -74,19 +92,19 @@ cp build_x86_64/obs-moq.so ~/.config/obs-studio/plugins/obs-moq/bin/64bit/obs-mo 2. Go to **Settings** > **Stream**. 3. In the **Service** dropdown, select **MoQ**. 4. Enter your MoQ Server details: - * For development (`just dev`): `http://localhost:4443/anon`. - * For testing: `https://cdn.moq.dev/anon`. + - For development (`just dev`): `http://localhost:4443/anon`. + - For testing: `https://cdn.moq.dev/anon`. 5. Enter the broadcast name/path: - * For testing: `obs` or some unique string. - * Watch it here: https://moq.dev/watch/?name=obs -5. Configure your Output settings (Codecs, Bitrate) as desired. - * Currently, only: `h264` and `aac` are supported. -6. Start Streaming! - + - For testing: `obs` or some unique string. + - Watch it here: https://moq.dev/watch/?name=obs +6. Configure your Output settings (Codecs, Bitrate) as desired. + - Currently, only: `h264` and `aac` are supported. +7. Start Streaming! ## Manual MoQ Output Streaming Configuration For configuring via a file, prior to launching OBS you can add this to your OBS Profile directory (eg: "Untitled"): + ```bash # Linux $ cat ~/.config/obs-studio/basic/profiles/Untitled/service.json @@ -111,25 +129,22 @@ $ cat ~/Library/Application\ Support/obs-studio/basic/profiles/Untitled/service. 1. Open OBS Studio 2. Goto **Sources** > (right-click) **MoQ Source** 3. Enter your MoQ Server details, eg: - * For development (`just dev`): `http://localhost:4443/anon`. -4. Enter the broadcast name/path: - * For development: `bbb`. + - For development (`just dev`): `http://localhost:4443/anon`. +4. Enter the broadcast name/path: + - For development: `bbb`. 5. Click **OK** - ## Supported Build Environments -| Platform | Tool | -|-----------|--------| -| Windows | Visual Studio 17 2022 | -| macOS | Xcode 16.0 | -| Windows, macOS | CMake 3.30.5 | -| Ubuntu 24.04 | CMake 3.28.3 | -| Ubuntu 24.04 | `ninja-build` | -| Ubuntu 24.04 | `pkg-config` -| Ubuntu 24.04 | `build-essential` | - - +| Platform | Tool | +| -------------- | --------------------- | +| Windows | Visual Studio 17 2022 | +| macOS | Xcode 16.0 | +| Windows, macOS | CMake 3.30.5 | +| Ubuntu 24.04 | CMake 3.28.3 | +| Ubuntu 24.04 | `ninja-build` | +| Ubuntu 24.04 | `pkg-config` | +| Ubuntu 24.04 | `build-essential` | ## License From f56396902ca51a37edac147ce0718341cf391a25 Mon Sep 17 00:00:00 2001 From: Dan Rossi Date: Mon, 29 Jun 2026 19:30:29 +1000 Subject: [PATCH 4/8] - Adding windows console debugger in debug mode --- src/obs-moq.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/obs-moq.cpp b/src/obs-moq.cpp index 678f815..76e69ce 100644 --- a/src/obs-moq.cpp +++ b/src/obs-moq.cpp @@ -30,6 +30,11 @@ extern "C" { #include "moq.h" } +#ifdef _WIN64 + #include + #include +#endif + OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("obs-moq", "en-US") MODULE_EXPORT const char *obs_module_description(void) @@ -43,6 +48,14 @@ bool obs_module_load(void) // The second argument is the string length of the first argument. moq_log_level("info", 4); + // Enable a debug console in Windows if the RUST_LOG env var is set to debug. + #ifdef _WIN64 + const char* logLevel = std::getenv("RUST_LOG"); + if (logLevel && strcmp(logLevel, "debug") == 0) + AllocConsole(); + #endif + + register_moq_output(); register_moq_service(); register_moq_source(); From 050a3ad126ccb822bb49950ff97893e50356e98a Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 29 Jun 2026 11:40:08 -0700 Subject: [PATCH 5/8] Link Windows system libraries required by Rust libmoq libmoq is a Rust static library whose std runtime references Windows system symbols (e.g. NtCreateNamedPipeFile from ntdll) that MSVC does not auto-resolve when the archive is linked into the plugin module, causing LNK2001/LNK1120 at link time. Link the OS import libraries reported by `rustc --print native-static-libs` that aren't pulled in by default. They resolve by name from the Windows SDK (no hard-coded paths), and linking them here keeps the plugin buildable against any libmoq whose package config predates the Windows link declaration. Co-Authored-By: Claude Opus 4.8 --- CMakeLists.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c1e61e..889bf8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,22 @@ else() target_link_libraries(obs-moq PRIVATE moq::moq) endif() +# libmoq is a Rust static library; its std runtime pulls in symbols from Windows +# system libraries (e.g. NtCreateNamedPipeFile from ntdll) that MSVC does not +# auto-resolve when the archive is linked into this module. These are the OS +# import libraries reported by `rustc --print native-static-libs` that aren't +# linked by default; they resolve by name from the Windows SDK (no hard-coded +# paths). The libmoq package config also declares these, but linking them here +# keeps the plugin buildable against any libmoq (local dev tree or prebuilt +# release) whose config may predate that declaration. Duplicate links are +# harmless. +if(WIN32) + target_link_libraries( + obs-moq + PRIVATE ntdll userenv ws2_32 dbghelp bcrypt + ) +endif() + # The obs-deps Qt6 build references the AGL framework transitively (via # WrapOpenGL), but recent macOS SDKs ship no linkable AGL binary -- it exists # only in the runtime dyld shared cache. Generate a stub whose install name From c69aa0aaff7b2220ce7ddcf73036a164cb5c22af Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 29 Jun 2026 11:40:08 -0700 Subject: [PATCH 6/8] Address PR #45 review feedback - Drop the redundant `-G "Visual Studio 18 2026" -A x64` from the docs: with `--preset`, the generator and architecture come from the preset (Visual Studio 17 2022), and a non-matching `-G` makes CMake error. - Align the documented Visual Studio version with the preset (2022, not 2026), including the chocolatey build-tools package. - Revert the macOS build doc to `cmake --build --preset macos` (matching the justfile) instead of a raw xcodebuild invocation. - Fix obs-moq.cpp formatting to satisfy clang-format (IndentPPDirectives: None / right pointer alignment): de-indent the preprocessor blocks, use `const char *`, and drop the stray blank line. - Include for std::getenv rather than relying on a transitive include. Co-Authored-By: Claude Opus 4.8 --- README.md | 11 +++-------- WINDOWS.md | 6 +++--- src/obs-moq.cpp | 16 ++++++++-------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 1528db3..bc815f0 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ Prerequisites: ```bash cd obs-studio - # Configure for Windows - cmake -G "Visual Studio 18 2026" -A x64 --preset windows-x64 + # Configure for Windows (generator and architecture come from the preset) + cmake --preset windows-x64 # Configure for macos cmake --preset macos @@ -44,12 +44,7 @@ Prerequisites: cmake --build --preset windows-x64 # Build for macOS - cd build_macos - xcodebuild \ - -configuration RelWithDebInfo \ - -scheme obs-studio \ - -parallelizeTargets \ - -destination "generic/platform=macOS,name=Any Mac" + cmake --build --preset macos ``` 3. Configure the plugin: diff --git a/WINDOWS.md b/WINDOWS.md index 3bc3013..73ac8db 100644 --- a/WINDOWS.md +++ b/WINDOWS.md @@ -6,7 +6,7 @@ Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) choco install -y git choco install -y cmake --installargs 'ADD_CMAKE_TO_PATH=System' - choco install visualstudio2026buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" + choco install visualstudio2022buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" choco install rustup ``` @@ -18,7 +18,7 @@ Locate "Visual Studio Installer". Click "Modify". Choose "Desktop Development wi ```powershell cd obs-studio -cmake -G "Visual Studio 18 2026" -A x64 --preset windows-x64 +cmake --preset windows-x64 cmake --build --preset windows-x64 ``` @@ -26,7 +26,7 @@ cmake --build --preset windows-x64 ```powershell cd obs -cmake -G "Visual Studio 18 2026" -A x64 --preset windows-x64 -DMOQ_LOCAL="../moq" +cmake --preset windows-x64 -DMOQ_LOCAL="../moq" cmake --build --preset windows-x64 --target install ``` diff --git a/src/obs-moq.cpp b/src/obs-moq.cpp index 76e69ce..c4dd263 100644 --- a/src/obs-moq.cpp +++ b/src/obs-moq.cpp @@ -31,8 +31,9 @@ extern "C" { } #ifdef _WIN64 - #include - #include +#include +#include +#include #endif OBS_DECLARE_MODULE() @@ -49,12 +50,11 @@ bool obs_module_load(void) moq_log_level("info", 4); // Enable a debug console in Windows if the RUST_LOG env var is set to debug. - #ifdef _WIN64 - const char* logLevel = std::getenv("RUST_LOG"); - if (logLevel && strcmp(logLevel, "debug") == 0) - AllocConsole(); - #endif - +#ifdef _WIN64 + const char *logLevel = std::getenv("RUST_LOG"); + if (logLevel && strcmp(logLevel, "debug") == 0) + AllocConsole(); +#endif register_moq_output(); register_moq_service(); From b673c207cd2fc2b83d40c732cc224f75c71cb6ae Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 29 Jun 2026 12:13:16 -0700 Subject: [PATCH 7/8] Fix Windows debug console so Rust logs are actually visible Allocate the console before moq_log_level() so the Rust logger binds to a valid stderr, and reopen stdout/stderr onto CONOUT$ -- AllocConsole sets the process std handles but does not redirect the C runtime streams, so without this the debug console stayed empty. Co-Authored-By: Claude Opus 4.8 --- src/obs-moq.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/obs-moq.cpp b/src/obs-moq.cpp index c4dd263..d564c2f 100644 --- a/src/obs-moq.cpp +++ b/src/obs-moq.cpp @@ -32,6 +32,7 @@ extern "C" { #ifdef _WIN64 #include +#include #include #include #endif @@ -45,17 +46,23 @@ MODULE_EXPORT const char *obs_module_description(void) bool obs_module_load(void) { - // Use RUST_LOG env var for more verbose output - // The second argument is the string length of the first argument. - moq_log_level("info", 4); - - // Enable a debug console in Windows if the RUST_LOG env var is set to debug. + // On Windows, allocate a console when RUST_LOG=debug *before* initializing + // the Rust logger below, so its output binds to a valid stderr. AllocConsole + // sets the process std handles, but the C runtime streams must be reopened + // onto the console device for that output to be visible. #ifdef _WIN64 const char *logLevel = std::getenv("RUST_LOG"); - if (logLevel && strcmp(logLevel, "debug") == 0) + if (logLevel && strcmp(logLevel, "debug") == 0) { AllocConsole(); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } #endif + // Use RUST_LOG env var for more verbose output + // The second argument is the string length of the first argument. + moq_log_level("info", 4); + register_moq_output(); register_moq_service(); register_moq_source(); From 489f29f0b14e1c777c89bf7acef52ef735f52095 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 29 Jun 2026 12:22:49 -0700 Subject: [PATCH 8/8] Default relay to cdn.moq.dev and randomize broadcast name Change the MoQ dock defaults so the plugin works against the public relay out of the box: relay URL defaults to https://cdn.moq.dev/anon, and the broadcast name defaults to "obs-" (a 6-char suffix) so distinct setups don't collide on the shared relay. Saved settings still override these on subsequent launches. Co-Authored-By: Claude Opus 4.8 --- src/moq-dock.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/moq-dock.cpp b/src/moq-dock.cpp index dda20dd..924e60d 100644 --- a/src/moq-dock.cpp +++ b/src/moq-dock.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #ifndef MOQ_VERSION_STRING @@ -71,16 +72,30 @@ std::string SettingsPath() return s; } +// Default broadcast name "obs-" so distinct setups don't collide on a +// shared relay out of the box. Only used until the user edits/saves their own. +std::string RandomBroadcastName() +{ + static const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, (int)sizeof(charset) - 2); + std::string s = "obs-"; + for (int i = 0; i < 6; i++) + s += charset[dist(gen)]; + return s; +} + } // namespace MoQDock::MoQDock(QWidget *parent) : QWidget(parent) { urlEdit = new QLineEdit(this); - urlEdit->setText("http://localhost:4443/anon"); - urlEdit->setPlaceholderText("https://cdn.moq.dev/anon"); + urlEdit->setText("https://cdn.moq.dev/anon"); + urlEdit->setPlaceholderText("http://localhost:4443/anon"); pathEdit = new QLineEdit(this); - pathEdit->setText("obs"); + pathEdit->setText(QString::fromStdString(RandomBroadcastName())); pathEdit->setPlaceholderText("(optional) broadcast name"); // Labels above the fields (WrapAllRows), and let the fields grow to the full