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

# TTSDK player

> Hand a TTSDK engine (TTVideoEngine) to the SDK with so.kontext:video-ttsdk.

The SDK follows your content player: where the viewer is in the episode, and whether the content plays. An overlay shows over playing content only and ends when the viewer pauses; a pause ad ends when the content plays again. With a TTSDK player (`TTVideoEngine`, the BytePlus / Volcengine VOD player SDK), one call gives the SDK all of that.

## Add the adapter

```kotlin theme={null}
dependencies {
    implementation("so.kontext:video:0.1.0")
    implementation("so.kontext:video-ttsdk:0.1.0")
}
```

* **TTSDK 1.40 or later.**
* **TTSDK is not included.** The adapter uses your app's own TTSDK, with your license; it adds no TTSDK artifact and no repository to your build.

## Track the engine

```kotlin theme={null}
import so.kontext.video.ttsdk.track

ads.track(engine)
```

Call it once the engine has the episode's source (`setStrategySource`, `setVideoID`, …), when the episode starts. The SDK holds the engine weakly and lets go at `ads.destroy()` or the next `track`.

**Your callback stays yours.** The adapter listens with `addVideoEngineCallback`, next to the callback you set with `setVideoEngineCallback`, and removes its own when it lets go. An overlay ends the moment the viewer pauses.

## In a feed

Short-drama feeds usually give each page its own engine, or hand a page an engine TTSDK pre-rendered for it. Give each page its own `VideoAds`, and track the page's engine when the page becomes current:

```kotlin theme={null}
override fun onPageSelected(page: Int) {
    val item = pages[page]
    item.ads.track(item.engine)        // this page's engine, pre-rendered or not
}
```

Show an overlay or pause ad on the current page only. A page swiped away with its ad on screen ends that ad within about a second (`INTERRUPTED`), so the next page's ad can show.

## The playback speed

TTSDK has no getter for the speed. When the viewer changes it, tell the SDK, so an overlay's duration counts video seconds correctly:

```kotlin theme={null}
ads.track(engine) { currentSpeed }     // read when the SDK needs it
```

Without it, the SDK accepts playback up to about 4× and takes a bigger jump for a seek.

## What the SDK reads

| The SDK needs | Read from TTSDK |
| - | - |
| Where the content is | `getCurrentPlaybackTime()`, in milliseconds |
| Whether it plays | `getPlaybackState()` is playing. Paused or stopped by the viewer or your app is not playing; buffering is. |
| Another episode | another `getVideoID()` on the same engine, or the end of the video (`onCompletion`): a replay after the end is another play |
| A seek | inferred from the position: TTSDK does not report seeks |

An overlay or pause ad of a `VideoAds` then throws `Invalidated(ContentChanged)` at `show` once its engine plays another video. An engine playing a URL without a vid is still followed; only that check is skipped.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.