@api.stream/studio-kit
Version:
Client SDK for building studio experiences with API.stream
448 lines (447 loc) • 15.2 kB
TypeScript
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>;