> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://fastpix.com/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://fastpix.com/docs/_mcp/server.

# Add seek preview thumbnails

> Learn how to show spritesheet-based thumbnail previews during seek bar scrubbing in the FastPix Android Player.

Learn how to show spritesheet-based thumbnail previews during seek bar scrubbing in the FastPix Android Player.

Seek preview shows thumbnail previews while the user scrubs the seek bar. The SDK resolves spritesheets automatically for FastPix streams using the URL pattern `https://images.fastpix.com/{playbackId}/spritesheet.json`.

## Enable seek preview

Configure seek preview when building the player:

```kotlin
val seekPreviewConfig = SeekPreviewConfig.Builder()
    .setEnabled(true)
    .setFallbackMode(PreviewFallbackMode.TIMESTAMP) // or NONE
    .setEnablePreload(true)
    .setPreloadRadius(1)
    .setCacheEnabled(true)
    .build()

val player = FastPixPlayer.Builder(context)
    .setSeekPreviewConfig(seekPreviewConfig)
    .build()
```

## Fallback modes

If the spritesheet doesn't exist, or the media is not a FastPix stream, the SDK falls back:

* **`TIMESTAMP`**: Shows a time label (for example, `"02:30"`). `SpritesheetMetadata.bitmap` may be null.
* **`NONE`**: Shows nothing.

## Listen for preview events

```kotlin
player.setSeekPreviewListener(object : SeekPreviewListenerAdapter() {
    override fun onSpritesheetInitialized() {
        // Spritesheet metadata is available and preview can be used
    }
    override fun onSpritesheetFailed(error: Throwable) {
        // Spritesheet unavailable; fallback may still work depending on config
    }
    override fun onPreviewShow() {
        // Show your preview container
    }
    override fun onPreviewHide() {
        // Hide your preview container
    }
    override fun onSpritesheetLoaded(metadata: SpritesheetMetadata) {
        // metadata.bitmap: bitmap for current position (can be null in timestamp fallback)
        // metadata.timestampMs: current seek timestamp (ms)
        // Additional fields: rows, columns, frameWidth, frameHeight, frameCount,
        // durationMs, intervalMs (distance between frames)
    }
})
```

## Connect to a SeekBar

Wire the preview to your SeekBar's touch events:

```kotlin
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
    override fun onStartTrackingTouch(seekBar: SeekBar) {
        player.showPreview()
    }
    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
        if (fromUser) {
            player.loadPreview(progress.toLong()) // progress in ms
        }
    }
    override fun onStopTrackingTouch(seekBar: SeekBar) {
        player.hidePreview()
        player.seekTo(seekBar.progress.toLong())
    }
})
```

## Fetch preview bitmaps directly

If you're building a custom preview UI, you can request bitmaps directly from a coroutine:

```kotlin
val bmp = player.getPreviewBitmap(timeMs = 30_000)
val label = player.formatTimestamp(timeMs = 30_000)
```