Manage live streams
Create, schedule, start, stop and decorate live streams from your app through
liveStreamRepository.
Prerequisites
net.bunny:apidependencyBunnyStreamApi.initialize(...)called, see Getting started- All repository methods are
suspend- call them from a coroutine
val repo = BunnyStreamApi.getInstance().liveStreamRepository
Every method returns BunnyResult<T> — Ok with the value or Err with a typed
BunnyError. See Handle errors for the taxonomy and the terminal/transient
split.
Create a stream
val result = repo.createLiveStream(
libraryId = 12345L,
request = LiveStreamCreateRequest(
title = "Friday Q&A", // required by the API
scheduledStartTime = "2026-08-01T18:00:00Z", // optional, ISO 8601
enableCountdown = true, // show a countdown before the start
dvrEnabled = true, // viewers can pause and seek back
dvrWindowSeconds = 1800, // how far back
recordVod = true, // keep a recording after the stream ends
preStreamTrailerVideoId = "trailer-video-guid", // optional, loops before the start
),
)
result.fold(
onOk = { stream -> /* stream.id, stream.streamKey, stream.primaryIngestUrl */ },
onErr = { error -> /* show error.message; error.isTerminal says whether to retry */ },
)
The created stream carries everything a broadcaster needs: streamKey, primaryIngestUrl,
backupIngestUrl and up to four restream outputs (rtmpOutputs).
List, read, update, delete
repo.listLiveStreams(libraryId, page = 1, itemsPerPage = 20, search = "q&a")
repo.getLiveStream(libraryId, streamId)
// Update reuses the create request; only non-null fields are sent, the rest stays unchanged.
repo.updateLiveStream(libraryId, streamId, LiveStreamCreateRequest(title = "New title"))
repo.deleteLiveStream(libraryId, streamId)
Deleting is permanent, but a recorded VOD survives the stream that produced it.
Start and stop
repo.startLiveStream(libraryId, streamId) // PREVIEW -> RUNNING, viewers can watch
repo.stopLiveStream(libraryId, streamId) // ends the stream; converts to VOD when recordVod is set
You only call these when driving a broadcast yourself (for example with an external encoder). The camera view from Go live from the camera starts and stops the stream for you.
A stream's life: created (or scheduled) -> an encoder connects (PREVIEW) -> started (RUNNING) -> stopped (ENDED, then VOD_PROCESSING when it records). An ended stream cannot be restarted.
Watching the status
Poll with pollLiveStream when you need the state cheaply and repeatedly (a lobby screen, a
"stream starts soon" page):
when (val result = repo.pollLiveStream(libraryId, streamId)) {
is BunnyResult.Ok -> render(result.value.status)
is BunnyResult.Err ->
if (result.isTerminal) stopPolling() // 401/403/404/410: gone for good
else Unit // transient (5xx, network): keep polling
}
The players do this internally; you rarely need it next to a player.
Thumbnails
repo.listLiveStreamThumbnails(libraryId, streamId, limit = 24) // generated preview thumbnails
repo.setLiveStreamThumbnail(libraryId, streamId, url) // pick one
repo.uploadLiveStreamThumbnail(libraryId, streamId, bytes, "image/jpeg") // or upload your own
repo.deleteLiveStreamThumbnail(libraryId, streamId, restoreLibraryDefault = true)
The thumbnail shows in the player before the stream starts and when the encoder disconnects.
Pre-stream trailer
The trailer is a normal video from your library, referenced at create or update time through
preStreamTrailerVideoId. The player loops it (muted) before the stream starts; it takes
priority over the thumbnail.
Gotchas
titleis required on create.- Dates are ISO 8601 strings; include a timezone (
Zor an offset). - Restream outputs (
rtmpOutputs, up to 4) are accepted by the API but the feature may not be enabled for your account yet; a non-empty list can be rejected server-side.
Working example: LiveStreamsScreen and LiveStreamEditorScreen in the
demo app.