UNPKG

@api.stream/studio-kit

Version:

Client SDK for building studio experiences with API.stream

448 lines (447 loc) 15.2 kB
import { CoreContext } from '../core/context'; import { Compositor, SDK } from '../core/namespaces'; import { Banner, BannerProps, BannerSource } from '../core/sources/Banners'; import { RoomParticipantSource } from '../core/sources/WebRTC'; import { ChatOverlayProps } from '../core/transforms/ChatOverlay'; import { Disposable, VideoRendering } from '../core/types'; import { BackgroundProps } from './../core/transforms/Background'; import { LogoProps } from './../core/transforms/Logo'; import { OverlayProps } from './../core/transforms/Overlay'; import { AlertOverlayProps } from './../core/transforms/Alert'; import LayoutName = Compositor.Layout.LayoutName; import { LiveApiModel } from '@api.stream/sdk'; export type { LayoutName }; export type { Banner, BannerSource, RoomParticipantSource }; export type ParticipantProps = { volume: number; isMuted: boolean; isHidden: boolean; isAudioOnly: boolean; }; export type HTMLVideoElementAttributes = { loop?: boolean; autoplay?: boolean; muted?: boolean; playsinline?: boolean; disablepictureinpicture?: boolean; }; type CreateSourceProps = { displayName?: string; address?: Partial<LiveApiModel.Source['address']>; props?: any; }; type GenerateGameSourceProps<T extends LiveApiModel.Source> = { address: T['address'] extends { dynamic: LiveApiModel.Source['address']['dynamic']; } ? { dynamic: { id: 'integration'; }; } : never; displayName?: string; props?: any; }; type CreateGameSourceProps = GenerateGameSourceProps<LiveApiModel.Source>; export type ParticipantType = 'camera' | 'screen'; declare const ExternalSourceTypeMap: { readonly rtmp: "RTMP"; readonly game: "Game"; }; export type ExternalSourceType = keyof typeof ExternalSourceTypeMap; interface ScenelessProject extends SDK.Project { } /** * These commands assist with management of WebRTC {@link Participant Participants}, * custom layouts, backgrounds, and overlay content. * * Only a valid {@link ScenelessProject} can leverage these commands. */ export interface Commands { /** * Get the node that holds the stream's background * @private */ getBackground(): Compositor.SceneNode; /** * Get the node that holds the stream's content * @private */ getContent(): Compositor.SceneNode; /** * Get the node that holds the stream's foreground (overlays) * @private */ getForeground(): Compositor.SceneNode; /** * Get the active layout * @private */ getLayout(): string; /** * Get all banners stored on the project */ getBanners(): Banner[]; /** * Get all participants in the project * @private */ getParticipants(): Compositor.SceneNode[]; /** * play video overlay on foreground * @private */ autoPlayVideoOverlay(overlayId: string, attributes: HTMLVideoElementAttributes): void; /** * play background Video * @private */ autoPlayBackgroundVideo(attributes?: HTMLVideoElementAttributes): void; /** * Remove logo from stream */ removeLogo(): Promise<void>; /** * Add logo on stream * @param id * @param logo */ addLogo(id: string, logo: LogoProps): Promise<void>; /** * Get active logo */ getLogo(): string; /** * Add an chat comment to the stream. */ addChatOverlay(id: string, Options: ChatOverlayProps): void; /** * Add an any exisiting chat comment from the stream. */ removeChatOverlay(id: string): void; /** * get the active chat comment to the stream. */ getChatOverlay(): ChatOverlayProps | null; /** * Set the active layout and associated layoutProps */ setLayout(layout: LayoutName, layoutProps: LayoutProps): void; /** * Set the active background image */ getBackgroundMedia(): string; /** * Get the active background image */ getBackgroundImage(): string; /** * Get the active background video */ getBackgroundVideo(): string; /** * remove the active video overlay */ removeBackgroundImage(): Promise<void>; /** * remove the active image overlay */ removeBackgroundVideo(): Promise<void>; /** Set the active background image */ setBackgroundImage(id: string, props: BackgroundProps): Promise<void>; /** * Set the active background video */ setBackgroundVideo(id: string, props: BackgroundProps & HTMLVideoElementAttributes): Promise<void>; updateBackgroundVideoProps(id: string, props: BackgroundProps & HTMLVideoElementAttributes): Promise<void>; getImageOverlay(): string | null; /** * Get the active video overlay */ getVideoOverlay(): string | null; /** * Get the active foreground image overlay */ getCustomOverlay(): string | null; /** * Set the active foreground image overlay */ addImageOverlay(overlayId: string, props: OverlayProps): Promise<void>; /** * set image overlay on foreground video layer */ addVideoOverlay(overlayId: string, props: OverlayProps & HTMLVideoElementAttributes): Promise<void>; updateVideoOverlayProps(id: string, props: OverlayProps & HTMLVideoElementAttributes): Promise<void>; /** * add html alert overlay */ addAlertOverlay(id: string, props: AlertOverlayProps): Promise<void>; /** * remove html alert overlay from foreground layer */ removeAlertOverlay(): Promise<void>; /** * add html overlay */ addCustomOverlay(id: string, props: OverlayProps): Promise<void>; /** * remove video overlay from foreground layer */ removeCustomOverlay(id: string): Promise<void>; /** * remove the active video overlay */ removeVideoOverlay(): Promise<void>; /** * remove the active image overlay */ removeImageOverlay(): Promise<void>; useLayerState<T>(sourceType: string, cb: (state: T) => void): void; /** Set one participant to "showcase". This participant will expand to fill * the space of the stream without affecting the underlying layout. */ setShowcase(participantId: string, /** @default `'camera'` */ type?: ParticipantType): ReturnType<typeof CoreContext.Command.updateNode>; /** * @hook * Receive information about the showcased participant. * As with other hooks, the callback will be invoked when its value changes. */ useShowcase(cb: (state: { participantId: string; type: ParticipantType; }) => void): Disposable; /** * Add an RTMP or GAME Source to the canvas */ addSourceNode(id: string, props: Partial<ParticipantProps>, type?: ExternalSourceType): Promise<void>; /** * Remove an RTMP or GAME source from the canvas */ removeSourceNode(id: string): Promise<void>; /** * @private * Get the node associated with an RTMP or GAME Source */ getSourceNode(id: string): Compositor.SceneNode; /** * Use the RTMP or GAME nodes that are on currently on stage. */ useSourceNodes(cb: (nodes: Compositor.SceneNode[]) => void, type: ExternalSourceType): Disposable; /** * Change a source node's volume. * This does not affect the underlying MediaStreamTrack. */ setSourceNodeVolume(id: string, volume: number): void; /** * Mute a source node without changing its volume. * This does not affect the underlying MediaStreamTrack. */ setSourceNodeMuted(id: string, isMuted: boolean): void; /** * Add a participant camera track to the stream canvas. * Available participants can be gleaned from the WebRTC {@link Room} using * {@link Room.useParticipants}. * * A participant will remain on stream even if there is no active feed, until * it is removed using {@link removeParticipantTrack removeParticipantTrack()} or {@link pruneParticipants pruneParticipants()}. */ addParticipantTrack(trackId: string, props: Partial<ParticipantProps>, /** * The type of participant feed to add. * @default `'camera'` */ type?: ParticipantType): Promise<void>; /** * Remove a stream participant from the stream canvas. */ removeParticipantTrack(trackId: string, type?: ParticipantType): void; /** * Add a participant to the stream canvas. * Available participants can be gleaned from the WebRTC {@link Room} using * {@link Room.useParticipants}. * * A participant will remain on stream even if there is no active feed, until * it is removed using {@link removeParticipant removeParticipant()} or {@link pruneParticipants pruneParticipants()}. */ addParticipant(participantId: string, props: Partial<ParticipantProps>, /** * The type of participant feed to add. * @default `'camera'` */ type?: ParticipantType): Promise<void>; /** * Remove a stream participant from the stream canvas. */ removeParticipant(participantId: string, type: ParticipantType): void; /** * @private * Get the node associated with a room participant * */ getParticipantNode(id: string, /** @default `'camera'` */ type?: ParticipantType | ExternalSourceType): Compositor.SceneNode; /** * Get {@link ParticipantProps} associated with a participant/type. */ getParticipantState(participantId: string, /** @default `'camera'` */ type?: ParticipantType | ExternalSourceType): ParticipantProps; /** * @hook * Receive {@link ParticipantProps} associated with a participant/type * via invoked callback anytime one of the property values changes. */ useParticipantState(participantId: string, cb: (state: ParticipantProps) => void, /** @default `'camera'` */ type?: ParticipantType | ExternalSourceType): Disposable; /** * Change a participant's volume. * This does not affect the underlying MediaStreamTrack. */ setParticipantVolume(participantId: string, /** * Accepted values from [0 - 1] */ volume: number, type?: ParticipantType | ExternalSourceType): void; /** * Mute a participant without changing their volume. * This does not affect the underlying MediaStreamTrack. * * Participants muted in this way will not stop sending * audio data, but it will not play on the receiving end. * * A host may use this to override a guest's settings * for the stream output. */ setParticipantMuted(participantId: string, isMuted: boolean, /** @default `camera` */ type?: ParticipantType | ExternalSourceType): void; /** * Hide a participant video feed from the stream. * This does not affect the underlying MediaStreamTrack. * * Participants hidden in this way will not stop sending * video data, but it will not play on the receiving end. * * A host may use this to override a guest's settings * for the stream output. */ setParticipantHidden(participantId: string, isHidden: boolean, /** @default `camera` */ type?: ParticipantType | ExternalSourceType): void; setParticipantAudioOnly(participantId: string, isAudioOnly: boolean, /** @default `camera` */ type?: ParticipantType | ExternalSourceType): void; /** * Remove all participants from the stream canvas who are not actively * sending a MediaStreamTrack for display. */ pruneParticipants(): void; /** * Create and store a banner on the project. * * Does not add the banner to the stream. */ addBanner(props: BannerProps): void; /** * Edit a banner on the project. */ editBanner(id: string, props: BannerProps): void; /** * Remove a banner from the project. */ removeBanner(id: string): void; /** * Fetch the active banner displayed on stream. */ getActiveBanner(): string | null; /** * Add an existing banner to the stream. * If no `id` is supplied, existing banners will be removed. */ setActiveBanner(id: string): void; /** * Get an arbitrary property from the project (`project.props{}`) */ getProp(props: string): any; /** * Set an arbitrary property on the project (`project.props{}`) */ setProp(props: string, val: any): void; /** * Use the latest value of an arbitrary property on the project (`project.props{}`) */ useProp(props: string, cb: (val: any) => void): void; /** * Add a source TEMPORARY */ createSource(props?: CreateSourceProps): Promise<LiveApiModel.Source>; /** * Remove a source TEMPORARY */ deleteSource(sourceId: string): void; /** * Add a source for type "integration" */ createGameSource(props: CreateGameSourceProps): Promise<LiveApiModel.Source>; /** * Update the layout props of a node */ updateLayoutProps(nodeId: string, layout: LayoutName, layoutProps: LayoutProps): Promise<void>; /** * Get the current video rendering properties of the project. */ getVideoRendering(): VideoRendering; /** * Update the video rendering properties of the project. This includes height, width, framerate, and/or colorspace. */ updateVideoRendering(videoRendering: VideoRendering): Promise<void>; } /** * Accepts a Project that was created using {@link ScenelessProject.create ScenelessProject.create()} * and returns several commands specialized for a Sceneless broadcasting experience. * * These commands assist with management of WebRTC {@link Participant Participants}, * custom layouts, backgrounds, and overlay content. */ export declare const commands: (_project: ScenelessProject) => Commands; export type LayoutProps = { cover?: boolean; /** Valid CSS for justify-content */ justifyViewers?: 'flex-end' | 'center' | 'flex-start'; /** Percentage */ barWidth?: number; barPosition?: 'bottom' | 'side'; useGrid?: boolean; reverse?: boolean; /** used for type alert */ type?: 'alert' | 'image-iframe-overlay'; /** Either 'top-center' or 'bottom-center' **/ preset?: string; /** used for type image-iframe-overlay to order the layers */ order?: string[]; }; type ScenelessSettings = { backgroundImage?: string; layout?: string; layoutProps?: LayoutProps; }; /** * **An abstraction over {@link Command.createProject Command.createProject()}.** * * A Project created using this function will be compatible with {@link ScenelessProject.commands ScenelessProject.commands()} * * **Emits: ProjectAdded** */ export declare const create: (settings?: ScenelessSettings, props?: SDK.Props, size?: { x: number; y: number; }) => Promise<ScenelessProject>; /** @private */ export declare const createCompositor: (layoutId: string, size: { x: number; y: number; }, settings: ScenelessSettings) => Promise<Compositor.Project>;