架构与开发者参考
本页面是面向开发者的”底层原理”参考文档,供需要扩展插件的开发者使用。内容涵盖模块结构、基于处理器的客户端、Sequencer 集成、编辑器细节面板系统、关键类型,以及新增功能的实现模式。
如需查看原生 C++ 委托的完整列表(即带有 Native 后缀、支持 lambda 绑定的事件),请参阅 原生委托。
模块结构
该插件由三个模块组成:
| 模块 | 类型 | 用途 |
|---|---|---|
InhyeongOBSWebSocket | Runtime | 核心功能、Subsystem、组件、Sequencer 集成 |
InhyeongOBSWebSocketEditor | Editor | 细节面板定制、Editor Subsystem、Sequencer 轨道编辑器 |
InhyeongOBSWebSocketTakeRecorder | Editor | Take Recorder 同步(在 PostEngineInit 时加载,仅当 Takes plugin 启用时) |
Take Recorder 同步配置
设置存储于 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
工具类
| 类 | 位置 | 用途 |
|---|---|---|
FOBSRequestBatchBuilder | Utilities/ | 流式构建批处理请求 |
FOBSJsonBuilder | Utilities/ | 流式构建 JSON 对象 |
请求类型常量
所有 OBS WebSocket 请求类型与字段名均集中定义于 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"
这样可以避免拼写错误,也便于管理协议升级。
JSON 构建工具
FOBSJsonBuilder 为 OBS 请求提供流式 JSON 构建能力:
#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();
可用方法:
| 方法 | 说明 |
|---|---|
Add(Key, Value) | 添加 string、int32、int64、float、double、bool 或 JSON 对象 |
AddIfNotEmpty(Key, String) | 仅在字符串非空时添加 |
AddIfPositive(Key, Number) | 仅在数值 > 0 时添加 |
AddIfInRange(Key, Value, Min, Max) | 仅在值处于范围内时添加 |
Build() | 返回构建完成的 TSharedPtr<FJsonObject> |
HasFields() | 检查是否已添加任何字段 |
处理器架构
WebSocket 客户端采用模块化处理器进行组织:
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)
通过以下方式访问各处理器:
Client->GetOutputs()
Client->GetScenes()
Client->GetAudio()
Client->GetInputSettings()
Client->GetMediaInputs()
Client->GetStudioMode()
Client->GetTransitions()
Client->GetFilters()
Client->GetScreenshots()
Client->GetConfig()
Client->GetGeneral()
Sequencer 架构
Sequencer 集成遵循 Unreal 的 movie scene 模式:
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
关键类:
| 类 | 用途 |
|---|---|
FOBSSequencerActionRegistry | 包含 40 余个动作及其元数据的静态注册表 |
FOBSSequencerActionQueue | 单例队列,具备 33ms 节流(约 30fps)、去重及批处理优化(每批最多 48 个动作) |
FOBSOutputPreAnimatedState | 在播放前捕获输出状态以便恢复 |
FOBSSequencerActionExecutor | 将动作路由到正确的 OBS 客户端(Editor Subsystem 或 Game Subsystem) |
新增 Sequencer 动作
- 在
InhyeongOBSSequencerTypes.h的EOBSSequencerAction中添加枚举值。 - 在
InhyeongOBSSequencerTypes.cpp中添加REGISTER_ACTION块。 - 在
OBSSequencerActionExecutor.cpp中添加执行分支。 - 如需使用批处理,在
OBSSequencerActionQueue.cpp中添加批处理请求构建逻辑。
新增动画前状态支持
对于会修改 OBS 设置的 State 类型动作,需实现状态恢复:
- 在
Sequencer/EventTriggersTrack/中创建FOBS[Handler]PreAnimatedState。 - 继承自
IPersistentEvaluationData。 - 使用处理器的缓存值(不得使用异步!)实现
CaptureFrom()。 - 实现带有 150ms 防抖的
RestoreTo()。 - 更新
MovieSceneOBSTemplate::SupportsPreAnimatedState()以包含对应分类。 - 在
MovieSceneOBSTemplate.cpp中添加 Setup/TearDown 块。
动画前状态模式:
// 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);
}
新增 Continuous State Track
每个 Continuous State Track 需在 Sequencer/ContinuousStateTrack/[Handler]/ 下创建 4 个文件:
| 文件 | 用途 |
|---|---|
OBS[State]PreAnimatedState.h/.cpp | 捕获/恢复,幂等的 ApplyState() |
MovieSceneOBS[State]Section.h/.cpp | 简单属性(bool/enum),无通道 |
MovieSceneOBS[State]Track.h/.cpp | 包含目标标识的容器 |
MovieSceneOBS[State]Template.h/.cpp | Setup 捕获状态,Evaluate 应用状态,TearDown 恢复状态 |
关键实现规则:
- PreAnimatedState 继承自
IPersistentEvaluationData(不得使用 USTRUCT)。 ApplyState()必须是幂等的(发送前检查bStateIsApplied)。Track::CreateTemplateForSection使用直接返回(不得使用*new)。- Section 不含
FMovieSceneFloatChannel,仅有简单属性。 - Section 构造函数将
EvalOptions.CompletionMode设为RestoreState。 - Template 使用
GetOrAddTrackData<>()/FindTrackData<>()管理持久化数据。
新增 Keyframeable Track
每个可关键帧属性需在 Sequencer/KeyframeableTrack/[Category]/ 下创建 4 个文件:
| 文件 | 用途 |
|---|---|
OBS[Property]PreAnimatedState.h/.cpp | 捕获/恢复原始 OBS 状态 |
MovieSceneOBS[Property]Section.h/.cpp | 存储 FMovieSceneFloatChannel 关键帧 |
MovieSceneOBS[Property]Track.h/.cpp | 包含目标标识的容器 |
MovieSceneOBS[Property]Template.h/.cpp | 持续求值,增量阈值发送 |
关键实现规则:
- PreAnimatedState 继承自
IPersistentEvaluationData(不得使用 USTRUCT)。 Track::CreateTemplateForSection使用直接返回(不得使用*new)。- Template 使用
GetOrAddSectionData<>()/FindSectionData<>()管理持久化数据。 Setup()通过FOBSSequencerActionExecutor::GetClientForContext()将客户端缓存至 PreAnimatedState。Evaluate()从State->CachedClient.Get()获取客户端(不使用 Player 上下文,该上下文在Evaluate中不可用)。Evaluate()通过FOBSSequencerActionQueue::Get().EnqueueAction()路由,以实现节流/批处理。- 增量阈值检查在入队之前进行,以避免创建不必要的动作。
Sequencer 编辑器 UI
所有轨道均提供完善的编辑器体验:
轨道大纲:
- 连接状态指示器(绿/红状态指示点)
- 快速”+“按钮,可在播放头处添加分段
- 通过
FMovieSceneFloatChannel自动集成曲线编辑器
细节面板定制:
| 轨道 | 目标选择 | 备注 |
|---|---|---|
| Volume / Balance | 音频输入下拉菜单 | 仅筛选支持音频的输入 |
| Transform | 场景 → 场景项目级联选择 | 场景项目显示”SourceName (ID: 123)“格式 |
| Filter Setting | 来源 → 滤镜级联选择 | 设置名称手动输入(OBS 内部键名) |
| Transition Duration | 无(影响当前转场) | 已连接时显示当前转场信息 |
| Color Source | 色源下拉菜单 | 仅筛选 color_source 输入 |
| Media Cursor | 媒体输入下拉菜单 | 仅筛选 ffmpeg_source/vlc_source |
下拉菜单填充:
- 所有下拉菜单数据均来自 OBS 客户端缓存。
- 刷新按钮会触发从 OBS 全量刷新数据。
- 断开连接时显示占位文本”(Connect to OBS first)”。
- 级联选择在父级变更时会清空子级选项。
编辑器模块架构
编辑器模块采用分段构建器模式实现细节面板定制:
FInhyeongOBSComponentCustomization
├── FOBSConnectionSectionBuilder
├── FOBSScenesSectionBuilder
├── FOBSSceneItemTransformsSectionBuilder
├── FOBSStudioModeSectionBuilder
├── FOBSTransitionsSectionBuilder
├── FOBSRecordingStreamingSectionBuilder
├── FOBSVirtualCamSectionBuilder
├── FOBSReplayBufferSectionBuilder
├── FOBSAdvancedOutputsSectionBuilder
├── FOBSAudioInputsSectionBuilder
├── FOBSMediaInputsSectionBuilder
├── FOBSInputSettingsSectionBuilder
├── FOBSFiltersSectionBuilder
├── FOBSScreenshotsSectionBuilder
├── FOBSWatchedScenesSectionBuilder
└── FOBSConfigSectionBuilder
FInhyeongOBSTriggerVolumeCustomization
├── FOBSTriggerShapeSectionBuilder
├── FOBSTriggerSettingsSectionBuilder
├── FOBSTriggerConditionsSectionBuilder
├── FOBSTriggerActionsSectionBuilder
└── FOBSTriggerTestSectionBuilder
分段构建器基类
FOBSSectionBuilderBase:OBS Component 分段的基类:
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:Trigger Volume 分段的基类:
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
};
分段上下文结构体
FOBSSectionContext:组件分段的共享数据:
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:Trigger Volume 分段的共享数据:
struct FOBSTriggerVolumeSectionContext
{
UInhyeongOBSEditorSubsystem* Subsystem;
UInhyeongOBSWebSocketClient* Client;
TWeakObjectPtr<AInhyeongOBSTriggerVolume> TriggerVolume;
IDetailLayoutBuilder* DetailBuilder;
TSharedPtr<bool> ValidityFlag;
bool IsValid() const;
bool IsConnected() const;
// ... handler accessors
};
关键类型
枚举:
EOBSConnectionState:Disconnected、Connecting、Authenticating、ConnectedEOBSOutputState:Starting、Started、Stopping、Stopped、Paused、Resumed 等EOBSMediaInputAction:None、Play、Pause、Stop、Restart、Next、PreviousEOBSMediaState:Unknown、None、Playing、Paused、Stopped、Buffering、Ended、Error、OpeningEOBSTriggerActionType:所有受支持的触发动作EOBSTriggerShape:Box、SphereEOBSTriggerEvent:OnEnter、OnExit、BothEOBSRequestBatchExecutionType:SerialRealtime、SerialFrame、ParallelEOBSMonitorType:None、MonitorOnly、MonitorAndOutput
结构体:
FOBSScene:场景名称、UUID、索引FOBSSceneItem:场景内的来源信息(包含锁定状态、混合模式)FOBSSceneWithItems:场景及其所有项目FOBSInput:包含音量/静音信息的输入FOBSStreamStatus/FOBSRecordStatus:带时间码的输出状态FOBSMediaInputStatus:媒体状态、时长、游标位置FOBSTriggerAction:Trigger Volume 的动作配置FOBSTriggerConditions:触发器的条件配置FOBSBatchRequest/FOBSBatchResult:批处理请求/响应数据FOBSTransition:转场名称、UUID、类型、可配置标志、固定标志FOBSSourceFilter:滤镜名称、类型、索引、启用状态、设置FOBSCurrentTransitionInfo:包含设置在内的完整转场详情FOBSSceneItemTransform:位置、缩放、旋转、裁剪、边界、来源尺寸EOBSBoundsType:None、Stretch、ScaleInner、ScaleOuter、ScaleToWidth、ScaleToHeight、MaxOnlyEOBSBlendMode:Normal、Additive、Subtract、Screen、Multiply、Lighten、DarkenFOBSScreenshotRequest:截图捕获参数(来源、格式、尺寸、质量、路径)FOBSScreenshotResult:包含 base64 图像数据的捕获结果FOBSScreenshotSavedResult:包含文件路径确认信息的保存结果FOBSSceneTransitionOverride:每场景转场覆盖(名称、时长、bHasOverride)FOBSProfileParameter:参数值与默认值FOBSStreamServiceSettings:推流目标配置(服务器、推流密钥、身份验证)FOBSAudioTracks:轨道 1 至 6 的启用状态及辅助方法FOBSSpecialInputs:默认音频设备名称(Desktop1/2、Mic1 至 4)FOBSOutput:通用输出信息(名称、类型、尺寸、活动状态、标志)FOBSOutputStatus:通用输出状态(名称、活动状态、重连状态、时间码、时长、拥塞、字节数、帧数)
缓存:
- 输入设置在通过
GetInputSettings()获取后缓存于UInhyeongOBSInputSettings中。 - 使用
GetCachedInputSettings()/GetCachedInputSettingsString()访问已缓存数据。 - 使用
HasCachedSettings()检查数据是否可用。 - 使用
ClearCachedSettings()/ClearAllCachedSettings()使缓存失效。
细节面板定制
该插件采用模块化分段构建器模式实现细节面板:
FOBSSectionBuilderBase:OBS Component 分段的基类FOBSTriggerVolumeSectionBuilderBase:Trigger Volume 分段的基类FOBSDetailsPanelStyle:共享样式常量与控件构建器
每个分段(连接、场景、录制等)均作为独立的构建器类实现。
身份解析器(名称 → UUID 重绑定)
OBS 使用数字 SceneItemId 作为场景项目的键,设计师通常不会接触该 ID,且该 ID 在来源被改名后会发生变化。Core/InhyeongOBSIdentityResolver.h(OBSIdentity::FindSceneItemByName / FindSceneItemByUuids 以及 FOBSIdentityBindingCache)通过名称解析来源,记录其场景/来源 UUID,并在后续按名称查找失败时通过 UUID 进行重绑定。这样,以名称为目标的触发器在来源改名后仍可正常工作。该功能已集成至 Trigger Volume 的”Set Source Visibility”动作中。缓存仅在运行时有效,在场景集合切换时会重置。
身份验证
该插件在内部实现了 SHA256 身份验证,无需平台依赖。实现细节请参阅 InhyeongOBSAuth.h。
请求批处理
使用 FOBSRequestBatchBuilder 进行高效批处理请求:
FOBSRequestBatchBuilder::Create(Client)
.SetCurrentProgramScene("Scene1")
.StartRecord()
.SetInputMute("Mic", false)
.HaltOnFailure(true)
.SetExecutionType(EOBSRequestBatchExecutionType::SerialRealtime)
.ExecuteWithCallback([](const FOBSBatchResult& Result) {
// Handle results
});
可用批处理方法:
- 场景:
GetSceneList()、SetCurrentProgramScene()、GetCurrentProgramScene()、CreateScene()、RemoveScene()、SetSceneName()、GetSceneSceneTransitionOverride()、SetSceneSceneTransitionOverride()、SetSceneItemEnabled()、CreateSceneItem()、RemoveSceneItem()、DuplicateSceneItem()、GetSceneItemLocked()、SetSceneItemLocked()、GetSceneItemIndex()、SetSceneItemIndex()、GetSceneItemBlendMode()、SetSceneItemBlendMode() - 配置文件:
GetSceneCollectionList()、SetCurrentSceneCollection()、CreateSceneCollection()、GetProfileList()、SetCurrentProfile()、CreateProfile()、RemoveProfile()、GetProfileParameter()、SetProfileParameter()、GetVideoSettings()、SetVideoSettings()、SetBaseResolution()、SetOutputResolution()、SetFPS() - 推流:
StartStream()、StopStream()、ToggleStream()、GetStreamStatus() - 录制:
StartRecord()、StopRecord()、ToggleRecord()、PauseRecord()、ResumeRecord()、GetRecordStatus() - Virtual Camera:
StartVirtualCam()、StopVirtualCam()、ToggleVirtualCam()、GetVirtualCamStatus() - Replay Buffer:
StartReplayBuffer()、StopReplayBuffer()、ToggleReplayBuffer()、SaveReplayBuffer()、GetReplayBufferStatus() - 录制目录:
GetRecordDirectory()、SetRecordDirectory() - 录制分割/章节:
SplitRecordFile()、CreateRecordChapter() - 通用输出:
GetOutputList()、GetOutputStatus()、GetOutputSettings()、SetOutputSettings()、StartOutput()、StopOutput()、ToggleOutput() - 推流字幕:
SendStreamCaption() - 音频:
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() - 输入设置:
GetInputSettings()、SetInputSettings()、GetInputDefaultSettings()、SetTextSourceText()、SetBrowserSourceUrl()、SetImageSourceFile()、SetMediaSourceFile()、SetColorSourceColor() - 媒体:
TriggerMediaInputAction()、GetMediaInputStatus()、SetMediaInputCursor()、OffsetMediaInputCursor() - Studio Mode:
GetStudioModeEnabled()、SetStudioModeEnabled()、GetCurrentPreviewScene()、SetCurrentPreviewScene()、SetCurrentPreviewSceneByUuid()、TriggerStudioModeTransition() - 转场:
GetSceneTransitionList()、GetCurrentSceneTransition()、SetCurrentSceneTransition()、SetCurrentSceneTransitionDuration()、SetCurrentSceneTransitionSettings()、GetCurrentSceneTransitionCursor() - 截图:
GetSourceScreenshot()、GetSourceScreenshotByUuid()、GetSourceScreenshotWithOptions()、SaveSourceScreenshot()、SaveSourceScreenshotByUuid()、SaveSourceScreenshotWithOptions() - 滤镜:
GetSourceFilterKindList()、GetSourceFilterList()、GetSourceFilterListByUuid()、GetSourceFilter()、GetSourceFilterDefaultSettings()、CreateSourceFilter()、RemoveSourceFilter()、SetSourceFilterName()、SetSourceFilterIndex()、SetSourceFilterEnabled()、SetSourceFilterSettings()
内部组织:
批处理构建器的实现为便于维护拆分至多个文件:
| 文件 | 内容 |
|---|---|
InhyeongOBSRequestBatch.cpp | 核心逻辑、配置、执行 |
InhyeongOBSRequestBatch_Scenes.cpp | 场景与场景项目请求 |
InhyeongOBSRequestBatch_Outputs.cpp | 推流、录制、虚拟摄像头、Replay Buffer |
InhyeongOBSRequestBatch_Audio.cpp | 音频、媒体输入、输入设置 |
InhyeongOBSRequestBatch_Filters.cpp | 来源滤镜管理 |
InhyeongOBSRequestBatch_StudioMode.cpp | Studio Mode 与转场 |
InhyeongOBSRequestBatch_Config.cpp | 截图、配置文件、场景集合、视频设置 |
新增功能
- 在
InhyeongOBSTypes.h中添加类型/委托。 - 在相应处理器(
Outputs、Scenes、Inputs、MediaInputs)中实现功能。 - 如有需要,为
Client、Subsystem和Component添加便捷方法。 - 在客户端的
ProcessOBSEvent()中处理事件。 - 在相应的分段构建器中添加 UI。
新增编辑器分段
- 创建继承自
FOBSSectionBuilderBase或FOBSTriggerVolumeSectionBuilderBase的新分段构建器类。 - 实现
BuildSection()、GetSectionTitle(),以及可选的IsInitiallyCollapsed()。 - 如果分段需要实时更新,覆写
BindToEvents()和UnbindFromEvents()。 - 将构建器添加至定制类的
CreateSectionBuilders()方法中。 - 使用
FOBSDetailsPanelStyle保持样式一致。