> ## 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.

# Device-Specific Settings (Unreal)

> Optimize LCK recording settings for different VR headsets in Unreal Engine.

## What Problem Does This Solve?

Different VR headsets have different performance limits:

* Quest 2 has thermal/power constraints
* Quest 3/Pro can handle higher quality
* PCVR depends on GPU capabilities

Device-specific overrides let you automatically adjust recording settings based on detected hardware, ensuring the best balance between video quality and game performance.

## When to Use This

Use device overrides when:

* Supporting multiple Quest devices
* Targeting both standalone VR and PCVR
* Users report performance issues
* Optimizing for specific platforms
* Want automatic quality adjustment

Skip this if: You're only targeting one specific device and have manually tuned settings.

***

## Supported Devices

| Device        | Max Resolution | Max FPS | Max Bitrate | Notes                         |
| ------------- | -------------- | ------- | ----------- | ----------------------------- |
| **Quest 2**   | 1080p HD       | 30      | 10 Mbps     | Conservative (thermal limits) |
| **Quest 3**   | 4K UHD         | 60      | 20 Mbps     | Full quality support          |
| **Quest Pro** | 4K UHD         | 60      | 20 Mbps     | Full quality support          |
| **PCVR**      | 4K UHD         | 60      | 20 Mbps     | GPU dependent                 |

***

## Quest 2 Optimization

Quest 2 has thermal and power constraints that limit encoding performance.

### Recommended Quest 2 Settings

| Setting        | Default  | Quest 2 Override | Reason             |
| -------------- | -------- | ---------------- | ------------------ |
| Max Resolution | 4K       | **1080p HD**     | Thermal limits     |
| Framerate      | 60       | **30**           | CPU overhead       |
| Video Bitrate  | 20 Mbps  | **10 Mbps**      | Encoding load      |
| Audio Bitrate  | 320 Kbps | **192 Kbps**     | Sufficient quality |
| 2K Profile     | Enabled  | **Disabled**     | Not performant     |
| 4K Profile     | Enabled  | **Disabled**     | Not performant     |

***

### Apply Quest 2 Overrides

```cpp theme={null}
void ADeviceManager::ApplyQuest2Overrides()
{
    ULCKDeveloperSettings* Settings = ULCKDeveloperSettings::Get();
    
    // Override HD profile for Quest 2
    FLCKRecordingProfile& HDProfile = Settings->Profile_HD;
    HDProfile.Width = 1920;
    HDProfile.Height = 1080;
    HDProfile.Framerate = 30;
    HDProfile.VideoBitrate = 10 << 20;  // 10 Mbps
    HDProfile.AudioBitrate = 192000;    // 192 Kbps
    
    // Disable higher quality profiles
    /* bEnable2KProfile - custom property, not in SDK */ = false;
    /* bEnable4KProfile - custom property, not in SDK */ = false;
    
    UE_LOG(LogLCK, Log, TEXT("Applied Quest 2 optimizations"));
}
```

***

### Why These Limits?

**Thermal management:**

* Quest 2 SoC (Snapdragon XR2 Gen 1) generates heat under load
* Extended recording → thermal throttling → frame drops
* Conservative settings prevent overheating

**File size:**

* 10 Mbps @ 30fps = \~1.2 GB per hour
* 20 Mbps @ 60fps = \~5.4 GB per hour (too much for casual recording)

**Battery life:**

* Higher quality = faster battery drain
* 30fps encoding uses \~30% less power than 60fps

***

## Quest 3 / Quest Pro Optimization

Quest 3 and Quest Pro have better cooling and more powerful hardware.

### Recommended Quest 3/Pro Settings

| Setting        | Value          | Notes            |
| -------------- | -------------- | ---------------- |
| Max Resolution | 4K (3840×2160) | Full support     |
| Framerate      | 60             | Smooth encoding  |
| Video Bitrate  | 20 Mbps        | High quality     |
| Audio Bitrate  | 320 Kbps       | Max quality      |
| 2K Profile     | **Enabled**    | Available option |
| 4K Profile     | **Enabled**    | Available option |

***

### Apply Quest 3 Overrides

```cpp theme={null}
void ADeviceManager::ApplyQuest3Overrides()
{
    ULCKDeveloperSettings* Settings = ULCKDeveloperSettings::Get();
    
    // Enable all quality profiles
    /* bEnable2KProfile - custom property, not in SDK */ = true;
    /* bEnable4KProfile - custom property, not in SDK */ = true;
    
    // Configure 4K profile
    FLCKRecordingProfile& UHDProfile = Settings->Profile_4K;
    UHDProfile.Width = 3840;
    UHDProfile.Height = 2160;
    UHDProfile.Framerate = 60;
    UHDProfile.VideoBitrate = 20 << 20;  // 20 Mbps
    UHDProfile.AudioBitrate = 320000;    // 320 Kbps
    
    UE_LOG(LogLCK, Log, TEXT("Applied Quest 3 optimizations"));
}
```

***

## Automatic Device Detection

Detect the device at runtime and apply appropriate settings:

```cpp theme={null}
UCLASS()
class ADeviceManager : public AActor
{
    GENERATED_BODY()
    
public:
    void BeginPlay() override
    {
        Super::BeginPlay();
        ApplyDeviceOverrides();
    }
    
private:
    void ApplyDeviceOverrides()
    {
        FString DeviceModel = GetDeviceModel();
        
        UE_LOG(LogLCK, Log, TEXT("Detected device: %s"), *DeviceModel);
        
        if (DeviceModel.Contains(TEXT("Quest 2")))
        {
            ApplyQuest2Overrides();
        }
        else if (DeviceModel.Contains(TEXT("Quest 3")))
        {
            ApplyQuest3Overrides();
        }
        else if (DeviceModel.Contains(TEXT("Quest Pro")))
        {
            ApplyQuestProOverrides();
        }
        else
        {
            // PCVR or unknown device - use default settings
            UE_LOG(LogLCK, Log, TEXT("Using default settings for PCVR/unknown device"));
        }
    }
    
    FString GetDeviceModel()
    {
#if PLATFORM_ANDROID
        // Get Android device model
        return FAndroidMisc::GetDeviceModel();
#else
        // Get VR headset name via XR system
        if (GEngine && GEngine->XRSystem.IsValid())
        {
            FString DeviceName = GEngine->XRSystem->GetSystemName().ToString();
            return DeviceName;
        }
        return TEXT("Unknown");
#endif
    }
    
    void ApplyQuest2Overrides() { /* See above */ }
    void ApplyQuest3Overrides() { /* See above */ }
    void ApplyQuestProOverrides() { /* Same as Quest 3 */ }
};
```

***

## Custom Override Configuration

### Using Config Files

Create platform-specific config files:

**Config/Android\_Quest2/DefaultGame.ini:**

```ini theme={null}
[/Script/LCKCore.LCKDeveloperSettings]
+Profile_HD=(Width=1920,Height=1080,Framerate=30,VideoBitrate=10000000,AudioBitrate=192000)
bEnable2KProfile=false
bEnable4KProfile=false
```

**Config/Android\_Quest3/DefaultGame.ini:**

```ini theme={null}
[/Script/LCKCore.LCKDeveloperSettings]
+Profile_4K=(Width=3840,Height=2160,Framerate=60,VideoBitrate=20000000,AudioBitrate=320000)
bEnable2KProfile=true
bEnable4KProfile=true
```

***

### Runtime Configuration System

```cpp theme={null}
USTRUCT(BlueprintType)
struct FLCKDeviceOverride
{
    GENERATED_BODY()
    
    UPROPERTY(EditAnywhere, Category = "Device Override")
    FString DeviceModelPattern;
    
    UPROPERTY(EditAnywhere, Category = "Device Override")
    ELCKVideoQuality MaxQuality;
    
    UPROPERTY(EditAnywhere, Category = "Device Override")
    int32 MaxFramerate;
    
    UPROPERTY(EditAnywhere, Category = "Device Override")
    int32 VideoBitrate;
    
    UPROPERTY(EditAnywhere, Category = "Device Override")
    int32 AudioBitrate;
};

UCLASS(Config=Game, DefaultConfig)
class ULCKDeviceSettings : public UDeveloperSettings
{
    GENERATED_BODY()
    
public:
    UPROPERTY(Config, EditAnywhere, Category = "Device Overrides")
    TArray<FLCKDeviceOverride> DeviceOverrides;
    
    UFUNCTION(BlueprintCallable)
    void ApplyOverrideForDevice(const FString& DeviceModel)
    {
        for (const FLCKDeviceOverride& Override : DeviceOverrides)
        {
            if (DeviceModel.Contains(Override.DeviceModelPattern))
            {
                ApplyOverride(Override);
                return;
            }
        }
    }
    
private:
    void ApplyOverride(const FLCKDeviceOverride& Override)
    {
        ULCKDeveloperSettings* Settings = ULCKDeveloperSettings::Get();
        
        // Apply override settings
        FLCKRecordingProfile Profile;
        Profile.Framerate = Override.MaxFramerate;
        Profile.VideoBitrate = Override.VideoBitrate;
        Profile.AudioBitrate = Override.AudioBitrate;
        
        // Set based on quality
        switch (Override.MaxQuality)
        {
            case ELCKVideoQuality::HD:
                Settings->Profile_HD = Profile;
                /* bEnable2KProfile - custom property, not in SDK */ = false;
                /* bEnable4KProfile - custom property, not in SDK */ = false;
                break;
            case ELCKVideoQuality::TWO_K:
                Settings->Profile_2K = Profile;
                /* bEnable4KProfile - custom property, not in SDK */ = false;
                break;
            case ELCKVideoQuality::FOUR_K:
                Settings->Profile_4K = Profile;
                break;
        }
    }
};
```

***

## Performance Monitoring

Monitor encoding performance to validate your overrides:

```cpp theme={null}
UCLASS()
class ULCKPerformanceMonitor : public UActorComponent
{
    GENERATED_BODY()
    
public:
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, 
                              FActorComponentTickFunction* ThisTickFunction) override
    {
        Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
        
        if (!Service || !Service->IsRecording())
            return;
        
        // Track frame times
        float FrameTimeMs = DeltaTime * 1000.0f;
        FrameTimeHistory.Add(FrameTimeMs);
        
        // Keep last 2 seconds
        if (FrameTimeHistory.Num() > 60)
        {
            FrameTimeHistory.RemoveAt(0);
        }
        
        // Calculate average frame time
        float AvgFrameTime = 0.0f;
        for (float Time : FrameTimeHistory)
        {
            AvgFrameTime += Time;
        }
        AvgFrameTime /= FrameTimeHistory.Num();
        
        // Check for performance issues
        float TargetFrameTime = 1000.0f / 30.0f; // 33.3ms for 30fps
        if (AvgFrameTime > TargetFrameTime * 1.2f) // 20% over target
        {
            OnPerformanceWarning();
        }
    }
    
private:
    UPROPERTY()
    ULCKService* Service;
    
    TArray<float> FrameTimeHistory;
    
    void OnPerformanceWarning()
    {
        UE_LOG(LogLCK, Warning, 
            TEXT("Recording impacting performance - consider lower quality"));
        
        // Notify UI
        if (OnPerformanceIssue.IsBound())
        {
            OnPerformanceIssue.Broadcast(
                TEXT("Recording may be impacting game performance. "
                     "Consider using a lower quality profile.")
            );
        }
    }
    
public:
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPerformanceIssue, FString, Message);
    
    UPROPERTY(BlueprintAssignable)
    FOnPerformanceIssue OnPerformanceIssue;
};
```

***

## Thermal Management (Android)

On Android, monitor thermal state to prevent throttling:

```cpp theme={null}
#if PLATFORM_ANDROID

UCLASS()
class ULCKThermalMonitor : public UActorComponent
{
    GENERATED_BODY()
    
public:
    virtual void BeginPlay() override
    {
        Super::BeginPlay();
        
        // Check thermal state every 10 seconds
        GetWorld()->GetTimerManager().SetTimer(
            ThermalCheckTimer,
            this,
            &ULCKThermalMonitor::CheckThermalState,
            10.0f,
            true
        );
    }
    
private:
    FTimerHandle ThermalCheckTimer;
    UPROPERTY()
    ULCKService* Service;
    
    void CheckThermalState()
    {
        // Android thermal API
        int32 ThermalStatus = FAndroidMisc::GetThermalStatus();
        
        switch (ThermalStatus)
        {
            case 0: // THERMAL_STATUS_NONE
            case 1: // THERMAL_STATUS_LIGHT
                // Normal operation
                break;
                
            case 2: // THERMAL_STATUS_MODERATE
                UE_LOG(LogLCK, Warning, TEXT("Device warming up"));
                OnThermalWarning();
                break;
                
            case 3: // THERMAL_STATUS_SEVERE
            case 4: // THERMAL_STATUS_CRITICAL
                UE_LOG(LogLCK, Error, TEXT("Thermal throttling detected"));
                ReduceQualityForThermal();
                break;
        }
    }
    
    void OnThermalWarning()
    {
        // Notify user
        if (OnThermalAlert.IsBound())
        {
            OnThermalAlert.Broadcast(
                TEXT("Device temperature rising. Recording quality may be reduced.")
            );
        }
    }
    
    void ReduceQualityForThermal()
    {
        if (!Service)
        {
            Service = GetLCKService();
        }
        
        if (Service && !Service->IsRecording())
        {
            return;
        }
        
        // Get current quality
        ELCKVideoQuality CurrentQuality = DataModel->GetCurrentVideoQuality();
        
        // Drop one quality level
        ELCKVideoQuality NewQuality = CurrentQuality;
        
        switch (CurrentQuality)
        {
            case ELCKVideoQuality::FOUR_K:
                NewQuality = ELCKVideoQuality::TWO_K;
                break;
            case ELCKVideoQuality::TWO_K:
                NewQuality = ELCKVideoQuality::HD;
                break;
            case ELCKVideoQuality::HD:
                NewQuality = ELCKVideoQuality::SD;
                break;
            case ELCKVideoQuality::SD:
                // Already at lowest - stop recording
                Service->StopRecording();
                UE_LOG(LogLCK, Error, TEXT("Stopped recording due to thermal limits"));
                return;
        }
        
        // Stop current recording
        Service->StopRecording();
        
        // Apply new quality
        DataModel->SetVideoQuality(NewQuality);
        
        UE_LOG(LogLCK, Warning, 
            TEXT("Reduced quality due to thermal throttling: %d -> %d"), 
            (int32)CurrentQuality, (int32)NewQuality);
        
        // Notify user
        if (OnThermalAlert.IsBound())
        {
            OnThermalAlert.Broadcast(
                FString::Printf(TEXT("Quality reduced to %s due to device temperature."), 
                    *UEnum::GetValueAsString(NewQuality))
            );
        }
    }
    
public:
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnThermalAlert, FString, Message);
    
    UPROPERTY(BlueprintAssignable)
    FOnThermalAlert OnThermalAlert;
};

#endif // PLATFORM_ANDROID
```

***

## User-Selectable Performance Presets

Let users choose their own balance:

```cpp theme={null}
UENUM(BlueprintType)
enum class ELCKPerformancePreset : uint8
{
    Quality      UMETA(DisplayName = "Quality"),      // Highest quality, may impact performance
    Balanced     UMETA(DisplayName = "Balanced"),     // Default, good quality with minimal impact
    Performance  UMETA(DisplayName = "Performance")   // Lower quality, prioritize game FPS
};

UCLASS()
class ULCKPerformancePresetManager : public UObject
{
    GENERATED_BODY()
    
public:
    UFUNCTION(BlueprintCallable)
    void ApplyPreset(ELCKPerformancePreset Preset)
    {
        ULCKDeveloperSettings* Settings = ULCKDeveloperSettings::Get();
        FString DeviceModel = GetDeviceModel();
        
        if (DeviceModel.Contains(TEXT("Quest 2")))
        {
            ApplyQuest2Preset(Preset);
        }
        else if (DeviceModel.Contains(TEXT("Quest 3")))
        {
            ApplyQuest3Preset(Preset);
        }
    }
    
private:
    void ApplyQuest2Preset(ELCKPerformancePreset Preset)
    {
        ULCKDeveloperSettings* Settings = ULCKDeveloperSettings::Get();
        FLCKRecordingProfile& HDProfile = Settings->Profile_HD;
        
        switch (Preset)
        {
            case ELCKPerformancePreset::Quality:
                // 1080p @ 60fps, 12 Mbps (HD default)
                HDProfile.Framerate = 60;
                HDProfile.VideoBitrate = 12 << 20;
                break;

            case ELCKPerformancePreset::Balanced:
                // 1080p @ 30fps, 8 Mbps (reduced for Quest)
                HDProfile.Framerate = 30;
                HDProfile.VideoBitrate = 8 << 20;
                break;
                
            case ELCKPerformancePreset::Performance:
                // 720p @ 30fps, 4 Mbps
                HDProfile.Width = 1280;
                HDProfile.Height = 720;
                HDProfile.Framerate = 30;
                HDProfile.VideoBitrate = 4 << 20;
                break;
        }
    }
};
```

***

## Best Practices

### 1. Test on Target Devices

<Warning>
  Always test recording performance on actual target devices, not in editor or emulator.
</Warning>

* Quest 2 has different thermal characteristics than Quest 3
* PCVR performance depends heavily on GPU
* Test with your game's most demanding scenes
* Monitor frame times during extended recordings

***

### 2. Provide User Options

```cpp theme={null}
// Settings menu
void ASettingsMenu::BuildQualityOptions()
{
    FString DeviceModel = GetDeviceModel();
    
    if (DeviceModel.Contains(TEXT("Quest 2")))
    {
        // Quest 2: Offer SD and HD only
        AddQualityOption(ELCKVideoQuality::SD, TEXT("SD (720p)"), 
            TEXT("Best performance"));
        AddQualityOption(ELCKVideoQuality::HD, TEXT("HD (1080p)"), 
            TEXT("Recommended"));
    }
    else if (DeviceModel.Contains(TEXT("Quest 3")))
    {
        // Quest 3: Offer all options
        AddQualityOption(ELCKVideoQuality::HD, TEXT("HD (1080p)"), 
            TEXT("Recommended"));
        AddQualityOption(ELCKVideoQuality::TWO_K, TEXT("2K (1440p)"), 
            TEXT("High quality"));
        AddQualityOption(ELCKVideoQuality::FOUR_K, TEXT("4K (2160p)"), 
            TEXT("Maximum quality"));
    }
}
```

***

### 3. Document Device Support

Clearly communicate what works best:

**In-game tooltips:**

```cpp theme={null}
FString GetQualityTooltip(ELCKVideoQuality Quality)
{
    if (IsQuest2())
    {
        switch (Quality)
        {
            case ELCKVideoQuality::HD:
                return TEXT("Recommended for Quest 2. Best balance of quality and performance.");
            case ELCKVideoQuality::SD:
                return TEXT("Lower quality, but ensures smooth gameplay.");
        }
    }
    return TEXT("");
}
```

***

## Key Takeaways

<Check>**Quest 2: HD @ 30fps max** — thermal/power limits</Check>
<Check>**Quest 3/Pro: Up to 4K @ 60fps** — better cooling and hardware</Check>
<Check>**Auto-detect device** — apply appropriate overrides at runtime</Check>
<Check>**Monitor performance** — track frame times during recording</Check>
<Check>**Watch thermal state (Android)** — reduce quality if overheating</Check>
<Check>**Offer user presets** — Quality, Balanced, Performance</Check>
<Check>**Test on target devices** — editor performance ≠ device performance</Check>

***

## Related

* [Best Practices](/api-reference/unreal/best-practices) — General optimization tips
* [Enums Reference](/api-reference/unreal/enums) — ELCKVideoQuality enum values
* [Types Reference](/api-reference/unreal/types) — FLCKRecordingProfile struct
* [Architecture](/api-reference/unreal/architecture) — How platform detection works
