Architecture & Developer Reference
This page is the “how it works under the hood” reference for developers extending the plugin. It covers the module structure, the handler-based client, the Sequencer integration, the editor details-panel system, key types, and the patterns for adding new features.
For the full list of native C++ delegates (the Native-suffixed events that support lambda binding), see Native Delegates.
Module Structure
The plugin consists of three modules:
| Module | Type | Purpose |
|---|---|---|
InhyeongOBSWebSocket | Runtime | Core functionality, subsystems, components, Sequencer integration |
InhyeongOBSWebSocketEditor | Editor | Details panel customization, editor subsystem, Sequencer track editor |
InhyeongOBSWebSocketTakeRecorder | Editor | Take Recorder sync (loads PostEngineInit, only when the Takes plugin is enabled) |
Take Recorder Sync Config
Settings are stored in Config/DefaultInhyeongOBS.ini:
[/Script/InhyeongOBSWebSocketTakeRecorder.InhyeongOBSTakeRecorderSync]
bEnabled=True
bShowNotifications=True
bWarnIfOBSNotConnected=True
bAutoStartRecord=True
bAutoStopRecord=True
PostRollSeconds=0.000000
bAutoStartVirtualCam=False
bAutoStopVirtualCam=False
bAutoStartStream=False
bAutoStopStream=False
bSwitchSceneOnStart=False
StartSceneName=
bSwitchSceneOnStop=False
StopSceneName=
bCreateChaptersOnMarkedFrames=True
bAddStartChapterWithMetadata=True
bMatchRecordDirectory=False
bLogFileCorrelation=True
Utility Classes
| Class | Location | Purpose |
|---|---|---|
FOBSRequestBatchBuilder | Utilities/ | Fluent builder for batch requests |
FOBSJsonBuilder | Utilities/ | Fluent JSON object construction |
Request Type Constants
All OBS WebSocket request types and field names are centralized in Core/Types/InhyeongOBSRequestTypes.h:
#include "Core/Types/InhyeongOBSRequestTypes.h"
// Request types
OBSRequests::GetSceneList // "GetSceneList"
OBSRequests::SetCurrentProgramScene // "SetCurrentProgramScene"
OBSRequests::StartRecord // "StartRecord"
// Field names
OBSFields::SceneName // "sceneName"
OBSFields::InputName // "inputName"
OBSFields::SceneItemId // "sceneItemId"
This prevents typos and makes protocol updates easier to manage.
JSON Builder Utility
FOBSJsonBuilder provides fluent JSON construction for OBS requests:
#include "Utilities/InhyeongOBSJsonBuilder.h"
// Basic usage
TSharedPtr<FJsonObject> Data = FOBSJsonBuilder::Create()
.Add(TEXT("sceneName"), SceneName)
.Add(TEXT("sceneItemId"), SceneItemId)
.Add(TEXT("sceneItemEnabled"), true)
.Build();
// Conditional additions
TSharedPtr<FJsonObject> Settings = FOBSJsonBuilder::Create()
.Add(TEXT("sourceName"), SourceName)
.Add(TEXT("imageFormat"), TEXT("png"))
.AddIfPositive(TEXT("imageWidth"), Width) // Only adds if > 0
.AddIfPositive(TEXT("imageHeight"), Height)
.AddIfInRange(TEXT("imageCompressionQuality"), Quality, 0, 100)
.Build();
// Nested objects
TSharedPtr<FJsonObject> Transform = FOBSJsonBuilder::Create()
.Add(TEXT("positionX"), 100.0f)
.Add(TEXT("positionY"), 200.0f)
.Build();
TSharedPtr<FJsonObject> Request = FOBSJsonBuilder::Create()
.Add(TEXT("sceneName"), SceneName)
.Add(TEXT("sceneItemId"), ItemId)
.Add(TEXT("sceneItemTransform"), Transform)
.Build();
Available Methods:
| Method | Description |
|---|---|
Add(Key, Value) | Add string, int32, int64, float, double, bool, or JSON object |
AddIfNotEmpty(Key, String) | Add only if string is not empty |
AddIfPositive(Key, Number) | Add only if number > 0 |
AddIfInRange(Key, Value, Min, Max) | Add only if value is within range |
Build() | Returns the constructed TSharedPtr<FJsonObject> |
HasFields() | Check if any fields were added |
Handler Architecture
The WebSocket client uses modular handlers for organization:
UInhyeongOBSWebSocketClient
├── UInhyeongOBSOutputs (Stream, Record, VirtualCam, ReplayBuffer)
├── UInhyeongOBSScenes (Scene switching, scene items)
├── UInhyeongOBSAudio (Audio inputs, volume, mute)
├── UInhyeongOBSInputSettings (Text, browser, image, media source settings)
├── UInhyeongOBSMediaInputs (Media playback control)
├── UInhyeongOBSStudioMode (Preview scene, studio transitions)
├── UInhyeongOBSTransitions (Scene transitions, duration, settings)
├── UInhyeongOBSFilters (Source filter management)
├── UInhyeongOBSScreenshots (Screenshot capture and texture conversion)
├── UInhyeongOBSConfig (Scene collections, profiles, video settings, persistent data)
└── UInhyeongOBSGeneral (Stats, hotkeys, vendor requests, custom events)
Access handlers via:
Client->GetOutputs()
Client->GetScenes()
Client->GetAudio()
Client->GetInputSettings()
Client->GetMediaInputs()
Client->GetStudioMode()
Client->GetTransitions()
Client->GetFilters()
Client->GetScreenshots()
Client->GetConfig()
Client->GetGeneral()
Sequencer Architecture
The Sequencer integration follows Unreal’s movie scene pattern:
Runtime Module (InhyeongOBSWebSocket)
├── EventTriggersTrack/ Discrete action tracks
│ ├── UMovieSceneOBSTrack Track container with playback settings
│ ├── UMovieSceneOBSSection Section with action parameters
│ ├── FMovieSceneOBSTemplate Evaluation template (boundary detection)
│ ├── FOBSExecutionToken Execution token for firing actions
│ └── PreAnimatedState/ State restoration handlers
│ ├── FOBSOutputPreAnimatedState
│ ├── FOBSScenesPreAnimatedState
│ ├── FOBSAudioPreAnimatedState
│ ├── FOBSTransitionsPreAnimatedState
│ ├── FOBSStudioModePreAnimatedState
│ ├── FOBSFiltersPreAnimatedState
│ └── FOBSSourcesPreAnimatedState
├── KeyframeableTrack/ Interpolated property tracks
│ ├── Audio/
│ │ ├── UMovieSceneOBSVolumeTrack Volume track (targets InputName)
│ │ ├── UMovieSceneOBSVolumeSection Float channel for volume dB
│ │ ├── FMovieSceneOBSVolumeTemplate Continuous evaluation
│ │ ├── FOBSVolumePreAnimatedState Capture/restore volume
│ │ ├── UMovieSceneOBSBalanceTrack Balance track (targets InputName)
│ │ ├── UMovieSceneOBSBalanceSection Float channel for L/R balance
│ │ ├── FMovieSceneOBSBalanceTemplate Continuous evaluation
│ │ └── FOBSBalancePreAnimatedState Capture/restore balance
│ ├── Scene/
│ │ ├── UMovieSceneOBSTransformTrack Transform track (targets Scene+Source)
│ │ ├── UMovieSceneOBSTransformSection Float/Int channels for transform
│ │ ├── FMovieSceneOBSTransformTemplate Continuous evaluation
│ │ └── FOBSTransformPreAnimatedState Capture/restore transform
│ ├── Sources/
│ │ ├── UMovieSceneOBSColorSourceTrack Color source track (targets InputName)
│ │ ├── UMovieSceneOBSColorSourceSection 4 float channels for RGBA
│ │ ├── FMovieSceneOBSColorSourceTemplate Continuous evaluation, ABGR conversion
│ │ └── FOBSColorSourcePreAnimatedState Capture/restore with format conversion
│ ├── Media/
│ │ ├── UMovieSceneOBSMediaCursorTrack Media cursor track (targets InputName)
│ │ ├── UMovieSceneOBSMediaCursorSection Single float channel for cursor (ms)
│ │ ├── FMovieSceneOBSMediaCursorTemplate Continuous evaluation, float→int64
│ │ └── FOBSMediaCursorPreAnimatedState Capture/restore cursor position
│ ├── Filters/
│ │ ├── UMovieSceneOBSFilterSettingTrack Generic filter setting track (targets Source+Filter+Setting)
│ │ ├── UMovieSceneOBSFilterSettingSection Float channel for any numeric setting
│ │ ├── FMovieSceneOBSFilterSettingTemplate Continuous evaluation with JSON overlay
│ │ ├── FOBSFilterSettingPreAnimatedState Capture/restore from filter cache
│ │ └── FOBSCommonFilterSettings UI hints for known filter types
│ └── Transitions/
│ ├── UMovieSceneOBSTransitionDurationTrack Duration track (current transition)
│ ├── UMovieSceneOBSTransitionDurationSection Float channel for duration ms
│ ├── FMovieSceneOBSTransitionDurationTemplate Continuous evaluation, handles fixed transitions
│ └── FOBSTransitionDurationPreAnimatedState Capture/restore duration
├── ContinuousStateTrack/ State-holding tracks (no keyframes)
│ ├── Audio/
│ │ ├── OBSMuteStatePreAnimatedState Capture/restore mute state
│ │ ├── MovieSceneOBSMuteStateSection Section with bMuteState property
│ │ ├── MovieSceneOBSMuteStateTrack Track targeting InputName
│ │ ├── MovieSceneOBSMuteStateTemplate Setup/Evaluate/TearDown
│ │ ├── OBSMonitorTypeStatePreAnimatedState Capture/restore monitor type
│ │ ├── MovieSceneOBSMonitorTypeStateSection Section with MonitorType enum
│ │ ├── MovieSceneOBSMonitorTypeStateTrack Track targeting InputName
│ │ └── MovieSceneOBSMonitorTypeStateTemplate Setup/Evaluate/TearDown
│ ├── Scene/
│ │ ├── OBSVisibilityStatePreAnimatedState Capture/restore visibility
│ │ ├── MovieSceneOBSVisibilityStateSection Section with bVisible property
│ │ ├── MovieSceneOBSVisibilityStateTrack Track targeting Scene+ItemId
│ │ ├── MovieSceneOBSVisibilityStateTemplate Setup/Evaluate/TearDown
│ │ ├── OBSBlendModeStatePreAnimatedState Capture/restore blend mode
│ │ ├── MovieSceneOBSBlendModeStateSection Section with BlendMode enum
│ │ ├── MovieSceneOBSBlendModeStateTrack Track targeting Scene+ItemId
│ │ ├── MovieSceneOBSBlendModeStateTemplate Setup/Evaluate/TearDown
│ │ ├── OBSLockStatePreAnimatedState Capture/restore lock state
│ │ ├── MovieSceneOBSLockStateSection Section with bLocked property
│ │ ├── MovieSceneOBSLockStateTrack Track targeting Scene+ItemId
│ │ └── MovieSceneOBSLockStateTemplate Setup/Evaluate/TearDown
│ ├── Filter/
│ │ ├── OBSFilterEnabledStatePreAnimatedState Capture/restore filter enabled
│ │ ├── MovieSceneOBSFilterEnabledStateSection Section with bEnabled property
│ │ ├── MovieSceneOBSFilterEnabledStateTrack Track targeting Source+Filter
│ │ └── MovieSceneOBSFilterEnabledStateTemplate Setup/Evaluate/TearDown
│ ├── StudioMode/
│ │ ├── OBSStudioModeStatePreAnimatedState Capture/restore studio mode
│ │ ├── MovieSceneOBSStudioModeStateSection Section with bEnabled property
│ │ ├── MovieSceneOBSStudioModeStateTrack Global track (no target)
│ │ └── MovieSceneOBSStudioModeStateTemplate Setup/Evaluate/TearDown
│ └── Transitions/
│ ├── OBSTransitionStatePreAnimatedState Capture/restore current transition
│ ├── MovieSceneOBSTransitionStateSection Section (presence = apply)
│ ├── MovieSceneOBSTransitionStateTrack Track with TransitionName target
│ └── MovieSceneOBSTransitionStateTemplate Setup/Evaluate/TearDown
├── MediaSyncTrack/ Timeline-synchronized media playback
│ ├── OBSMediaSyncPreAnimatedState Capture/restore media state+position
│ ├── MovieSceneOBSMediaSyncSection Section defines sync window
│ ├── MovieSceneOBSMediaSyncTrack Track targeting MediaInputName
│ └── MovieSceneOBSMediaSyncTemplate Play/pause/seek synchronization
Editor Module (InhyeongOBSWebSocketEditor)
├── Sequencer/
│ ├── Shared/
│ │ └── OBSSequencerMenuRegistry Centralized menu building (prevents duplicates)
│ ├── EventTriggersTrack/
│ │ ├── FMovieSceneOBSTrackEditor Track editor for event trigger
│ │ └── FMovieSceneOBSSectionInterface Section display
│ ├── KeyframeableTrack/
│ │ ├── FOBSKeyframeableTrackEditorBase Shared base for all keyframeable editors
│ │ └── [Category]/FOBSXxxTrackEditor Per-track editors (Volume, Balance, etc.)
│ ├── ContinuousStateTrack/
│ │ ├── FOBSContinuousStateTrackEditorBase Shared base for all continuous state editors
│ │ ├── FOBSContinuousStateSectionInterface Shared section display (colored bar)
│ │ └── [Category]/FOBSXxxStateTrackEditor Per-track editors (Mute, Visibility, etc.)
│ └── MediaSyncTrack/
│ ├── FOBSMediaSyncTrackEditor Track editor with media input picker
│ └── FOBSMediaSyncSectionInterface Section display with offset indicator
└── DetailsCustomization/
└── Sequencer/
├── EventTriggersTrack/ Action params customization
├── KeyframeableTrack/ Target pickers (Input, Scene+Item, etc.)
├── ContinuousStateTrack/ Target pickers per track type
└── MediaSyncTrack/ Track + Section customizations
├── FOBSSequencerActionExecutor Routes to correct OBS client
├── FOBSSequencerActionQueue Throttling, deduplication, batching
└── FOBSSequencerActionRegistry Action metadata registry
Key Classes:
| Class | Purpose |
|---|---|
FOBSSequencerActionRegistry | Static registry of all 40+ actions with metadata |
FOBSSequencerActionQueue | Singleton queue with 33ms throttling (~30fps), deduplication, batch optimization (up to 48 actions/batch) |
FOBSOutputPreAnimatedState | Captures output states before playback for restoration |
FOBSSequencerActionExecutor | Routes actions to the correct OBS client (Editor vs Game subsystem) |
Adding New Sequencer Actions
- Add an enum value to
EOBSSequencerActioninInhyeongOBSSequencerTypes.h. - Add a
REGISTER_ACTIONblock inInhyeongOBSSequencerTypes.cpp. - Add an execution case in
OBSSequencerActionExecutor.cpp. - Add batch request building in
OBSSequencerActionQueue.cpp(if using batching).
Adding Pre-Animated State Support
For State-type actions that modify OBS settings, implement restoration:
- Create
FOBS[Handler]PreAnimatedStateinSequencer/EventTriggersTrack/. - Inherit from
IPersistentEvaluationData. - Implement
CaptureFrom()using the handler’s cached values (no async!). - Implement
RestoreTo()with 150ms debouncing. - Update
MovieSceneOBSTemplate::SupportsPreAnimatedState()to include the category. - Add Setup/TearDown blocks in
MovieSceneOBSTemplate.cpp.
Pre-Animated State Pattern:
// In Setup() - capture before section modifies OBS
FOBS[Handler]PreAnimatedState& State = PersistentData.GetOrAddSectionData();
if (!State.bHasCapturedState)
{
State.CaptureFrom(Handler, EntryAction);
}
// In TearDown() - restore when section becomes inactive
FOBS[Handler]PreAnimatedState* State = PersistentData.FindSectionData();
if (State && State->bHasCapturedState)
{
State->RestoreTo(Handler);
}
Adding New Continuous State Tracks
Each continuous state track requires 4 files in Sequencer/ContinuousStateTrack/[Handler]/:
| File | Purpose |
|---|---|
OBS[State]PreAnimatedState.h/.cpp | Capture/restore, idempotent ApplyState() |
MovieSceneOBS[State]Section.h/.cpp | Simple property (bool/enum), NO channels |
MovieSceneOBS[State]Track.h/.cpp | Container with target identification |
MovieSceneOBS[State]Template.h/.cpp | Setup captures, Evaluate applies, TearDown restores |
Critical Implementation Rules:
- PreAnimatedState inherits
IPersistentEvaluationData(NOT USTRUCT). ApplyState()MUST be idempotent (checkbStateIsAppliedbefore sending).Track::CreateTemplateForSectionuses direct return (NOT*new).- Section has NO
FMovieSceneFloatChannel, just simple properties. - Section constructor sets
EvalOptions.CompletionMode = RestoreState. - Template uses
GetOrAddTrackData<>()/FindTrackData<>()for persistent data.
Adding New Keyframeable Tracks
Each keyframeable property requires 4 files in Sequencer/KeyframeableTrack/[Category]/:
| File | Purpose |
|---|---|
OBS[Property]PreAnimatedState.h/.cpp | Capture/restore original OBS state |
MovieSceneOBS[Property]Section.h/.cpp | Store FMovieSceneFloatChannel keyframes |
MovieSceneOBS[Property]Track.h/.cpp | Container with target identification |
MovieSceneOBS[Property]Template.h/.cpp | Continuous evaluation, delta threshold sending |
Critical Implementation Rules:
- PreAnimatedState inherits
IPersistentEvaluationData(NOT USTRUCT). Track::CreateTemplateForSectionuses direct return (NOT*new).- Template uses
GetOrAddSectionData<>()/FindSectionData<>()for persistent data. Setup()caches the client viaFOBSSequencerActionExecutor::GetClientForContext()into PreAnimatedState.Evaluate()retrieves the client fromState->CachedClient.Get()(not the Player context, which is unavailable inEvaluate).Evaluate()routes throughFOBSSequencerActionQueue::Get().EnqueueAction()for throttling/batching.- The delta threshold check happens BEFORE enqueueing to avoid unnecessary action creation.
Sequencer Editor UI
All tracks feature a polished editor experience:
Track Outliner:
- Connection status indicator (green/red dot)
- Quick ”+” button to add sections at the playhead
- Automatic curve editor integration via
FMovieSceneFloatChannel
Details Panel Customizations:
| Track | Target Selection | Notes |
|---|---|---|
| Volume / Balance | Audio input dropdown | Filtered to audio-capable inputs only |
| Transform | Scene → Scene Item cascading | Scene item shows “SourceName (ID: 123)” format |
| Filter Setting | Source → Filter cascading | Setting name entered manually (OBS internal key) |
| Transition Duration | None (affects current) | Shows current transition info when connected |
| Color Source | Color source dropdown | Filtered to color_source inputs only |
| Media Cursor | Media input dropdown | Filtered to ffmpeg_source/vlc_source only |
Dropdown Population:
- All dropdowns are populated from the OBS client cache.
- The Refresh button triggers a full data refresh from OBS.
- Placeholder text “(Connect to OBS first)” appears when disconnected.
- Cascading selections clear the child when the parent changes.
Editor Module Architecture
The editor module uses a section builder pattern for details panel customization:
FInhyeongOBSComponentCustomization
├── FOBSConnectionSectionBuilder
├── FOBSScenesSectionBuilder
├── FOBSSceneItemTransformsSectionBuilder
├── FOBSStudioModeSectionBuilder
├── FOBSTransitionsSectionBuilder
├── FOBSRecordingStreamingSectionBuilder
├── FOBSVirtualCamSectionBuilder
├── FOBSReplayBufferSectionBuilder
├── FOBSAdvancedOutputsSectionBuilder
├── FOBSAudioInputsSectionBuilder
├── FOBSMediaInputsSectionBuilder
├── FOBSInputSettingsSectionBuilder
├── FOBSFiltersSectionBuilder
├── FOBSScreenshotsSectionBuilder
├── FOBSWatchedScenesSectionBuilder
└── FOBSConfigSectionBuilder
FInhyeongOBSTriggerVolumeCustomization
├── FOBSTriggerShapeSectionBuilder
├── FOBSTriggerSettingsSectionBuilder
├── FOBSTriggerConditionsSectionBuilder
├── FOBSTriggerActionsSectionBuilder
└── FOBSTriggerTestSectionBuilder
Section Builder Base Classes
FOBSSectionBuilderBase: Base for OBS Component sections:
class FOBSSectionBuilderBase : public TSharedFromThis<FOBSSectionBuilderBase>
{
public:
void Initialize(const TSharedRef<FOBSSectionContext>& InContext);
virtual void BuildSection(IDetailCategoryBuilder& Category) = 0;
virtual FText GetSectionTitle() const = 0;
virtual bool IsInitiallyCollapsed() const { return false; }
virtual void BindToEvents() {}
virtual void UnbindFromEvents() {}
void RequestRefresh();
protected:
bool IsConnected() const;
UInhyeongOBSEditorSubsystem* GetSubsystem() const;
UInhyeongOBSWebSocketClient* GetClient() const;
TAttribute<bool> MakeEnabledWhenConnected() const;
};
FOBSTriggerVolumeSectionBuilderBase: Base for Trigger Volume sections:
class FOBSTriggerVolumeSectionBuilderBase : public TSharedFromThis<FOBSTriggerVolumeSectionBuilderBase>
{
public:
void Initialize(const TSharedRef<FOBSTriggerVolumeSectionContext>& InContext);
virtual void BuildSection(IDetailCategoryBuilder& Category) = 0;
virtual FText GetSectionTitle() const = 0;
protected:
AInhyeongOBSTriggerVolume* GetTriggerVolume() const;
// ... same helpers as FOBSSectionBuilderBase
};
Section Context Structs
FOBSSectionContext: Shared data for component sections:
struct FOBSSectionContext
{
UInhyeongOBSEditorSubsystem* Subsystem;
UInhyeongOBSWebSocketClient* Client;
TWeakObjectPtr<UInhyeongOBSComponent> Component;
IDetailLayoutBuilder* DetailBuilder;
TSharedPtr<bool> ValidityFlag; // Set false on destruction
bool IsValid() const;
bool IsConnected() const;
UInhyeongOBSOutputs* GetOutputs() const;
UInhyeongOBSScenes* GetScenes() const;
UInhyeongOBSAudio* GetAudio() const;
UInhyeongOBSInputSettings* GetInputSettings() const;
UInhyeongOBSMediaInputs* GetMediaInputs() const;
};
FOBSTriggerVolumeSectionContext: Shared data for trigger volume sections:
struct FOBSTriggerVolumeSectionContext
{
UInhyeongOBSEditorSubsystem* Subsystem;
UInhyeongOBSWebSocketClient* Client;
TWeakObjectPtr<AInhyeongOBSTriggerVolume> TriggerVolume;
IDetailLayoutBuilder* DetailBuilder;
TSharedPtr<bool> ValidityFlag;
bool IsValid() const;
bool IsConnected() const;
// ... handler accessors
};
Key Types
Enums:
EOBSConnectionState: Disconnected, Connecting, Authenticating, ConnectedEOBSOutputState: Starting, Started, Stopping, Stopped, Paused, Resumed, etc.EOBSMediaInputAction: None, Play, Pause, Stop, Restart, Next, PreviousEOBSMediaState: Unknown, None, Playing, Paused, Stopped, Buffering, Ended, Error, OpeningEOBSTriggerActionType: All supported trigger actionsEOBSTriggerShape: Box, SphereEOBSTriggerEvent: OnEnter, OnExit, BothEOBSRequestBatchExecutionType: SerialRealtime, SerialFrame, ParallelEOBSMonitorType: None, MonitorOnly, MonitorAndOutput
Structs:
FOBSScene: Scene name, UUID, indexFOBSSceneItem: Source info within a scene (includes lock state, blend mode)FOBSSceneWithItems: Scene with all its itemsFOBSInput: Input with volume/mute infoFOBSStreamStatus/FOBSRecordStatus: Output status with timecodeFOBSMediaInputStatus: Media state, duration, cursor positionFOBSTriggerAction: Action configuration for trigger volumesFOBSTriggerConditions: Condition configuration for triggersFOBSBatchRequest/FOBSBatchResult: Batch request/response dataFOBSTransition: Transition name, UUID, kind, configurable, fixed flagsFOBSSourceFilter: Filter name, kind, index, enabled state, settingsFOBSCurrentTransitionInfo: Full transition details including settingsFOBSSceneItemTransform: Position, scale, rotation, crop, bounds, source dimensionsEOBSBoundsType: None, Stretch, ScaleInner, ScaleOuter, ScaleToWidth, ScaleToHeight, MaxOnlyEOBSBlendMode: Normal, Additive, Subtract, Screen, Multiply, Lighten, DarkenFOBSScreenshotRequest: Screenshot capture parameters (source, format, size, quality, path)FOBSScreenshotResult: Capture result with base64 image dataFOBSScreenshotSavedResult: Save result with file path confirmationFOBSSceneTransitionOverride: Per-scene transition override (name, duration, bHasOverride)FOBSProfileParameter: Parameter value and default valueFOBSStreamServiceSettings: Stream destination configuration (server, key, auth)FOBSAudioTracks: Track 1 to 6 enable states with helper methodsFOBSSpecialInputs: Default audio device names (Desktop1/2, Mic1 to 4)FOBSOutput: Generic output info (name, kind, dimensions, active state, flags)FOBSOutputStatus: Generic output status (name, active, reconnecting, timecode, duration, congestion, bytes, frames)
Caching:
- Input settings are cached in
UInhyeongOBSInputSettingsafter fetching viaGetInputSettings(). - Use
GetCachedInputSettings()/GetCachedInputSettingsString()to access cached data. - Use
HasCachedSettings()to check if data is available. - Use
ClearCachedSettings()/ClearAllCachedSettings()to invalidate the cache.
Details Panel Customization
The plugin uses a modular section builder pattern for details panels:
FOBSSectionBuilderBase: Base class for OBS Component sectionsFOBSTriggerVolumeSectionBuilderBase: Base class for Trigger Volume sectionsFOBSDetailsPanelStyle: Shared style constants and widget builders
Each section (Connection, Scenes, Recording, etc.) is implemented as a separate builder class.
Identity Resolver (name → UUID rebind)
OBS keys scene items by a numeric SceneItemId that designers never see, and that id changes if the source is renamed mid-stream. Core/InhyeongOBSIdentityResolver.h (OBSIdentity::FindSceneItemByName / FindSceneItemByUuids + FOBSIdentityBindingCache) resolves a source by name, remembers its scene/source UUIDs, and rebinds by UUID on a later by-name miss, so a trigger that targets a source by name keeps working after a rename. It is wired into the Trigger Volume’s “Set Source Visibility” action. The cache is runtime-only and resets on scene-collection swaps.
Authentication
The plugin implements SHA256 authentication internally without platform dependencies. See InhyeongOBSAuth.h for the implementation.
Request Batching
Use FOBSRequestBatchBuilder for efficient batch requests:
FOBSRequestBatchBuilder::Create(Client)
.SetCurrentProgramScene("Scene1")
.StartRecord()
.SetInputMute("Mic", false)
.HaltOnFailure(true)
.SetExecutionType(EOBSRequestBatchExecutionType::SerialRealtime)
.ExecuteWithCallback([](const FOBSBatchResult& Result) {
// Handle results
});
Available batch methods:
- Scene:
GetSceneList(),SetCurrentProgramScene(),GetCurrentProgramScene(),CreateScene(),RemoveScene(),SetSceneName(),GetSceneSceneTransitionOverride(),SetSceneSceneTransitionOverride(),SetSceneItemEnabled(),CreateSceneItem(),RemoveSceneItem(),DuplicateSceneItem(),GetSceneItemLocked(),SetSceneItemLocked(),GetSceneItemIndex(),SetSceneItemIndex(),GetSceneItemBlendMode(),SetSceneItemBlendMode() - Config:
GetSceneCollectionList(),SetCurrentSceneCollection(),CreateSceneCollection(),GetProfileList(),SetCurrentProfile(),CreateProfile(),RemoveProfile(),GetProfileParameter(),SetProfileParameter(),GetVideoSettings(),SetVideoSettings(),SetBaseResolution(),SetOutputResolution(),SetFPS() - Stream:
StartStream(),StopStream(),ToggleStream(),GetStreamStatus() - Record:
StartRecord(),StopRecord(),ToggleRecord(),PauseRecord(),ResumeRecord(),GetRecordStatus() - VirtualCam:
StartVirtualCam(),StopVirtualCam(),ToggleVirtualCam(),GetVirtualCamStatus() - ReplayBuffer:
StartReplayBuffer(),StopReplayBuffer(),ToggleReplayBuffer(),SaveReplayBuffer(),GetReplayBufferStatus() - Record Directory:
GetRecordDirectory(),SetRecordDirectory() - Record Split/Chapters:
SplitRecordFile(),CreateRecordChapter() - Generic Outputs:
GetOutputList(),GetOutputStatus(),GetOutputSettings(),SetOutputSettings(),StartOutput(),StopOutput(),ToggleOutput() - Stream Captions:
SendStreamCaption() - Audio:
GetInputList(),SetInputMute(),ToggleInputMute(),SetInputVolume(),GetInputKindList(),CreateInput(),RemoveInput(),RemoveInputByUuid(),SetInputName(),GetInputAudioBalance(),GetInputAudioBalanceByUuid(),SetInputAudioBalance(),SetInputAudioBalanceByUuid(),GetInputAudioSyncOffset(),GetInputAudioSyncOffsetByUuid(),SetInputAudioSyncOffset(),SetInputAudioSyncOffsetByUuid(),GetInputAudioMonitorType(),GetInputAudioMonitorTypeByUuid(),SetInputAudioMonitorType(),SetInputAudioMonitorTypeByUuid(),GetInputAudioTracks(),GetInputAudioTracksByUuid(),SetInputAudioTracks(),SetInputAudioTracksByUuid(),GetSpecialInputs() - Input Settings:
GetInputSettings(),SetInputSettings(),GetInputDefaultSettings(),SetTextSourceText(),SetBrowserSourceUrl(),SetImageSourceFile(),SetMediaSourceFile(),SetColorSourceColor() - Media:
TriggerMediaInputAction(),GetMediaInputStatus(),SetMediaInputCursor(),OffsetMediaInputCursor() - StudioMode:
GetStudioModeEnabled(),SetStudioModeEnabled(),GetCurrentPreviewScene(),SetCurrentPreviewScene(),SetCurrentPreviewSceneByUuid(),TriggerStudioModeTransition() - Transitions:
GetSceneTransitionList(),GetCurrentSceneTransition(),SetCurrentSceneTransition(),SetCurrentSceneTransitionDuration(),SetCurrentSceneTransitionSettings(),GetCurrentSceneTransitionCursor() - Screenshots:
GetSourceScreenshot(),GetSourceScreenshotByUuid(),GetSourceScreenshotWithOptions(),SaveSourceScreenshot(),SaveSourceScreenshotByUuid(),SaveSourceScreenshotWithOptions() - Filters:
GetSourceFilterKindList(),GetSourceFilterList(),GetSourceFilterListByUuid(),GetSourceFilter(),GetSourceFilterDefaultSettings(),CreateSourceFilter(),RemoveSourceFilter(),SetSourceFilterName(),SetSourceFilterIndex(),SetSourceFilterEnabled(),SetSourceFilterSettings()
Internal Organization:
The batch builder implementation is split across multiple files for maintainability:
| File | Contents |
|---|---|
InhyeongOBSRequestBatch.cpp | Core, configuration, execution |
InhyeongOBSRequestBatch_Scenes.cpp | Scene and scene item requests |
InhyeongOBSRequestBatch_Outputs.cpp | Stream, record, virtual cam, replay buffer |
InhyeongOBSRequestBatch_Audio.cpp | Audio, media inputs, input settings |
InhyeongOBSRequestBatch_Filters.cpp | Source filter management |
InhyeongOBSRequestBatch_StudioMode.cpp | Studio mode and transitions |
InhyeongOBSRequestBatch_Config.cpp | Screenshots, profiles, scene collections, video settings |
Adding New Features
- Add types/delegates to
InhyeongOBSTypes.h. - Implement in the appropriate handler (
Outputs,Scenes,Inputs,MediaInputs). - Add convenience methods to
Client,Subsystem, andComponentif needed. - Handle events in
ProcessOBSEvent()in the client. - Add UI in the appropriate section builder.
Adding New Editor Sections
- Create a new section builder class inheriting from
FOBSSectionBuilderBaseorFOBSTriggerVolumeSectionBuilderBase. - Implement
BuildSection(),GetSectionTitle(), and optionallyIsInitiallyCollapsed(). - Override
BindToEvents()andUnbindFromEvents()if the section needs live updates. - Add the builder to the customization class’s
CreateSectionBuilders()method. - Use
FOBSDetailsPanelStylefor consistent styling.