Quick start - Browser (WASM)
In this guide, you’ll learn how to create a basic Smelter setup in browser using TypeScript SDK. We will show you how to take camera input, compose it with some other elements, and send it over WebRTC (via WHIP protocol).
-
Create Smelter object and initialize it.
import Smelter from "@swmansion/smelter-web-wasm"function DemoPage() {const videoRef = useRef<HTMLVideoElement>();const [smelter, setSmelter] = useState<Smelter | undefined>();useEffect(() => {(async () => {const smelter = await start(videoRef.current);setSmelter(smelter);})();}, []);return (<div><video ref={videoRef}/></div>)}async function start(videoElement: HTMLVideoElement): Promise<Smelter> {const smelter = new Smelter();await smelter.init();return smelter;}We are starting with a simple page with empty
<div />
and the<video />
tag that will latter be used as a stream preview. When component is mounted a new Smelter instance is created. -
Register an output stream and call
Smelter.start()
.import { View } from "@swmansion/smelter"import Smelter from "@swmansion/smelter-web-wasm"function DemoPage() {15 collapsed linesconst videoRef = useRef<HTMLVideoElement>();const [smelter, setSmelter] = useState<Smelter | undefined>();useEffect(() => {(async () => {const smelter = await start(videoRef.current);setSmelter(smelter);})();}, []);return (<div><video ref={videoRef}/></div>)}async function start(videoElement: HTMLVideoElement): Promise<Smelter> {const smelter = new Smelter();await smelter.init();const { stream } = await smelter.registerOutput('output',<View />,{type: 'whip',endpointUrl: 'https://example.com/whip',bearerToken: '<STREAM TOKEN>',video: {resolution: { width: 1920, height: 1080 },},audio: true,});await smelter.start();videoElement.srcObject = stream;await videoElement.play();return smelter;}This step creates an output that renders just an empty
<View />
component. Resulting blank image is encoded and sent via WHIP protocol to specified url.Additionally,
stream
returned fromregisterOutput
call is assigned as a source to the HTML<video>
tag, which will display stream preview on that element. -
Register camera input and add it to the scene.
import { Rescaler, InputStream } from "@swmansion/smelter"import Smelter from "@swmansion/smelter-web-wasm"function SmelterScene() {return (<Rescaler><InputStream inputId="camera" /></Rescaler>)}function DemoPage() {15 collapsed linesconst videoRef = useRef<HTMLVideoElement>();const [smelter, setSmelter] = useState<Smelter | undefined>();useEffect(() => {(async () => {const smelter = await start(videoRef.current);setSmelter(smelter);})();}, []);return (<div><video ref={videoRef}/></div>)}async function start(videoElement: HTMLVideoElement): Promise<Smelter> {const smelter = new Smelter();await smelter.init();await smelter.registerInput('camera', { type: 'camera' });const { stream } = await smelter.registerOutput('output',<SmelterScene />,{type: 'whip',6 collapsed linesendpointUrl: 'https://example.com/whip',bearerToken: '<STREAM TOKEN>',video: {resolution: { width: 1920, height: 1080 },},audio: true,});6 collapsed linesawait smelter.start();videoElement.srcObject = stream;await videoElement.play();return smelter}In this step we registered a new input (
camera
) and replaced<View />
in aregisterOutput
call with a<SmelterScene />
component. New output stream will include camera output resized to match output resolution. -
Add button that adds screen capture to the output stream.
import {View,Rescaler,InputStream,useInputStreams} from "@swmansion/smelter"import Smelter from "@swmansion/smelter-web-wasm"function SmelterScene() {const inputs = useInputStreams();const hasScreenCapture = !!inputs['screen'];if (!hasScreenCapture) {return (<Rescaler><InputStream inputId="camera" /></Rescaler>)}return (<View><Rescaler><InputStream inputId="camera" /></Rescaler><Rescaler style={{ top: 20, left: 20, width: 640, height: 360 }}><InputStream inputId="screen" /></Rescaler></View>)}function DemoPage() {10 collapsed linesconst videoRef = useRef<HTMLVideoElement>();const [smelter, setSmelter] = useState<Smelter | undefined>();useEffect(() => {(async () => {const smelter = await start(videoRef.current);setSmelter(smelter);})();}, []);const startScreenCapture = () => {smelter?.registerInput('screen', { type: 'screen_capture' })};return (<div><video ref={videoRef}/><button onClick={startScreenCapture} >Start screen sharing</button></div>)}async function start(videoElement: HTMLVideoElement): Promise<Smelter> {25 collapsed linesconst smelter = new Smelter();await smelter.init();await smelter.registerInput('camera', { type: 'camera' });const { stream } = await smelter.registerOutput('output',<SmelterScene />,{type: 'whip',endpointUrl: 'https://example.com/whip',bearerToken: '<STREAM TOKEN>',video: {resolution: { width: 1920, height: 1080 },},audio: true,});await smelter.start();videoElement.srcObject = stream;await videoElement.play();return smelter;}In this example:
- We are adding
<button />
toDemoPage
component that will trigger adding screen share as an input. - Modify
SmelterScreen
component to change it based on connected inputs:- Camera input scaled to output when screen share is not used.
- Screen share scaled to output and camera in top left corner when it is.
- We are adding