useAudio, useImages, useVideo, and useFiles assemble multimodal blocks from the protocol stream. Each hook returns an array of media handles (one per message containing a matching block in the target namespace).
Runnable example: The
multimodalstorybook in the streaming cookbook streams story text, generated images, audio narration, and video from scoped graph nodes.
Every media handle exposes the same core fields, plus media-specific extras:
| Field | Type | Description |
|---|---|---|
id |
string |
Stable id for the media block. |
messageId |
string |
Owning message id. |
partialBytes |
Uint8Array \| undefined |
Live-growing byte buffer during streaming. |
blob |
Blob \| undefined |
Settled Blob — populated on message-finish. |
objectURL |
string \| undefined |
Object URL for the settled Blob (auto-revoked). |
error |
unknown |
Fail-loud error surface. |
mimeType |
string \| undefined |
Declared MIME type. |
Media-specific extras:
| Hook | Extras |
|---|---|
useAudio |
transcript?: string, duration?: number, sampleRate?: number |
useImages |
width?: number, height?: number |
useVideo |
duration?: number, width?: number, height?: number |
useFiles |
filename?: string, size?: number |
import { useAudio, useImages, useVideo, useFiles } from "@langchain/svelte";
const audios = useAudio(stream);
const images = useImages(stream);
const videos = useVideo(stream);
const files = useFiles(stream);
Each accepts an optional target argument (subagent / subgraph / { namespace }) to scope the subscription — see Selectors.
useMediaUrluseMediaUrl turns a media handle into a stable blob URL you can pass to <audio/img/video src>:
import { useAudio, useMediaUrl } from "@langchain/svelte";
function AudioReply({ stream }: { stream: AnyStream }) {
const audios = useAudio(stream);
const latest = audios.at(-1);
const url = useMediaUrl(latest);
return url ? <audio controls src={url} /> : null;
}
useMediaUrl(undefined) returns undefined — safe to call unconditionally.
useAudioPlayer / useVideoPlayeruseAudioPlayer and useVideoPlayer provide opinionated player handles with play/pause/seek state, built on top of the media hooks:
import { useAudio, useAudioPlayer } from "@langchain/svelte";
function AudioPlayer({ stream }: { stream: AnyStream }) {
const audio = useAudio(stream).at(-1);
const player = useAudioPlayer(audio, { autoPlay: true });
return (
<div>
<button onClick={player.toggle}>{player.isPlaying ? "Pause" : "Play"}</button>
<progress value={player.currentTime} max={player.duration} />
</div>
);
}
useVideoPlayer mirrors the same shape for video handles.
Subscribe to a scoped audio-media stream. Each handle is yielded
Subscribe to a scoped image-media stream. Pair with useMediaURL
Subscribe to a scoped video-media stream. Pair with useMediaURL
Subscribe to a scoped file-media stream. Pair with useMediaURL
Progressive audio playback for AudioMedia handles with a
Bind a VideoMedia handle to a caller-owned <video>
Player controls + live state returned by useAudioPlayer.
Controls + live state returned by useVideoPlayer. Mirrors
Shared surface across every media handle returned by
Shared surface across every media handle returned by
Shared surface across every media handle returned by
Shared surface across every media handle returned by