> ## Documentation Index
> Fetch the complete documentation index at: https://docs.liv.tv/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrade Guide

> How to update the LIV Camera Kit (LCK) SDK to the latest version in Unreal Engine, including backup steps, breaking changes, and troubleshooting failed upgrades.

<Danger>
  **Always close the Unreal Editor before upgrading LCK.**

  Native libraries are loaded at editor startup and cannot be replaced while running.
  Upgrading while the editor is open will cause failures and may corrupt your project.
</Danger>

## Before You Begin

<AccordionGroup>
  <Accordion title="Pre-Upgrade Checklist" icon="clipboard-check" defaultOpen>
    * [ ] Close Unreal Editor completely
    * [ ] Backup your project (especially Plugins folder)
    * [ ] Note current LCK version for reference
    * [ ] Check release notes for breaking changes
    * [ ] Verify Unreal Engine version compatibility
  </Accordion>
</AccordionGroup>

***

## Upgrade Steps

<Steps>
  <Step title="Close Unreal Editor">
    Completely close the Unreal Editor. Verify no UE processes are running in Task Manager.

    <Warning>
      Even if you haven't pressed Play, LCK loads native libraries on editor startup.
      These cannot be replaced while the editor is open.
    </Warning>
  </Step>

  <Step title="Backup Current Installation">
    Before removing the old SDK, create a backup:

    ```bash theme={null}
    # Windows
    xcopy /E /I "YourProject\Plugins\LCK" "YourProject\Plugins\LCK_backup"
    xcopy /E /I "YourProject\Plugins\LCKTablet" "YourProject\Plugins\LCKTablet_backup"
    ```

    Or manually copy the `Plugins/LCK*` folders to a safe location.
  </Step>

  <Step title="Remove Old SDK">
    Delete the existing LCK plugin folders:

    ```
    YourProject/
    └── Plugins/
        ├── LCK/              ← Delete
        ├── LCKTablet/        ← Delete
        ├── LCKUI/            ← Delete
        ├── LCKAudio/         ← Delete
        ├── LCKUnrealAudio/   ← Delete (if present, new in v1.0)
        ├── LCKStreaming/     ← Delete (if present, new in v1.0)
        ├── LCKFMOD/          ← Delete (if present)
        ├── LCKWwise/         ← Delete (if present)
        ├── LCKVivox/         ← Delete (if present)
        └── LCKOboe/          ← Delete (if present)
    ```
  </Step>

  <Step title="Install New SDK">
    Extract the new SDK package to your Plugins folder:

    ```
    YourProject/
    └── Plugins/
        ├── LCK/           ← New version
        ├── LCKTablet/     ← New version
        └── ...
    ```
  </Step>

  <Step title="Regenerate Project Files">
    Right-click your `.uproject` file and select **Generate Visual Studio project files** (or equivalent for your IDE).

    This ensures the new plugin modules are properly registered.
  </Step>

  <Step title="Open Editor and Verify">
    1. Open Unreal Editor
    2. Go to **Edit > Plugins**
    3. Verify LCK plugins are enabled
    4. Check **Output Log** for any LCK errors
    5. Test recording functionality
  </Step>
</Steps>

***

## Version Compatibility

| SDK Version | Unreal Engine | Notes           |
| ----------- | ------------- | --------------- |
| 1.0         | 5.4+          | Current stable  |
| 0.9.2       | 5.4+          | Previous stable |
| 0.9.1       | 5.4+          | Initial release |

<Note>
  We recommend always using the latest SDK version.
  Per the SDK License Agreement, older versions are not officially supported.
</Note>

***

## Breaking Changes by Version

### 1.0

<Danger>
  v1.0 introduces **streaming support** and refactors the audio delegate system.
  If you bind audio delegates or interact with the encoder directly, you **must** update your code.
</Danger>

**Breaking Changes:**

1. **Audio delegate renamed and re-typed** — `FOnRenderAudioDelegate` is now a typedef for a multicast delegate invocation, not a single-cast delegate

   The parent delegate type has been renamed from `FOnRenderAudioDelegate` to `FDelegateRenderAudio` and changed from a single-cast delegate to a multicast delegate (`DECLARE_MULTICAST_DELEGATE_FourParams`). The old name `FOnRenderAudioDelegate` still exists as a typedef for the inner `FDelegate` type, so existing variable declarations compile — but **binding semantics have changed**.

   Additionally, the delegate signature gained a fourth parameter (`SampleRate`).

   ```cpp theme={null}
   // Before (v0.9.2) — single-cast delegate, 3 params
   AudioSource->OnAudioDataDelegate.BindLambda(
       [](TArrayView<const float> PCM, int32 Channels, ELCKAudioChannel Source)
       {
           // Process audio...
       }
   );

   // After (v1.0) — multicast delegate, 4 params (added SampleRate)
   // OnAudioDataDelegate is now FOnRenderAudioDelegate (typedef for FDelegateRenderAudio::FDelegate)
   // You must use multicast binding via the parent delegate
   AudioSource->OnAudioDataDelegate.BindLambda(
       [](TArrayView<const float> PCM, int32 Channels, int32 SampleRate, ELCKAudioChannel Source)
       {
           // Process audio — SampleRate is now available directly
       }
   );
   ```

   <Warning>
     Even though `FOnRenderAudioDelegate` still exists as a typedef, your lambda **must** accept four parameters or it will not compile. Update all audio delegate bindings to include `int32 SampleRate` as the third parameter.
   </Warning>

2. **`bEnableStreaming` added to developer settings** — Streaming is disabled by default

   A new `bEnableStreaming` setting has been added to `ULCKDeveloperSettings`. When `false` (the default), RTMP streaming libraries are not packaged and streaming API calls return `LCK_STREAMING_NOT_AVAILABLE`.

   ```cpp theme={null}
   // Enable streaming in Project Settings > Plugins > LCK SDK > Features
   // Or set directly:
   ULCKDeveloperSettings* Settings = ULCKDeveloperSettings::Get();
   Settings->bEnableStreaming = true;
   ```

   <Info>
     If you do not need streaming, leave this disabled to reduce APK size. The streaming `.so`/`.dll` files will not be included in the build.
   </Info>

3. **`AcquireEncoder()` / `ReleaseEncoder()` added** — New encoder lifecycle management

   `ULCKRecorderSubsystem` now uses reference-counted encoder ownership. Recording and streaming can share the same encoder instance. If you call `StartRecording()` / `StopRecording()` through `ULCKService`, this is handled automatically. Only update if you use the recorder subsystem directly.

   ```cpp theme={null}
   ULCKRecorderSubsystem* Recorder = GetWorld()->GetSubsystem<ULCKRecorderSubsystem>();

   // Acquire encoder (ref count +1)
   // bNeedsDisk: true if you need MP4 file output
   // Optional overrides for video/audio bitrate
   bool bSuccess = Recorder->AcquireEncoder(/*bNeedsDisk=*/ true);

   // ... use encoder for recording or streaming ...

   // Release encoder (ref count -1, encoder destroyed when count reaches 0)
   // bSaveFile: true to finalize MP4 and copy to gallery
   Recorder->ReleaseEncoder(/*bSaveFile=*/ true);
   ```

4. **`ILCKStreamingFeature` interface added** — Streaming backend contract

   A new modular feature interface for streaming backends. Implementations are discovered at runtime via `IModularFeatures`. You do not need to implement this unless you are building a custom streaming backend.

   ```cpp theme={null}
   // Check if a streaming feature is available
   auto& MF = IModularFeatures::Get();
   if (MF.IsModularFeatureAvailable(ILCKStreamingFeature::GetModularFeatureName()))
   {
       ILCKStreamingFeature& Streaming = MF.GetModularFeature<ILCKStreamingFeature>(
           ILCKStreamingFeature::GetModularFeatureName());

       Streaming.OnStreamStartedDelegate.AddLambda([]() {
           UE_LOG(LogLCK, Log, TEXT("Stream started"));
       });

       Streaming.StartLogin();
   }
   ```

5. **`ILCKPacketSink` interface added** — Packet routing contract

   Encoders can now route encoded H.264/AAC packets to arbitrary sinks (RTMP streams, network transports, etc.) via `ILCKPacketSink`. You do not need to implement this unless you are building a custom packet consumer.

   ```cpp theme={null}
   // Register a custom packet sink with the encoder
   Encoder->AddPacketSink(MyCustomSink);

   // ILCKPacketSink methods you must implement:
   // Open(), OnVideoFormatReady(), OnAudioFormatReady(),
   // SendVideoPacket(), SendAudioPacket(), Close(), IsOpen()
   ```

6. **`ELCKStreamingState` enum added** — UI must handle streaming states

   If you build custom UI, you must handle the new streaming states:

   ```cpp theme={null}
   // ELCKStreamingState values:
   // Idle      — No streaming activity
   // Pairing   — Waiting for pairing code entry
   // Paired    — Authenticated, ready to stream
   // Streaming — Live stream active
   // Error     — Stream error occurred
   ```

7. **`ELCKTabletMode` enum added** — Camera/Stream mode switching

   The tablet now supports two modes. Custom UI must handle mode switching:

   ```cpp theme={null}
   // ELCKTabletMode values:
   // Camera — Recording mode (default, same as v0.9.2 behavior)
   // Stream — Live streaming mode
   ```

8. **Plugin version bumped to 1.0** — All `.uplugin` files updated

   Update any version checks or minimum-version guards in your build scripts.

**New Features:**

* Live Streaming — RTMP streaming support via LCKStreaming module
* Encoder Sharing — Recording and streaming can share a single encoder instance
* Packet Sink Architecture — Extensible encoded packet routing
* Streaming UI — Tablet mode switching between Camera and Stream
* Hub Integration — `LaunchHub()` and `IsHubInstalled()` for LIV Hub companion app

**New Modules:**

* `LCKStreaming` — RTMP streaming implementation (optional, requires `bEnableStreaming`)
* `LCKUnrealAudio` — Extracted Unreal Engine audio capture (previously bundled in LCKAudio)

***

### 0.9.2

**Breaking Changes:**

1. **`FLCKMetaData.Build`** — Changed from `int32` to `FString`

   ```cpp theme={null}
   // Before (v0.9.1)
   int32 BuildNumber = MetaData.Build;

   // After (v0.9.2)
   FString BuildString = MetaData.Build;
   ```

2. **Mic state type** — Use `ELCKMicState` enum instead of `bool`

   ```cpp theme={null}
   // Before (v0.9.1)
   bool bMicEnabled = true;

   // After (v0.9.2)
   ELCKMicState MicState = ELCKMicState::On;
   // Values: On, Off, No_Access
   ```

**New Features:**

* PCVR Support — single implementation for PCVR and Meta Quest Standalone
* Microphone Mute Control with `SetMicrophoneEnabled()` API
* Audio Config Validation with editor warnings
* Debug Mode System with `ILCKVisuallyDebuggable` interface
* Improved Android microphone permission flow

### 0.9.1

Initial public release of LCK SDK for Unreal Engine. No breaking changes.

***

## Handling Custom Modifications

<Warning>
  Upgrading will overwrite any custom changes made directly to LCK plugin files.

  **We strongly recommend NOT modifying LCK plugins directly.**
</Warning>

### Recommended Approach

Instead of modifying LCK files, create project-local overrides:

1. **Custom Blueprints** — Create Blueprint subclasses of LCK actors
2. **Custom Widgets** — Create widget variants based on LCK widgets
3. **Custom Materials** — Create Material Instances, don't modify base materials
4. **Custom Scripts** — Extend LCK classes in your own modules

### If You Have Modifications

If you've modified LCK files directly:

1. Document all changes before upgrading
2. After upgrade, reapply changes to new version
3. Consider refactoring to use extension approach

***

## Troubleshooting Upgrades

<AccordionGroup>
  <Accordion title="Editor crashes on startup after upgrade" icon="skull">
    **Cause:** Old native libraries still loaded or version mismatch.

    **Solution:**

    1. Close all UE processes
    2. Delete `Binaries` and `Intermediate` folders in your project
    3. Delete `DerivedDataCache` folder
    4. Regenerate project files
    5. Rebuild project
  </Accordion>

  <Accordion title="Compile errors after upgrade" icon="code">
    **Cause:** API changes between versions.

    **Solution:**

    1. Check release notes for breaking changes
    2. Update your code to match new API
    3. See migration examples above
  </Accordion>

  <Accordion title="Plugins not appearing in editor" icon="eye-slash">
    **Cause:** Plugin not properly installed or wrong folder structure.

    **Solution:**

    1. Verify folder structure matches expected layout
    2. Check `.uplugin` files exist in each plugin folder
    3. Ensure plugins are enabled in Edit > Plugins
  </Accordion>

  <Accordion title="Recording not working after upgrade" icon="video-slash">
    **Cause:** Settings or configuration may have changed.

    **Solution:**

    1. Verify Tracking ID is still configured
    2. Check Project Settings > LCK SDK
    3. Review Output Log for specific errors
    4. Test with a fresh LCK tablet actor
  </Accordion>
</AccordionGroup>

***

## Downgrading

<Danger>
  Downgrading to older SDK versions is **not recommended** and **not supported**.

  If you must downgrade due to critical issues:

  1. Report the issue to [LIV support](https://discord.com/invite/liv)
  2. Restore from your backup
  3. Regenerate project files
</Danger>

***

## Clean Installation

For a completely fresh start:

```bash theme={null}
# 1. Remove all LCK plugins
rm -rf YourProject/Plugins/LCK*

# 2. Remove cached data
rm -rf YourProject/Intermediate
rm -rf YourProject/Binaries
rm -rf YourProject/DerivedDataCache
rm -rf YourProject/Saved/Config  # Optional: resets all settings

# 3. Install new SDK
# Extract new SDK to Plugins/

# 4. Regenerate project
# Right-click .uproject > Generate Project Files
```

***

## See Also

<CardGroup cols={2}>
  <Card title="Installation" icon="download" href="/unreal/installation">
    Fresh installation guide
  </Card>

  <Card title="Changelog" icon="list" href="/unreal/changelogs">
    Version history and release notes
  </Card>
</CardGroup>
