一、面试题目
前端如何实现多模态流式输出:文字打字机效果、图片渐进加载、音频实时播放?说明技术方案、流式协议、渲染时序、难点处理。
二、知识储备
整体方案
后端通过 SSE / WebSocket 推送多模态流式分片(文本块、图片URL、音频片段),前端分类型解析、按顺序渲染 ,实现:
文字逐字输出 + 图片渐进展示 + 音频边推边播。
流式数据格式(JSON 分片):
{"type":"text","content":"你好"}
{"type":"image","url":"xxx.png"}
{"type":"audio","chunk":"base64"}
{"type":"end"}
1. 文字打字机效果(流式文本)
实现方案
- 协议:SSE(Server‑Sent Events)/ WebSocket 接收流式 text chunk
- 前端逐字符追加,使用定时器/requestAnimationFrame实现打字机动画
- 支持换行、Markdown 实时解析渲染
核心代码(JS)
const textEl = document.getElementById('answer');
function typeWrite(textChunk) {
let i = 0;
const interval = setInterval(() => {
if (i >= textChunk.length) clearInterval(interval);
textEl.innerHTML += textChunk[i++];
}, 20);
}
优化
- 大量文本直接追加,不逐字卡顿
- 支持停止、清空、断点续打
2. 图片渐进加载(流式图片)
实现方案
- 后端推送 图片 URL / base64
- 前端先占位,使用
loading="lazy"+ 模糊渐进加载 - 图片加载期间显示骨架屏,加载完成淡入展示
- 多图按流式顺序依次渲染,不乱序
核心代码
function renderImage(url) {
const img = new Image();
img.style.opacity = 0;
img.style.transition = "opacity 0.5s ease";
img.onload = () => img.style.opacity = 1;
img.src = url;
container.appendChild(img);
}
渐进优化
- 先缩略图占位 → 高清图渐进
- 懒加载,不阻塞文字输出
3. 音频实时流式播放
实现方案
两种主流:
- base64 分片 + MediaSource 流式解码播放(实时语音)
- 后端返回完整音频 URL,前端 `` 播放
流式音频核心(MediaSource)
const mediaSource = new MediaSource();
const audio = new Audio();
audio.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', () => {
const buffer = mediaSource.addSourceBuffer('audio/mpeg');
// 不断追加音频分片
});
要点
- 音频分片顺序严格,不可乱序
- 支持边推边播、暂停、重播
4. 多模态时序控制(关键难点)
多模态必须按后端推送顺序串行渲染:
- 文字没打完,不渲染下一张图
- 图片加载完成后,继续输出文字
- 音频在对应节点触发播放
实现:异步队列 + Promise 串行调度
const taskQueue = [];
async function runQueue() {
while(taskQueue.length) await taskQueue.shift();
}
5. 协议选型对比
- SSE:适合文本、图片推送,简单稳定,单向流式
- WebSocket:适合音频实时双向通信,延迟更低
- 音频优先 WebSocket,图文优先 SSE
三、破局之道(面试升华)
前端多模态流式输出核心是:
后端流式分片推送 → 前端解析多类型消息 → 串行队列控制时序 → 文字打字机、图片淡入、音频流式解码 。
关键难点是多模态渲染顺序、异步调度、音频实时解码、流畅动画,兼顾体验与性能。
30秒口述精简版
前端通过 SSE/WebSocket 接收多模态流式数据;
文字用逐字符打字机动画 ;图片渐进淡入+骨架屏 ;
音频用 MediaSource 分片解码实时播放 ;
通过异步任务队列保证多模态渲染顺序不乱。