Overview
LCK v1.0 is the first public release of the LIV Camera Kit SDK. This release introduces live streaming to YouTube, Twitch, and custom RTMP endpoints via the newLCKStreaming plugin, adds a Getting Started wizard for first-time setup, and improves audio quality with per-source sample rate handling. Encoding stability on Android has been significantly improved.Highlights
- Live Streaming — Stream directly to YouTube, Twitch, or custom RTMP endpoints from VR via the new
LCKStreamingplugin - Modular Streaming Architecture —
ILCKStreamingFeaturemodular feature interface for streaming integration, discoverable viaIModularFeatures - Getting Started Wizard — Editor wizard guides first-time setup with audio plugin selection and configuration
- Improved Audio Quality — Per-source sample rate handling for correct resampling across all audio plugins
- Quest 2 Optimizations — Capped HD profile to 30 fps / 8 Mbps for reliable recording on Quest 2
New Features
LCK Core SDK
| Feature | Description |
|---|---|
ILCKStreamingFeature interface | Modular feature interface for streaming providers with login, streaming, and lifecycle APIs |
| Getting Started wizard | Editor wizard with step-by-step setup and audio plugin configuration |
| Editor menu | LCK menu in the editor toolbar for quick access to settings and about |
| SDK version check | Automatic version check on editor startup with update notification |
| Per-source audio resampling | Audio mixer resamples each source independently using reported sample rate |
AcquireEncoder / ReleaseEncoder | Reference-counted encoder access — multiple consumers (recording, streaming) can share the encoder |
IsEncoderActive() | Query whether the encoder is held by any consumer |
| Quest 2 HD profile cap | Caps HD recording to 30 fps and 8 Mbps on Quest 2 |
LCKStreaming (New Plugin)
| Feature | Description |
|---|---|
ULCKStreamingSubsystem | Game instance subsystem for full streaming lifecycle (login, stream, stop) |
| Device login/pairing | Device pairing flow with code display, polling, and expiry handling |
| YouTube / Twitch / Manual RTMP | Stream to YouTube (with broadcast creation), Twitch (with ingest lookup), or custom RTMP URLs |
| RTMPS by default | YouTube and Twitch streams use rtmps:// for encrypted transport |
| Per-platform bitrate presets | Framerate-aware bitrate presets for 720p/1080p streaming per platform |
IsRtmpAvailable() | Runtime check for RTMP native library availability |
| Conditional RTMP packaging | RTMP libraries only packaged when bEnableStreaming=true in DefaultGame.ini |
| App lifecycle handling | Stop streaming on app backgrounding, re-validate auth on resume (Quest) |
| Auto-logout on 401/403 | Expired auth tokens trigger automatic logout with OnLoggedOut |
| User-friendly error messages | Technical errors replaced with user-facing strings |
LCKTablet
| Feature | Description |
|---|---|
| Streaming integration | StartLogin(), CancelLogin(), Logout(), StartStreaming(), StopStreaming(), IsStreaming(), LaunchHub(), IsHubInstalled() on ULCKService |
| Streaming delegates | OnStreamingPairingCode, OnStreamingAuthenticated, OnStreamingStarted, OnStreamingStopped, OnStreamingError, OnStreamingLoggedOut, OnStreamingConfigChanged |
EnsureMicPermission | Async mic permission request with callback before recording/streaming |
FOnNotificationShown | Delegate for notification display state changes |
| Streaming UI elements | GoLive button, Stream button, Live indicator, LIV Hub button, streaming timer |
LCKUI
| Feature | Description |
|---|---|
| GoLive button | 3D button with long-press to start/stop streaming |
| Live indicator | Animated live status indicator with horizontal/vertical support |
| Stream button | Streaming state toggle with disabled states |
| LIV Hub button | Button to launch LIV Hub companion app |
| Screen label | Base class for text labels on 3D screens |
| Long press support | BaseButton long-press functionality with animation lock |
ELCKStreamingState | Streaming state enum: Idle, Pairing, Paired, Streaming, Error |
Audio Plugins
| Plugin | Changes |
|---|---|
| LCKFMOD | Pass sample rate through audio delegate for correct resampling |
| LCKOboe | Pass sample rate, add idempotency guard to StartCapture |
| LCKUnrealAudio | Pass sample rate, add idempotency guards, fix mic capture flag reset |
| LCKWwise | Pass sample rate through audio delegate |
| LCKVivox | Pass sample rate through audio delegate |
Bug Fixes
| Fix | Platform | Description |
|---|---|---|
| Crash when stopping a stream | Android | Fixed multiple crash scenarios when stopping streaming or recording on Android |
| Encoder stability | All | Multiple crash, deadlock, and resource leak fixes in the encoding pipeline |
| Mic capture flag not resetting | Android | bIsMicrophoneCapturing now correctly resets on StopCapture in UnrealAudio source |
| Mic not restarting after failure | All | SetMicrophoneEnabled(true) now retries capture after a previous failed attempt |
| Encoder overload on Quest 2 | Android | HD profile capped to 30 fps / 8 Mbps to prevent encoder overload on Quest 2 |
Breaking Changes
-
TSharedPtr→TSharedPtr<..., ESPMode::ThreadSafe>— All encoder and module shared pointers changed to thread-safe mode. Code holdingTSharedPtr<ILCKEncoder>orTSharedPtr<ILCKEncoderFactory>must addESPMode::ThreadSafe. -
FDelegateRenderAudiosignature changed — Audio delegate gained aSampleRateparameter. Code binding toOnAudioDataDelegatemust update the callback signature. -
FOnRecordStateChage→FOnRecordStateChange— Typo fix in delegate name. -
LCKService::StartRecording()return type changed — Changed fromvoidtobooland madeBlueprintCallable. -
ULCKNotificationController::WriteLine()removed — UseShowNotification()instead. -
Telemetry structs simplified —
FLCKGeoLocation,FLCKMetaData,FLCKTelemetryData, andFLCKTelemetryPayloadwere removed fromLCKTelemetry.h.SendTelemetry(FLCKTelemetryEvent)andGetCurrentTrackingId()still work as before. -
LCKCore
Build.csdependency changes —HTTPmodule removed from public dependencies.Json,JsonUtilitiesadded as public.ToolMenusadded for editor. If your module depended onHTTPbeing transitively available through LCKCore, add it to your ownBuild.cs.
Migration Guide (v0.9.2 → v1.0)
-
Update shared pointer types — If you hold
TSharedPtr<ILCKEncoder>orTSharedPtr<ILCKEncoderFactory>, addESPMode::ThreadSafeas the second template parameter. -
Update audio delegate bindings —
OnAudioDataDelegatenow has 4 parameters (addedint32 SampleRatebetweenChannelsandSourceChannel). Update your callback signatures. -
Update
FOnRecordStateChage→FOnRecordStateChange— Fix the typo in any delegate bindings. -
Update
StartRecording()callers — Now returnsbool. Update any code that called it asvoid. -
Replace
WriteLine()calls —ULCKNotificationController::WriteLine()was removed. UseShowNotification()instead. -
Check telemetry type usage — If you used
FLCKGeoLocation,FLCKMetaData,FLCKTelemetryData, orFLCKTelemetryPayload, these structs were removed. UseFLCKTelemetryEventdirectly. -
Add
HTTPmodule if needed —HTTPwas removed from LCKCore’s public dependencies. If your module relied on it transitively, add"HTTP"to your ownBuild.cs. -
Add
LCKStreamingplugin dependency — If your project uses streaming, add theLCKStreamingplugin to your.uprojector.upluginfile. -
Enable streaming in config — Set
bEnableStreaming=trueinDefaultGame.iniunder[/Script/LCKCore.LCKDeveloperSettings]to package RTMP libraries.
Platform Support
| Platform | Status |
|---|---|
| Meta Quest (Android) | Full support — recording, streaming, gallery save |
| Windows (PCVR) | Full support — recording, streaming |
| Linux | Build support (listed in SupportedTargetPlatforms), not actively tested |
Highlights
- PCVR Support — LCK is a single implementation for PCVR and Meta Quest Standalone
- Microphone Mute Control — New
SetMicrophoneEnabled()API for runtime mic control - Audio Config Validation — Real-time validation with editor warnings in Project Settings
- Permission Handling — Improved Android microphone permission flow with callbacks
- Developer Settings UI — Full settings panel in Project Settings with audio plugin configuration
New Features
LCK Core SDK
| Feature | Description |
|---|---|
| Audio Config Validation | ValidateAudioConfig() method with FMOD > Wwise > UnrealAudio priority |
| Build Info API | GetLoadedAudioPlugins(), GetBuildInfoDescription() with dynamic build number |
| Microphone Mute Control | SetMicrophoneEnabled(), IsMicrophoneEnabled() for runtime mic control |
| Developer Settings UI | Full settings panel in Project Settings with audio plugin checkboxes |
| Voice Chat Audio Source | FLCKAudioSourceVoiceChat struct for Vivox integration |
| Plugin Detection | Improved detection via IPluginManager with dependency checks |
| Settings Categories | Organized settings with headers, tooltips, and category grouping |
| Audio Buffer Cleanup | Clear previously buffered audio on state change |
LCKUI
| Feature | Description |
|---|---|
| Debug Mode System | ILCKVisuallyDebuggable interface for debug visualization |
| Debug Button | New debug toggle button in UI |
| ELCKMicState Enum | Three-state: On, Off, No_Access for permission handling |
| Audio Level Indicator | Real-time microphone level display on recording button |
| Demo Dashboard | LCKDemoUIBoard with FOV, quality, orientation, mic controls |
| JSON State Persistence | Replaced USaveGame with JSON for tablet state |
LCKTablet
| Feature | Description |
|---|---|
| Android Permission Handling | RequestMicAccess() with proper callback flow |
| Mic State Management | ToggleMicState() with No_Access state support |
| Recording State Manager | Mic level reading integrated into RecorderController |
| Developer Settings Integration | Uses ULCKDeveloperSettings for camera modes and profiles |
| Data Model Delegates | Added delegates for state change notifications |
| JSON Data Persistence | Save/load tablet state as JSON with platform paths |
| Mic Audio Level API | Read mic audio level via ULCKService |
Audio Plugins
| Plugin | Changes |
|---|---|
| LCKVivox | SDK settings binding, microphone output fix |
| LCKOboe | SDK settings binding for StartCapture |
| LCKWwise | SDK settings binding, documentation |
| LCKFMOD | Capture fix, SDK settings binding, documentation |
Bug Fixes
| Fix | Platform | Description |
|---|---|---|
| Photo capture not triggering | All | Fixed TSharedPtr notification handling |
| TabletDataModel null crash | All | Use NewObject in BeginPlay instead of CreateDefaultSubobject |
| Settings not restoring | All | Removed forced defaults on initialization |
| Notification callbacks | All | Execute callback per queued notification |
| Mic check on Windows | Windows | Return true for non-Android platforms |
| SetupBindingToDataModel null | All | Added null guard check |
Improvements
| Improvement | Description |
|---|---|
| Cleaned Constants | Consolidated constants across LCKUI and LCKTablet modules |
| Camera Modes Moved | Camera modes moved from LCKUI to LCKTablet for better modularity |
| JSON Helper Moved | JSON utilities centralized in LCKTablet |
| Plugin Icons | Added icons for LCKUI and LCKTablet plugins |
| Audio Sub-Levels | Added audio sub-levels for middleware variants |
Breaking Changes
-
FLCKMetaData.Build— Changed fromint32toFString -
Mic state type — Use
ELCKMicStateenum instead ofbool
Code Reorganization
Several components were moved between modules for better organization:| Component | From | To |
|---|---|---|
Camera modes (ELCKCameraMode) | LCKUI | LCKTablet |
| JSON helper utilities | LCKUI | LCKTablet |
| Tablet data model | LCKUI | LCKTablet |
| Tablet UI components | LCKUI | LCKTablet |
- Open Beta release