What Problem Does This Solve?
Understanding LCK’s architecture helps you:- Debug issues by knowing which subsystem handles what
- Extend the SDK with custom encoders or audio sources
- Optimize performance by understanding the data flow
- Build custom UI without breaking core functionality
When to Read This
Read this when:- Integrating LCK for the first time
- Building custom recording UI
- Creating custom audio sources (FMOD, Wwise)
- Debugging recording or encoding issues
- Contributing to LCK development
High-Level Overview
LCK is organized into modular runtime modules that load in specific phases:Module Dependency Map
This diagram shows which modules depend on which, and whether they are required or optional.Module Classification
Load Order
Modules load in three phases, in this order:-
EarliestPossible— Before engine initialization. OnlyLCKVulkanloads here (Android only). This phase exists because Vulkan interop must be established before the RHI initializes. -
PostDefault— After engine init, before game modules. Core infrastructure loads here:LCKCore,LCKAudio, and all platform-specific encoder modules. These must be available before any game code tries to use the recording API. -
Default— Standard game module loading. All high-level and optional modules load here:LCKTablet,LCKUI,LCKStreaming, and all audio plugins. By this point, core infrastructure is guaranteed to be available.
Platform-specific modules (
LCKVulkan, LCKWindowsEncoder, LCKAndroidEncoder, LCKAndroidGallery) are auto-loaded by the engine based on the target platform. You never need to add them to your .Build.cs.Runtime Discovery
Optional modules register themselves via Unreal’sIModularFeatures system at startup. Core modules discover them at runtime without compile-time coupling:
- Audio sources register as
ILCKAudioSourcemodular features - Encoder factories register as
ILCKEncoderFactorymodular features - Streaming backends register as
ILCKStreamingFeaturemodular features - Packet sinks are passed directly to encoders via
ILCKEncoder::AddPacketSink()
Platform Coverage Matrix
Linux support is limited to core, audio, UI, and Vivox modules. Encoding and streaming require Windows or Android.
Subsystem Hierarchy
LCK uses Unreal’s subsystem architecture for lifetime management:ULCKRecorderSubsystem
Type:UTickableWorldSubsystem (ticks every frame)Module: LCKCore
Purpose: Low-level recording control, frame capture, encoder lifecycle
ULCKService instead.
ULCKSubsystem
Type:UWorldSubsystemModule: LCKTablet
Purpose: Provides access to
ULCKService
ULCKTelemetrySubsystem
Type:UGameInstanceSubsystemModule: LCKCore
Purpose: Analytics and usage tracking
Encoder Architecture
Encoders implement theILCKEncoder interface and are created via modular features:
ILCKPacketSink implementations (for RTMP streaming or other transports). Use SetRecordToDisk(false) for stream-only mode.
Platform Implementations
Windows Encoder
- Uses
IMFSinkWriterfor muxing - Uses
IMFTransformfor H.264 encoding - Triple-buffered texture pool to avoid GPU stalls
- Direct3D 11 texture interop
Android Encoder
- Uses
AMediaCodecfor H.264/AAC encoding - Uses
AMediaMuxerfor MP4 container - Vulkan texture export via EGL
- Hardware-accelerated on Quest devices
Encoder Factory
Encoders are discovered and created via Unreal’s modular features system:Audio Architecture
Audio sources also use modular features for extensibility:In v1.0,
FDelegateRenderAudio is the multicast parent delegate. FOnRenderAudioDelegate is a typedef for its inner FDelegate type. The delegate now includes SampleRate as a third parameter.Audio Mixing
Multiple audio sources are combined viaFLCKAudioMix:
Data Flow
SetRecordToDisk(false) on the encoder.
Triple-Buffered Texture Pool
Encoder uses triple-buffering to prevent GPU stalls:- GPU is rendering to texture 0
- Encoder is reading from texture 1
- Texture 2 is free for next frame
Thread Safety
LCK uses standard Unreal thread-safety patterns:Modular Feature Discovery
Encoders and audio sources are discovered at runtime:Log Categories
Enable verbose logging for debugging:Key Takeaways
Modular design — Core functionality (encoding, audio) is separate from UI (tablet)
Subsystem-based — Uses Unreal’s subsystem architecture for clean lifetime management
Platform abstraction — Encoder interface allows platform-specific implementations
Extensible audio — Audio sources register via modular features
Thread-safe — Encoding happens on background thread, careful with audio callbacks
Related
- Module Loading — Module hierarchy and dependencies
- Types & Enums — Data structures used throughout
- Encoder Interface — Platform-specific encoding details
- Audio Source Interface — Custom audio source implementation