Skip to main content
LCK provides in-game video recording with hardware-accelerated encoding, configurable quality presets, and a full scripting API for programmatic control.

How recording works

When a user taps Record on the LCK tablet, the active LckCamera begins capturing frames. The captured video and audio are sent to a hardware-accelerated encoder and written to disk. Users can switch between cameras seamlessly during recording without interruption. Recordings are saved to:
  • Quest: Storage/Movies/<RecordingAlbumName>
  • PCVR: <User>/Videos/<RecordingAlbumName>
The album name is configurable in Edit > Project Settings > LCK.

Camera modes

LCK includes three built-in camera modes, all available from the tablet UI:
ModeDescriptionSettings
SelfieFront/back facing camera on the tabletFOV, Smoothing, Flip, Follow
First-personFilms from the player’s HMD perspectiveFOV, Smoothing
Third-personTracks the user’s head at a distanceFOV, Smoothing, Distance, Flip
All modes support FOV range of 50—100 and smoothing from 0—100.

Quality presets

Quality is configured through the LckQualityConfig ScriptableObject, referenced by the LCKCameraController component.

Android (Quest) defaults

PresetResolutionBitrateFramerateAudio Bitrate
SD1280x7207.5 Mbps60 fps192 kbps
HD1920x108012 Mbps60 fps192 kbps
Quest 2 override: SD at 6.5 Mbps / 30 fps, HD at 10 Mbps / 30 fps.

Desktop (PCVR) defaults

PresetResolutionBitrateFramerateAudio Bitrate
SD1280x7207.5 Mbps60 fps192 kbps
HD1920x108012 Mbps60 fps192 kbps
2K2560x144025 Mbps60 fps192 kbps
4K3840x216065 Mbps60 fps192 kbps
You can define custom presets and per-device overrides in the LckQualityConfig asset.

Recording API

For programmatic control, access LckService via dependency injection:
[InjectLck] private ILckService _lckService;

Core methods

// Start and stop recording
_lckService.StartRecording();
_lckService.StopRecording();

// Pause and resume (v1.3.5+)
_lckService.PauseRecording();
_lckService.ResumeRecording();

// Query state
_lckService.IsRecording();   // LckResult<bool>
_lckService.IsPaused();      // LckResult<bool>
_lckService.GetRecordingDuration(); // LckResult<TimeSpan>

// Capture a screenshot
_lckService.CapturePhoto();

Configure quality programmatically

// Set resolution (only when not capturing)
_lckService.SetTrackResolution(new CameraResolutionDescriptor { width = 1920, height = 1080 });
_lckService.SetTrackFramerate(60);
_lckService.SetTrackBitrate(12000000);
_lckService.SetTrackAudioBitrate(192000);
_lckService.SetCameraOrientation(LckCameraOrientation.Landscape);

Events

_lckService.OnRecordingStarted += (result) => { /* handle */ };
_lckService.OnRecordingStopped += (result) => { /* handle */ };
_lckService.OnRecordingPaused += (result) => { /* handle */ };
_lckService.OnRecordingResumed += (result) => { /* handle */ };
_lckService.OnRecordingSaved += (result) => { /* access result.Value */ };
_lckService.OnPhotoSaved += (result) => { /* handle */ };
_lckService.OnLowStorageSpace += (result) => { /* warn user */ };

Higher quality capture rendering

If you want capture output to look better than the in-game experience (for example, higher-quality player avatars), the recommended approach is to use separate render layers:
  1. Create a duplicate of the object at higher quality.
  2. Place it on a dedicated render layer visible only to LCK cameras.
  3. Keep the original on a different layer for gameplay rendering.
This avoids GPU timing issues with command buffers. See Higher Quality Scaling for alternative approaches using command buffers or URP Render Features.