This page covers SDK room broadcasting APIs. Camera, microphone, LiveKit client setup, permissions, and media publishing UI are app-owned concerns after the SDK returns broadcaster data.
Platform Surface
| Platform | Get broadcaster data | Observe lifecycle | Stop broadcast | Notes |
|---|---|---|---|---|
| TypeScript | RoomRepository.getBroadcasterData(roomId) | RoomRepository.onRoomStartBroadcasting(...), onRoomEndBroadcasting(...), or getRoom(...) | RoomRepository.stopRoom(roomId) | Amity.BroadcasterData can include coHostToken, coHostUrl, and directStreamUrl. |
| iOS | AmityRoomRepository().generateRoomToken(withId:) | AmityRoomRepository().getRoom(withId:) live object | AmityRoomRepository().stopRoom(withId:) | Token response is a dictionary from /api/v1/rooms/{roomId}/token; read known keys defensively. |
| Android | AmityVideoClient.newRoomRepository().getBroadcasterData(roomId) | getRoom(roomId) plus room topic subscription when real-time updates are needed | stopRoom(roomId) | Returns AmityRoomBroadcastData.CoHosts or AmityRoomBroadcastData.DirectStreaming. |
| Flutter | No current public room broadcaster API found in this audit | Not available | Not available | The Flutter SDK source exposes older stream read APIs, not the room broadcasting repository. |
Parameters
| Concept | Platforms | TypeScript | iOS | Android | Notes |
|---|---|---|---|---|---|
| Fetch credentials | TypeScript, iOS, Android | getBroadcasterData(roomId) | generateRoomToken(withId:) | getBroadcasterData(roomId) | Requires an existing room ID. |
| Co-host URL | TypeScript, iOS, Android | coHostUrl?: string | tokenPayload["coHostUrl"] | AmityRoomBroadcastData.CoHosts.getCoHostUrl() | Use as the media connection URL for co-host rooms. |
| Co-host token | TypeScript, iOS, Android | coHostToken?: string | tokenPayload["coHostToken"] | AmityRoomBroadcastData.CoHosts.getCoHostToken() | Use as the media access token for co-host rooms. |
| Direct stream URL | TypeScript, iOS, Android | directStreamUrl?: string | tokenPayload["directStreamUrl"] | AmityRoomBroadcastData.DirectStreaming.getDirectStreamUrl() | Use only for direct-streaming publisher flows. |
| Flutter room broadcasting | Flutter | Not applicable | Not applicable | Not applicable | No current public Flutter room broadcaster API found in this audit. |
Lifecycle Parameters
| Concept | Platforms | TypeScript | iOS | Android |
|---|---|---|---|---|
| Start event | TypeScript, iOS, Android | onRoomStartBroadcasting(callback) | Observe AmityRoom.status via getRoom(withId:) | Observe getRoom(roomId) and subscribe to AmityRoomEvents.STREAMER when needed |
| End event | TypeScript, iOS, Android | onRoomEndBroadcasting(callback) | Observe AmityRoom.status via getRoom(withId:) | Observe getRoom(roomId) and subscribe to AmityRoomEvents.STREAMER when needed |
| Stop room | TypeScript, iOS, Android | stopRoom(roomId) | stopRoom(withId:) | stopRoom(roomId) |
| Cleanup | TypeScript, iOS, Android | Call returned Amity.Unsubscriber functions | Retain and release the AmityNotificationToken with the screen lifecycle | Dispose Rx subscriptions and unsubscribe room topics when no longer needed |
Get Broadcaster Data
Call this after the room exists and before connecting your app-owned media client. Co-host rooms usecoHostUrl and coHostToken; direct-streaming rooms use directStreamUrl.
import { RoomRepository } from "@amityco/ts-sdk";
async function getBroadcastCredentials(roomId: string) {
const credentials = await RoomRepository.getBroadcasterData(roomId);
if (credentials.coHostUrl && credentials.coHostToken) {
return {
mode: "coHosts" as const,
url: credentials.coHostUrl,
token: credentials.coHostToken,
};
}
if (credentials.directStreamUrl) {
return {
mode: "directStreaming" as const,
directStreamUrl: credentials.directStreamUrl,
};
}
throw new Error("No broadcaster credentials returned for this room.");
}
import com.amity.socialcloud.sdk.api.video.AmityVideoClient
import com.amity.socialcloud.sdk.model.video.room.AmityRoomBroadcastData
val disposable = AmityVideoClient.newRoomRepository()
.getBroadcasterData(roomId)
.subscribe(
{ broadcastData ->
when (broadcastData) {
is AmityRoomBroadcastData.CoHosts -> {
showSuccessMessage(broadcastData.getCoHostUrl())
showSuccessMessage(broadcastData.getCoHostToken())
}
is AmityRoomBroadcastData.DirectStreaming -> {
showSuccessMessage(broadcastData.getDirectStreamUrl())
}
}
},
{ error -> handleGeneralError(error) }
)
let tokenPayload = try await AmityRoomRepository()
.generateRoomToken(withId: roomId)
if let coHostUrl = tokenPayload?["coHostUrl"] as? String,
let coHostToken = tokenPayload?["coHostToken"] as? String {
showSuccessMessage(coHostUrl)
showSuccessMessage(coHostToken)
} else if let directStreamUrl = tokenPayload?["directStreamUrl"] as? String {
showSuccessMessage(directStreamUrl)
}
Hand Credentials to Your Media Client
The SDK does not publish camera or microphone tracks. Use the returned URL/token with your media client, then let that client own connection, preview, mute, retry, and device-selection behavior.import { RoomRepository } from "@amityco/ts-sdk";
type ExternalMediaClient = {
connect: (url: string, token: string) => Promise<void>;
publishCamera: () => Promise<void>;
};
async function startCoHostBroadcast(
roomId: string,
mediaClient: ExternalMediaClient,
) {
const data = await RoomRepository.getBroadcasterData(roomId);
if (!data.coHostUrl || !data.coHostToken) {
throw new Error("This room did not return co-host broadcaster credentials.");
}
await mediaClient.connect(data.coHostUrl, data.coHostToken);
await mediaClient.publishCamera();
}
import com.amity.socialcloud.sdk.api.video.AmityVideoClient
import com.amity.socialcloud.sdk.model.video.room.AmityRoomBroadcastData
import io.reactivex.rxjava3.core.Completable
fun connectExternalMedia(url: String, token: String): Completable {
showSuccessMessage(url)
showSuccessMessage(token)
return Completable.complete()
}
fun publishExternalCamera(): Completable = Completable.complete()
val disposable = AmityVideoClient.newRoomRepository()
.getBroadcasterData(roomId)
.flatMapCompletable { broadcastData ->
when (broadcastData) {
is AmityRoomBroadcastData.CoHosts -> {
connectExternalMedia(
url = broadcastData.getCoHostUrl(),
token = broadcastData.getCoHostToken()
).andThen(publishExternalCamera())
}
is AmityRoomBroadcastData.DirectStreaming -> {
Completable.error(
IllegalStateException("Use directStreamUrl with your RTMP publisher.")
)
}
}
}
.subscribe(
{ showSuccessMessage(roomId) },
{ error -> handleGeneralError(error) }
)
func connectExternalMedia(url: String, token: String) async throws {
showSuccessMessage(url)
showSuccessMessage(token)
}
func publishExternalCamera() async throws {
showSuccessMessage("camera")
}
let tokenPayload = try await AmityRoomRepository()
.generateRoomToken(withId: roomId)
guard let coHostUrl = tokenPayload?["coHostUrl"] as? String,
let coHostToken = tokenPayload?["coHostToken"] as? String else {
throw NSError(domain: "Broadcast", code: 0)
}
try await connectExternalMedia(url: coHostUrl, token: coHostToken)
try await publishExternalCamera()
Observe Broadcast Lifecycle
Use lifecycle updates to keep host UI, viewer entry points, and moderation tools aligned with the room status.import { RoomRepository } from "@amityco/ts-sdk";
function observeBroadcastLifecycle(roomId: string): Amity.Unsubscriber {
const stopStarted = RoomRepository.onRoomStartBroadcasting(room => {
if (room.roomId === roomId) {
showSuccessMessage(room.status);
}
});
const stopEnded = RoomRepository.onRoomEndBroadcasting(room => {
if (room.roomId === roomId) {
showSuccessMessage(room.status);
}
});
return () => {
stopStarted();
stopEnded();
};
}
import com.amity.socialcloud.sdk.api.video.AmityVideoClient
import com.amity.socialcloud.sdk.model.core.events.AmityRoomEvents
val roomRepository = AmityVideoClient.newRoomRepository()
val roomDisposable = roomRepository
.getRoom(roomId)
.subscribe(
{ room -> showSuccessMessage(room.getStatus()) },
{ error -> handleGeneralError(error) }
)
val topicDisposable = roomRepository
.getRoom(roomId)
.firstOrError()
.flatMapCompletable { room ->
room.subscription(AmityRoomEvents.STREAMER).subscribeTopic()
}
.subscribe(
{ showSuccessMessage(roomId) },
{ error -> handleGeneralError(error) }
)
var roomObservationToken: AmityNotificationToken?
let roomObject = AmityRoomRepository().getRoom(withId: roomId)
roomObservationToken = roomObject.observe { liveObject, error in
if let error {
handleGeneralError(error)
return
}
if let room = liveObject.snapshot {
showSuccessMessage(room.status.rawValue)
}
}
showSuccessMessage(roomObservationToken != nil)
Stop the Broadcast
Stop the room when the host ends the session. Disconnect your media client separately, then call the SDK stop API so social.plus room state and viewer surfaces can move out of the live state.import { RoomRepository } from "@amityco/ts-sdk";
async function stopBroadcast(roomId: string) {
const { data: stoppedRoom } = await RoomRepository.stopRoom(roomId);
showSuccessMessage(stoppedRoom.status);
}
import com.amity.socialcloud.sdk.api.video.AmityVideoClient
val disposable = AmityVideoClient.newRoomRepository()
.stopRoom(roomId)
.subscribe(
{ showSuccessMessage(roomId) },
{ error -> handleGeneralError(error) }
)
let stoppedRoom = try await AmityRoomRepository()
.stopRoom(withId: roomId)
showSuccessMessage(stoppedRoom.status.rawValue)
Stopping a room ends the current broadcast session. Do not build a “restart the same room” flow unless your product and backend contract explicitly support it.
Media Boundary
| Area | Owned by social.plus SDK | Owned by your app/media stack |
|---|---|---|
| Room record | Create, observe, update, stop, delete | Product routing and host controls |
| Credentials | Return room broadcaster fields | Store only in memory and hand to the media client |
| Publishing | Not handled by social.plus SDK room APIs | Camera, microphone, preview, mute, reconnect, and permissions |
| Viewer state | Room status, live playback fields, recorded metadata | Player UI and playback SDK behavior |
Related Topics
Create Room
Create the room before fetching broadcaster credentials.
Co-Host Management
Invite, observe, and manage co-hosts before or during the broadcast.
Live Viewing
Show viewers how to watch active room broadcasts.