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

# Streaming Quick Start

> Get live streaming working in your Unreal Engine project with the LIV Camera Kit (LCK) SDK in five steps: enable, authenticate, stream, and handle events.

<Info>
  **Module:** LCKStreaming | **Version:** 1.0 | **Platforms:** Win64, Android (Quest)
</Info>

## Overview

This guide walks through enabling and using LCKStreaming from C++ in five steps. By the end, your game will authenticate with the LIV backend and stream to YouTube, Twitch, or a manual RTMP endpoint.

<Warning>
  Before you begin, ensure you have a LIV developer account, a valid Tracking ID, and an active streaming subscription. See the [Streaming Overview](/unreal/streaming/overview) for all prerequisites.
</Warning>

## Pairing to LIV Hub in Play In Editor mode

You must pair your game to LIV Hub on your Meta Quest. ie: LIV Hub doesn't need to be on the same device that you're pairing the game to.

1. In editor, while in play mode, go to the streaming tab to trigger the pairing code
2. In LIV Hub on the Meta Quest, pair your game via the LIV Camera Games section
3. Enter the pairing code in the editor

## Step 1: Enable Streaming

In **Project Settings → Plugins → LCK SDK → Features**, enable `bEnableStreaming`.

You can also set it in your `DefaultGame.ini`:

```ini theme={null}
[/Script/LCKCore.LCKDeveloperSettings]
bEnableStreaming=true
```

## Step 2: Add Module Dependencies

```csharp theme={null}
// YourProject.Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "LCKStreaming",
    "LCKCore"
});
```

## Step 3: Access the Subsystem

`ULCKStreamingSubsystem` is a `UGameInstanceSubsystem`. Access it from any point where you have a valid game instance.

```cpp theme={null}
#include "LCKStreamingSubsystem.h"

ULCKStreamingSubsystem* Streaming =
    GetGameInstance()->GetSubsystem<ULCKStreamingSubsystem>();
```

## Step 4: Authenticate and Stream

The minimum flow is: start login, wait for authentication, then start streaming.

```cpp theme={null}
void UMyStreamingManager::BeginStreaming()
{
    ULCKStreamingSubsystem* Streaming =
        GetGameInstance()->GetSubsystem<ULCKStreamingSubsystem>();

    if (!Streaming)
    {
        return;
    }

    // Bind delegates before starting login
    Streaming->OnPairingCodeReceived.AddDynamic(
        this, &UMyStreamingManager::HandlePairingCode);
    Streaming->OnAuthenticated.AddDynamic(
        this, &UMyStreamingManager::HandleAuthenticated);
    Streaming->OnStreamStarted.AddDynamic(
        this, &UMyStreamingManager::HandleStreamStarted);
    Streaming->OnStreamStopped.AddDynamic(
        this, &UMyStreamingManager::HandleStreamStopped);
    Streaming->OnStreamError.AddDynamic(
        this, &UMyStreamingManager::HandleStreamError);

    // Begin device pairing
    Streaming->StartLogin();
}

void UMyStreamingManager::HandlePairingCode(const FString& Code)
{
    // Display this code in your UI
    // User enters it at dashboard.liv.tv/pair
    UE_LOG(LogTemp, Log, TEXT("Pairing code: %s"), *Code);
}

void UMyStreamingManager::HandleAuthenticated()
{
    UE_LOG(LogTemp, Log, TEXT("Authenticated — starting stream"));

    ULCKStreamingSubsystem* Streaming =
        GetGameInstance()->GetSubsystem<ULCKStreamingSubsystem>();

    if (Streaming && Streaming->HasStreamingTarget())
    {
        Streaming->StartStreaming();
    }
}

void UMyStreamingManager::HandleStreamStarted()
{
    UE_LOG(LogTemp, Log, TEXT("Stream is live"));
}

void UMyStreamingManager::HandleStreamStopped()
{
    UE_LOG(LogTemp, Log, TEXT("Stream stopped"));
}

void UMyStreamingManager::HandleStreamError(const FString& ErrorMessage)
{
    UE_LOG(LogTemp, Error, TEXT("Stream error: %s"), *ErrorMessage);
}
```

## Step 5: Stop Streaming

```cpp theme={null}
void UMyStreamingManager::EndStreaming()
{
    ULCKStreamingSubsystem* Streaming =
        GetGameInstance()->GetSubsystem<ULCKStreamingSubsystem>();

    if (Streaming && Streaming->IsStreaming())
    {
        Streaming->StopStreaming();
    }
}
```

## Complete State Check Example

Use the state query methods to build your UI:

```cpp theme={null}
void UMyStreamingWidget::UpdateUI()
{
    ULCKStreamingSubsystem* Streaming =
        GetGameInstance()->GetSubsystem<ULCKStreamingSubsystem>();

    if (!Streaming)
    {
        return;
    }

    // Authentication state
    bool bLoggedIn = Streaming->IsAuthenticated();

    // Subscription check
    bool bCanStream = Streaming->HasActiveSubscription();

    // Target info
    bool bHasTarget = Streaming->HasStreamingTarget();
    FString TargetName = Streaming->GetStreamingTargetName(); // "YouTube", "Twitch", "Manual"

    // Stream state
    bool bIsLive = Streaming->IsStreaming();
    bool bIsStarting = Streaming->IsStartingOrStreaming();
}
```

## All Available Delegates

| Delegate                    | Signature                                                                             | When                           |
| --------------------------- | ------------------------------------------------------------------------------------- | ------------------------------ |
| `OnPairingCodeReceived`     | `FOnLCKPairingCodeReceived(const FString&, Code)`                                     | Pairing code ready for display |
| `OnAuthenticated`           | `FOnLCKAuthenticated()`                                                               | Login succeeded                |
| `OnStreamingConfigReceived` | `FOnLCKStreamingConfigReceived(ELCKStreamingTargetType, const FLCKUserSubscription&)` | Config loaded from server      |
| `OnStreamStarted`           | `FOnLCKStreamStarted()`                                                               | RTMP connection active         |
| `OnStreamStopped`           | `FOnLCKStreamStopped()`                                                               | Stream ended cleanly           |
| `OnStreamError`             | `FOnLCKStreamError(const FString&, ErrorMessage)`                                     | An error occurred              |
| `OnLoggedOut`               | `FOnLCKLoggedOut()`                                                                   | User logged out                |

<Tip>
  Always bind delegates before calling `StartLogin()` or `StartStreaming()` to avoid missing events that fire quickly.
</Tip>

## Troubleshooting

<AccordionGroup>
  <Accordion title="StartStreaming() returns false">
    1. Check `IsAuthenticated()` — the user must be logged in first
    2. Check `HasStreamingTarget()` — the streaming config must be loaded
    3. Check `HasActiveSubscription()` — an active subscription is required
    4. Verify `bEnableStreaming` is `true` in project settings
    5. Check `LogLCKStreaming` for detailed error output
  </Accordion>

  <Accordion title="Stream starts but drops immediately">
    1. Check `OnStreamError` for the error message
    2. Verify network connectivity to the RTMP ingest server
    3. Ensure the encoder is available (not locked by another process)
    4. The health check allows 2 consecutive failures before stopping — check logs for encoder health warnings
  </Accordion>

  <Accordion title="Pairing code never arrives">
    1. Verify network connectivity to `dashboard.liv.tv`
    2. Check that the Tracking ID is valid
    3. Look for errors in `LogLCKStreaming`
  </Accordion>
</AccordionGroup>

## See Also

<CardGroup cols={2}>
  <Card title="Streaming Overview" icon="signal-stream" href="/unreal/streaming/overview">
    Architecture and platform details
  </Card>

  <Card title="Authentication" icon="lock" href="/unreal/streaming/authentication">
    Detailed authentication and pairing guide
  </Card>

  <Card title="Recording" icon="circle-dot" href="/unreal/core-sdk/recording">
    Record locally while streaming
  </Card>
</CardGroup>
