Live streams
One person presents live to everyone watching: the picture, a chat beside it, reactions, and the count of who watches. In cloud.wordplus:realtime-calls, on the same media servers as the browser: an app watches a stream a browser presents, and goes live itself.
Who is who
Your server declares streams by pattern, as it declares rooms and calls (live streams in depth):
- Node
- PHP
- Python
realtime.streams( 'show:{id}', ( user ) => ( user === ANN ? 'host' : 'viewer' ), { reactions: true } );
$realtime->streams( 'show:{id}', fn ( $user ) => ANN === $user ? 'host' : 'viewer', [ 'reactions' => true ] );
realtime.streams("show:{id}", lambda user: "host" if user == ANN else "viewer", reactions=True)
The app asks the calls route of your server, as for calls: nothing more to add.
Watching
import cloud.wordplus.realtime.calls.LiveStreamVideoView
import cloud.wordplus.realtime.calls.calls
import cloud.wordplus.realtime.calls.stream
// In a coroutine on the main thread, such as one of lifecycleScope.
val show = rt.calls(context).stream("show:mugs")
val player = LiveStreamVideoView(context)
player.show(show) // the main picture of the stream as it changes, its sound plays by itself
show.onChange { // the state, the count, the chat, the pictures
state.text = if (show.state == LiveStreamState.LIVE) "Live now" else "Not live"
count.text = "${show.viewers} watching"
}
show.onMessage { message -> add(message.name, message.text) }
show.send("Hello!")
show.react(LiveStreamReaction.HEART)
show.leave()
stateisIDLE,LIVEorENDED.mediais where the app is in the room of the stream:OFF,CONNECTING,LIVE,RECONNECTING.- The main picture is the one the host chose: a shared screen, the picture from OBS, else the camera of the host.
show.tileshas each picture, andplayer.show(show, tile = identity)draws one of them. Callplayer.release()once the view leaves the screen for good. - The chat:
messages(the history, oldest first),pinned,canWrite,slow. Each message has the app user id of who wrote it, null for a visitor. onEndedsays why the app is out of the stream:left,banned,kicked.
In Compose, put the player in an AndroidView, and read the state of the stream from a counter that onChange raises, as the example app does.
Going live
The app of the host shows its camera, then goes live:
show.preview() // the camera and microphone, in the same LiveStreamVideoView
show.setCamera(false) // or setMicrophone(on)
show.goLive()
show.end()
- The camera and microphone need
CAMERAandRECORD_AUDIO, asked for at runtime beforepreview(), as for calls. goLive()with nothing on turns the camera and microphone on first.- What a role may not do throws a
CallExceptionwith its code:not_host,read_only,slow,timeout. - From OBS:
val (url, key) = show.ingest().ingest(renew = true)makes a new key and cuts off the old one.
Keeping the chat
The host, and anyone the rule made mod: deleteMessage(id), pin(id), unpin(), timeout(user, seconds) (from a minute to a day, they go on watching), setSlow(seconds), clearChat(), kick(user) (out now, they may come back) and ban(user).
The show card of the Example Shop watches the show of Ann from the app: the example app.