Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
21bbbbb
Add program-based blanking/mute when source not visible
rowdytomato Dec 11, 2025
b679230
blanking stability fix
rowdytomato Dec 12, 2025
06a7d81
Fix studio mode and formatting
rowdytomato Dec 14, 2025
b79ba15
Fix crash on exit when Branch Output Status Dock is open
rowdytomato Dec 14, 2025
d3aa84c
Merge pull request #103 from rowdytomato/obs-exit-dock-crash
hanatyan128 Jan 10, 2026
d1f06ab
Merge pull request #101 from rowdytomato/master
hanatyan128 Jan 10, 2026
d8df1b2
fix: Tweak translations for blanking mode settings
hanatyan128 Feb 22, 2026
912f53b
refactor: Apply coding style
hanatyan128 Feb 22, 2026
2a7da18
remove: Dead code.
hanatyan128 Feb 22, 2026
bb7e112
refactor: Rename blanking output variables for clarity
hanatyan128 Feb 22, 2026
62663a0
fix: clang-format error
hanatyan128 Feb 22, 2026
9131dd9
feat: Implement profile-specific settings saving and loading in outpu…
hanatyan128 Feb 22, 2026
3caa268
feat: Defer loading settings on profile change to ensure proper event…
hanatyan128 Feb 22, 2026
f1ecd06
fix: Update notes for blanking settings in multiple language files
hanatyan128 Feb 22, 2026
11ad824
fix: Update version number to 1.0.8 in buildspec.json
hanatyan128 Feb 22, 2026
6f3169c
fix: Add gap line in stream options and update mute audio property vi…
hanatyan128 Feb 22, 2026
cb4e669
fix: Validate recording path and handle errors for unavailable paths
hanatyan128 Feb 22, 2026
8472ee8
chore: Add draft of AGENTS.md
hanatyan128 Feb 22, 2026
5f658a7
chore: Update .gitignore to include build.ps1 and remove build-window…
hanatyan128 Feb 22, 2026
e520f66
fix: Update locale string instructions to include all locale files in…
hanatyan128 Feb 22, 2026
9f7a6e0
feat: Display blanking status in recording/streaming status on the St…
hanatyan128 Feb 22, 2026
7b0e0b4
refactor: Multi-line ternary operator to if/else statements for bette…
hanatyan128 Feb 22, 2026
9263be4
Merge pull request #107 from OPENSPHERE-Inc/feat-saving-status-dock-s…
hanatyan128 Feb 22, 2026
55a1ca5
Merge pull request #108 from OPENSPHERE-Inc/fix-crash-when-record-pat…
hanatyan128 Feb 22, 2026
f18ffc9
feat: Add capturing video of filter functionality
hanatyan128 Feb 23, 2026
d68fd75
Merge pull request #109 from OPENSPHERE-Inc/feat-capture-filter-video…
hanatyan128 Feb 23, 2026
f5b7015
fix: Status Dock settings are not saved correctly when quitting OBS 32
hanatyan128 Feb 23, 2026
f877c1a
feat: Add replay buffer functionality
hanatyan128 Feb 23, 2026
e908425
fix: clang-format errors
hanatyan128 Feb 23, 2026
4cdac2f
improve: Japenase translation
hanatyan128 Feb 23, 2026
8165b96
fix: Update output display for replay buffer in OutputTableRow
hanatyan128 Feb 23, 2026
27e9a40
Merge pull request #110 from OPENSPHERE-Inc/feat-integrate-replay-buffer
hanatyan128 Feb 23, 2026
211733c
fix: Enhance testing instructions for Branch Output filter stability
hanatyan128 Feb 23, 2026
d80bac3
add: Optimize GPU usage of filter input mode.
hanatyan128 Feb 27, 2026
c38dc2d
fix: Blanking mode was not exited when branch outputs were in the scene.
hanatyan128 Feb 27, 2026
07547e1
Merge branch 'patch-1.0.8' into feat-filter-input-mode-optimization
hanatyan128 Feb 27, 2026
b2d784c
fix: When adding a branch output to a scene and using filter input mo…
hanatyan128 Feb 27, 2026
880859f
fix: Improve translations
hanatyan128 Feb 27, 2026
7dcea5e
Merge pull request #111 from OPENSPHERE-Inc/feat-filter-input-mode-op…
hanatyan128 Feb 27, 2026
6cc8071
fix: clang-format error
hanatyan128 Feb 27, 2026
fbdc990
feat: Add new interlock modes, Replay Buffer, Always OFF
hanatyan128 Feb 28, 2026
a0e6335
feat: Add improved filter properties UI
hanatyan128 Feb 28, 2026
3ac54b6
Merge pull request #112 from OPENSPHERE-Inc/feat-interlock-new-modes
hanatyan128 Feb 28, 2026
2f60a65
Merge pull request #113 from OPENSPHERE-Inc/improve-filter-properties-ui
hanatyan128 Feb 28, 2026
86da803
fix: clang-format error
hanatyan128 Feb 28, 2026
d83ba63
fix: ensure blanking output and audio states are reset in innner of m…
hanatyan128 Feb 28, 2026
815ef49
fix: Bug where audio was not muted properly in blanking and mute mode…
hanatyan128 Feb 28, 2026
872b515
fix: Made blanking mode more robust by purging blankSource and using …
hanatyan128 Feb 28, 2026
557a832
fix: clang-format error.
hanatyan128 Feb 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
# Except additional project files
!screenshot1.jpg
!screenshot2.jpg
!build-windows-installer.ps1
!build.ps1
!README_ja.md

# Except for AI agent instructions
!AGENTS.md
254 changes: 254 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
# AGENTS.md — Branch Output Plugin for OBS Studio

## Project Overview

**Branch Output** is an OBS Studio plugin (shared library / module) that adds an effect filter allowing
individual sources or scenes to stream and/or record independently from the main OBS output.
It is developed and maintained by **OPENSPHERE Inc.** under the GPLv2+ license.

- Repository language: **C++ 17** with **Qt 6** for UI
- Build system: **CMake** (≥ 3.16)
- Based on the official [obs-plugintemplate](https://github.com/obsproject/obs-plugintemplate)
- Target OBS Studio version: **≥ 30.1.0** (Qt6, x64 / ARM64 / Apple Silicon)

---

## Repository Layout

```
branch-output/
├── CMakeLists.txt # Top-level CMake project definition
├── CMakePresets.json # CMake presets (windows-x64, macos, linux-x86_64, CI variants)
├── buildspec.json # Build specification (name, version, dependencies, UUIDs)
├── build.ps1 # Local Windows build script (RelWithDebInfo)
├── .clang-format # C++ code style (clang-format ≥ 16)
├── .cmake-format.json # CMake code style
├── .github/
│ ├── actions/ # Reusable format-check actions
│ └── workflows/ # CI workflows (build, format check, release)
├── cmake/ # CMake helpers & platform-specific modules
├── build-aux/ # Auxiliary build scripts (format runners)
├── data/
│ └── locale/ # Translation files (en-US, ja-JP, zh-CN, ko-KR, etc.)
├── src/
│ ├── plugin-main.cpp # Plugin entry point, BranchOutputFilter implementation
│ ├── plugin-main.hpp # BranchOutputFilter class declaration
│ ├── plugin-ui.cpp # OBS properties UI, filter settings UI
│ ├── plugin-support.h # Auto-generated plugin support header
│ ├── plugin-support.c.in # Template for plugin-support.c
│ ├── utils.cpp / .hpp # Utility functions, encoder helpers, profile helpers
│ ├── audio/
│ │ ├── audio-capture.cpp / .hpp # Audio capture abstraction
│ └── UI/
│ ├── output-status-dock.cpp / .hpp # Status dock widget
│ ├── resources.qrc # Qt resource file
│ └── images/ # Icons and images
└── release/ # Build output directory
```

---

## Build Instructions

### Prerequisites

| Platform | Toolchain |
|----------|-----------|
| Windows | Visual Studio 17 2022, CMake ≥ 3.16, Qt 6 |
| macOS | Xcode 15+, CMake ≥ 3.16, Qt 6 |
| Linux | GCC / Clang, CMake ≥ 3.16, Qt 6 |

OBS Studio sources and pre-built dependencies are fetched automatically via `buildspec.json`
(obs-studio 30.1.2, obs-deps, Qt6).

### Windows (local)

```powershell
# Configure + Build + Install
.\build.ps1

# With Inno Setup installer
.\build.ps1 -installer
```

Or manually:

```powershell
cmake --fresh -S . -B build_x64 -G "Visual Studio 17 2022" -A x64
cmake --build build_x64 --config RelWithDebInfo
cmake --install build_x64 --prefix release/Package --config RelWithDebInfo
```

### CMake Presets

Use `cmake --preset <name>` with one of:
- `windows-x64` / `windows-ci-x64`
- `macos` / `macos-ci`
- `linux-x86_64` / `linux-ci-x86_64`

---

## Architecture & Key Concepts

### Plugin Entry Point

The plugin registers an OBS **effect filter** via `obs_source_info` (filter ID: `osi_branch_output`).
The main class is `BranchOutputFilter` (declared in `plugin-main.hpp`), which is a `QObject` subclass.

### Core Responsibilities of BranchOutputFilter

| Area | Description |
|------|-------------|
| **Streaming** | Creates up to `MAX_SERVICES` (8) independent streaming outputs with dedicated services, encoders, and reconnect logic. |
| **Recording** | Supports file recording with various container formats, time/size-based splitting, pause/unpause, and chapter markers. |
| **Audio** | Manages up to `MAX_AUDIO_MIXES` audio contexts via `AudioCapture` class. Supports filter audio, per-source audio, and audio track selection. |
| **Video** | Creates an OBS view (`obs_view_t`) with a private video output for per-filter encoding and resolution control. |
| **UI** | Properties panel built via OBS properties API (`plugin-ui.cpp`). Status dock (`BranchOutputStatusDock`) shows live statistics for all filters. |
| **Hotkeys** | Registers hotkey pairs for enable/disable, split recording, pause/unpause, and chapter markers. |
| **Interlock** | Can link filter activation to OBS streaming, recording, or virtual camera states. |
| **Blanking** | Uses a private solid-color source to blank output when the parent source is inactive. |

### Threading Model

- OBS callbacks (video render, audio filter, video tick) may run on **different threads** from the UI thread.
- `pthread_mutex_t outputMutex` protects streaming/recording output state.
- `QMutex` protects audio buffers in `AudioCapture`.
- UI updates use `QMetaObject::invokeMethod` with `Qt::QueuedConnection` for thread safety.
- Settings changes are tracked via revision counters (`storedSettingsRev` / `activeSettingsRev`) to defer restarts.

### OBS API Usage

The plugin heavily uses:
- `obs-module.h` — Module registration, locale, config paths
- `obs-frontend-api.h` — Profile config, scene enumeration, frontend events
- `obs.hpp` — OBS RAII wrappers (`OBSSourceAutoRelease`, `OBSEncoderAutoRelease`, `OBSOutputAutoRelease`, etc.)
- `util/deque.h`, `util/threading.h`, `util/platform.h` — Low-level utilities

---

## Code Style & Formatting

### C++ (clang-format)

- **Standard**: C++17
- **Column limit**: 120
- **Indent**: 4 spaces (tabs not used)
- **Brace style**: Custom — functions use next-line braces; control statements use same-line braces
- **clang-format version**: ≥ 16 required
- Run: `clang-format -i src/**/*.cpp src/**/*.hpp`

### CMake (cmake-format)

- **Line width**: 120
- **Tab size**: 2
- Config: `.cmake-format.json`

### CI Enforcement

Format is checked in CI via `.github/workflows/check-format.yaml` using reusable actions
(`run-clang-format`, `run-cmake-format`). PRs and pushes to `master` are validated.

---

## Coding Guidelines

### General Rules

1. **Follow OBS plugin conventions** — Use `obs_log()` for logging, `OBS_DECLARE_MODULE()` for entry, locale via `obs_module_text()`.
2. **RAII wrappers** — Always use `OBSSourceAutoRelease`, `OBSDataAutoRelease`, etc. instead of manual `obs_*_release()`.
3. **Thread safety** — Any data shared between OBS callbacks and UI must be guarded by mutex. Use `QMetaObject::invokeMethod` with `Qt::QueuedConnection` when calling UI methods from non-UI threads.
4. **Settings migration** — When changing settings schema, add backward-compatible migration code in the constructor (see `audio_source` migration example in `BranchOutputFilter` constructor).
5. **Qt MOC** — Classes using `Q_OBJECT` must be in headers. `AUTOMOC`, `AUTOUIC`, `AUTORCC` are enabled.

### Naming Conventions

- **Classes**: PascalCase (`BranchOutputFilter`, `AudioCapture`, `OutputTableRow`)
- **Methods**: camelCase (`startOutput`, `stopRecordingOutput`, `onIntervalTimerTimeout`)
- **Constants/Macros**: UPPER_SNAKE_CASE (`MAX_SERVICES`, `FILTER_ID`, `OUTPUT_MAX_RETRIES`)
- **Member variables**: camelCase, no prefix (`filterSource`, `videoEncoder`, `recordingActive`)
- **Static callbacks**: camelCase with descriptive prefix (`onEnableFilterHotkeyPressed`, `audioFilterCallback`)

### Ternary Operators

- **Avoid multi-line ternary expressions** — clang-format cannot reliably format nested or multi-line ternary operators (`a ? b : c`) in a readable way. Use `if`/`else if`/`else` statements instead when the expression would span multiple lines.

### Error Handling

- Use `obs_log(LOG_ERROR, ...)` for errors, `LOG_WARNING` for warnings, `LOG_INFO` for lifecycle events, `LOG_DEBUG` for verbose tracing.
- Check return values from OBS API calls; handle gracefully (do not crash OBS).
- Never throw C++ exceptions across OBS API boundaries.

### Localization

- All user-facing strings must use `obs_module_text("Key")` or the `QTStr("Key")` helper.
- Add new keys to `data/locale/en-US.ini` (primary) and ideally to `ja-JP.ini`.
- Locale files use INI format: `Key="Value"`.

---

## Testing & Validation

- There are no automated unit tests in this repository currently.
- **Manual testing** is required: load the plugin in OBS Studio, add the "Branch Output" filter, and verify streaming/recording behavior.
- Test on all supported platforms when possible (Windows x64, macOS, Linux).
- Verify Studio Mode compatibility (Branch Output ignores studio mode's program and outputs from preview).
- Verify that enabling and then disabling the Branch Output filter does not cause a crash.
- Verify that shutting down OBS does not crash when the Branch Output filter is inactive or active, respectively.
- Verify that switching scene collections does not crash when the Branch Output filter is inactive or active, respectively.
- Verify that no memory leaks are logged on OBS shutdown.
- Verify that mutex does not cause deadlocks.

---

## CI / CD

| Workflow | Trigger | Purpose |
|----------|---------|---------|
| `push.yaml` | Push to `master`/`main`/`release/**`, tags | Format check + build + release creation |
| `build-project.yaml` | Called by push/PR workflows | Multi-platform build (Windows, macOS, Linux) |
| `check-format.yaml` | Called by push workflow | clang-format and cmake-format validation |
| `pr-pull.yaml` | Pull requests | Build validation |
| `dispatch.yaml` | Manual dispatch | On-demand builds |

Release tags follow semver: `X.Y.Z` for stable, `X.Y.Z-beta`/`X.Y.Z-rc` for pre-releases.

---

## Common Tasks for AI Agents

### Adding a New Setting / Feature

1. Add the setting key to `BranchOutputFilter::getDefaults()` in `plugin-main.cpp`.
2. Add UI controls in `plugin-ui.cpp` (use OBS properties API: `obs_properties_add_*`).
3. Handle the setting in `startOutput()` / `stopOutput()` / `updateCallback()` as needed.
4. Add locale strings to **all** locale files under `data/locale/` (`en-US.ini`, `ja-JP.ini`, `zh-CN.ini`, `ko-KR.ini`, `de-DE.ini`, `fr-FR.ini`, `ca-ES.ini`, `ro-RO.ini`, `ru-RU.ini`, `uk-UA.ini`). `en-US.ini` is the primary (required); all others should also be updated.
5. Ensure backward compatibility — existing saved settings must still load correctly.

### Adding a New Streaming Service Slot

- The plugin supports up to `MAX_SERVICES` (8) service slots.
- Each slot has its own `BranchOutputStreamingContext` with output, service, and signals.
- Use `getIndexedPropNameFormat()` for indexed property names.

### Modifying Audio Handling

- Audio capture is abstracted through `AudioCapture` class in `src/audio/`.
- The class manages an audio buffer, supports push/pop patterns, and handles format conversion.
- Audio mixers and encoder binding are managed in `BranchOutputFilter::startOutput()`.

### Modifying the Status Dock

- `BranchOutputStatusDock` in `src/UI/` is a `QFrame`-based dock widget.
- It uses a `QTableWidget` with custom cell classes (`OutputTableCellItem`, `LabelCell`, `FilterCell`).
- Thread-safe updates via `QMetaObject::invokeMethod`.

---

## Important Warnings

- **Do NOT call `obs_filter_get_parent()` in the `BranchOutputFilter` constructor** — it returns `nullptr` at that point. Use `addCallback()` instead.
- **Private sources** (not visible in frontend) are intentionally excluded from status dock and timer registration.
- **Settings revisions** (`storedSettingsRev` / `activeSettingsRev`) exist to avoid stopping output during reconnect attempts. Do not bypass this mechanism.
- **Encoder compatibility** — The plugin maps "simple" encoder names to actual encoder IDs, with version-specific fallbacks (OBS 30 vs OBS 31). See `getSimpleVideoEncoder()` in `utils.hpp`.
- **Memory management** — Use OBS RAII wrappers. Raw `bfree()` / `obs_data_release()` calls are error-prone.
- **`.gitignore` uses allowlist pattern** — New top-level files/directories must be explicitly un-ignored with `!` prefix.
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ if(ENABLE_QT)
endif()

target_sources(
${CMAKE_PROJECT_NAME} PRIVATE src/plugin-main.cpp src/plugin-ui.cpp src/utils.cpp src/audio/audio-capture.cpp
src/UI/output-status-dock.cpp src/UI/resources.qrc)
${CMAKE_PROJECT_NAME}
PRIVATE src/plugin-main.cpp
src/plugin-replay-buffer.cpp
src/plugin-ui.cpp
src/utils.cpp
src/audio/audio-capture.cpp
src/video/filter-video-capture.cpp
src/UI/output-status-dock.cpp
src/UI/resources.qrc)

set_target_properties_plugin(${CMAKE_PROJECT_NAME} PROPERTIES OUTPUT_NAME ${_name})
8 changes: 7 additions & 1 deletion build-windows-installer.ps1 → build.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Param (
[switch]$installer
)

$BuildSpec = Get-Content -Path ./buildspec.json -Raw | ConvertFrom-Json
$ProductName = $BuildSpec.name
$ProductVersion = $BuildSpec.version
Expand All @@ -8,4 +12,6 @@ cmake --fresh -S . -B build_x64 -Wdev -Wdeprecated -DCMAKE_SYSTEM_VERSION="10.0.
cmake --build build_x64 --config RelWithDebInfo --target ALL_BUILD --
cmake --install build_x64 --prefix release/Package --config RelWithDebInfo

iscc build_x64/installer-Windows.generated.iss /O"release" /F"${OutputName}-Installer-signed"
if ($installer) {
iscc build_x64/installer-Windows.generated.iss /O"release" /F"${OutputName}-Installer-signed"
}
2 changes: 1 addition & 1 deletion buildspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
"name": "osi-branch-output",
"displayName": "Branch Output Plugin",
"version": "1.0.7",
"version": "1.0.8",
"author": "OPENSPHERE Inc.",
"website": "https://opensphere.co.jp/",
"email": "info@opensphere.co.jp",
Expand Down
25 changes: 25 additions & 0 deletions data/locale/ca-ES.ini
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Status.Active="Actiu"
Status.Paused="En pausa"
Status.Pending="Pendent"
Status.Stopping="Aturant"
Status.BlankSuffix=" (Negre)"
Status.BlankMutedSuffix=" (Negre+Mut)"
Reset="Restableix"
ResetAll="Restableix-ho tot"
EnableAll="Activa-ho tot"
Expand All @@ -33,7 +35,9 @@ AlwaysOn="Sempre ON"
Streaming="Transmissió"
Recording="Gravació"
StreamingOrRecording="Transmissió o gravació"
ReplayBuffer="Memòria de repetició"
VirtualCam="Càmera virtual"
AlwaysOff="Sempre OFF"
StreamRecording="Gravació en flux"
Path="Ruta del directori"
VideoFormat="Format de contenidor"
Expand Down Expand Up @@ -130,6 +134,10 @@ UseProfileRecordingPath="Utilitzeu la ruta de gravació del perfil"
NoSpaceFileName="Genera noms de fitxer sense espai"
KeepOutputBaseResolution="No reinicieu la sortida quan canviï la resolució de la font"
KeepOutputBaseResolutionNote="Si s'activa, la imatge de vídeo pot quedar retallada o tenir espais en blanc quan es canvia la resolució de la font."
BlankWhenNotVisible="Enfosqueix la sortida quan la font no és a la sortida principal"
BlankWhenNotVisibleNote="Manté la transmissió/enregistrament actiu però substitueix el vídeo per negre sempre que la font no sigui visible a la sortida principal activa. Utilitzeu-ho quan no vulgueu enregistrar ni transmetre escenes fora d'antena."
MuteAudioWhenBlank="Silencia l'àudio mentre està enfosquit"
MuteAudioWhenBlankNote="Quan l'enfosquiment està actiu, també silencia les fonts d'àudio seleccionades. Utilitzeu-ho quan no vulgueu enregistrar ni transmetre l'àudio de les escenes fora d'antena."
AudioSourceNote="<strong>Àudio mestre:</strong> Sortida mixta d'OBS (té 6 pistes conegudes)<br /><strong>Àudio de font:</strong> Àudio del conducte de filtre que es passa al filtre Branch Output.<br /><strong>Àudio de font:</strong> Àudio agrupat de la font després de passar per tots els filtres del conducte."
SplitRecordingFileHotkey="Divideix el fitxer d'enregistrament de '%1'"
SplitRecordingAllHotkey="Divideix tots els fitxers d'enregistrament de Sortida de Branca"
Expand All @@ -147,3 +155,20 @@ SuspendRecordingWhenSourceCollapsedNote="Si hi ha emissió, l'enregistrament s'a
AddChapterToRecordingFileHotkey="Afegeix capítol al fitxer d'enregistrament de '%1'"
AddChapterToAllRecordings="Afegeix capítol a tots els enregistraments"
AddChapterToRecordingAllHotkey="Afegeix capítol a tots els enregistraments de Sortida de Branca"
VideoSourceType="Font de vídeo"
VideoSourceType.LongDescription="Seleccioneu quin vídeo capturar per a la sortida.\n'Sortida de la font' captura la sortida renderitzada final de la font (després de tots els filtres).\n'Entrada de filtre' captura el vídeo a la posició d'aquest filtre a la cadena (abans d'aquest filtre i qualsevol filtre a sota)."
VideoSourceType.Source="Mescla independent (Per defecte)"
VideoSourceType.FilterInput="Entrada de filtre (Experimental)"
ReplayBuffer="Replay Buffer"
ReplayBufferDuration="Maximum Replay Time (seconds)"
Status.ReplayBuffer="Buffering"
SaveReplayBufferHotkey="Save '%1' Replay Buffer"
SaveReplayBufferAllHotkey="Save all Branch Output replay buffers"
SaveAllReplayBuffers="Save All Replay Buffers"
ReplayBuffer.Saved="Replay Saved"
AdvancedSettings="Advanced Settings"
StreamingDescription="Configureu sortides de transmissió independents a servidors RTMP/SRT (fins a 8 transmissions simultànies)."
RecordingDescription="Enregistreu la sortida de la font en un fitxer independentment de l'enregistrament principal d'OBS."
ReplayBufferDescription="Manteniu les imatges recents en un buffer de reproducció i deseu-les en qualsevol moment mitjançant una drecera de teclat."
ReplayBufferHotkeyNote="Per desar el buffer de reproducció, utilitzeu la drecera de teclat registrada a Configuració d'OBS Studio → Dreceres de teclat."
CustomAudioSourceDescription="Seleccioneu fonts d'àudio específiques en lloc de l'àudio per defecte. Admet àudio multipista amb fins a 6 pistes."
Loading