This quickstart assumes your backend can return a Live WebSocket URL and ticket. Keep App credentials server-side; the browser should receive only the Live entrance URL, ticket, and optional voice sign data required for the current room.
Install
npm install @realsee/live@0.7.6 react@18 trtc-js-sdk amazon-chime-sdk-js @realsee/jsbridge-xThe browser-only co-viewing path can start with @realsee/live@0.7.6 and react@18. Add trtc-js-sdk, amazon-chime-sdk-js, or @realsee/jsbridge-x when you use the built-in RTC implementations.
Create the instance
The generic form is createLive<MyKeyframes>. The generic maps each keyframe channel to the serializable state shape your app will synchronize.
import { createLive, LiveState } from '@realsee/live'
interface MyKeyframes {
FiveState: unknown
activePoi: { id: string; title: string } | null
}
const live = createLive<MyKeyframes>({
getTicket: async () => {
const response = await fetch('/api/live/ticket')
const payload = await response.json()
return payload.ticket
},
__debug__: import.meta.env.DEV,
})
live.on('stateChange', (state, prevState) => {
console.log({ state, prevState })
})
await live.connect({
url: 'wss://ws-access.realsee.com/.../room',
force: true,
})
if (live.state === LiveState.OPEN) {
live.sendKeyframe('activePoi', null)
}live.connect(options?) accepts url, force, getTicket, and rtcMicStatus. The package also supports passing url and getTicket to createLive; when both are present the instance can auto-connect.
React integration
Use createLiveReact<MyKeyframes> when your controls are React components. It creates a LiveProvider, action hooks, keyframe hooks, and state hooks around one Live instance.
import { createLiveReact } from '@realsee/live'
interface MyKeyframes {
FiveState: unknown
activePoi: { id: string; title: string } | null
}
export const LiveReact = createLiveReact<MyKeyframes>({
getTicket: async () => {
const response = await fetch('/api/live/ticket')
return response.json().then((payload) => payload.ticket)
},
})
export function LiveRoot({ children }: { children: React.ReactNode }) {
return <LiveReact.LiveProvider>{children}</LiveReact.LiveProvider>
}
export function ConnectButton({ wsUrl }: { wsUrl: string }) {
const { connect } = LiveReact.useLiveAction()
return (
<button onClick={() => connect({ url: wsUrl, force: true })}>
Join live room
</button>
)
}Clean up
Call live.exit() when the current user leaves the room. Call live.close() when the room owner closes the room for everyone. Call live.dispose() when the page or React tree is unmounted and the instance should not be reused.
window.addEventListener('beforeunload', () => {
void live.dispose()
})Backend boundary
Ticket and voice sign endpoints must be same-origin endpoints in your app:
GET /api/live/ticketreturns the ticket used bygetTicket.POST /api/live/voice-signreturns the voice sign used bygetVoiceSign.- OpenAPI app keys and app secrets stay on the server.
See OpenAPI for the credential model and Team app management for app request review.
