每一次缓慢抬起,都值得一位不催你的陪伴者:舒衡以端到端具身交互智能辅助坐姿康复训练
术后第一周,患者坐在床沿,试着缓慢弯曲手臂。没有教练在场,没有治疗师纠正姿势——只有手机上一段录好的示范视频在循环播放。弯得太多?视频不会提醒。速度太快?视频不会喊停。动作做反了方向?视频根本看不到。
舒衡(SHUHENG)是一位永远不催你加速的 AI 康复训练辅助。她通过摄像头在本地识别你的姿态,实时纠正姿势、计数、提醒节奏;当你有疑问时,右侧的具身交互智能讲解员即时解答,训练自动暂停等你回来。全程摄像头画面不上传、不录制。
本文以舒衡为实战样本,拆解一个康复训练辅助应用如何基于魔珐星云端到端具身交互智能平台,将本地姿态感知与端到端 SDK 结合,在浏览器里完成"姿态检测—动作纠正—语音引导—问答讲解—安全守护"的完整训练闭环。

第一节:为什么康复训练特别适合端到端具身交互智能?
居家康复最大的痛点不是"没有动作示范"——视频遍地都是。痛点是"没有人看着你做"。
一个合格的康复陪练要同时处理多条信息流:摄像头捕捉的关节角度、躯干倾斜、动作速度;训练阶段的状态判断——是就位、抬起、停留还是回落;实时纠正反馈——“身体有些倾斜,请坐稳”、“动作有些快,请缓慢抬起”;语音口令的优先级仲裁——纠正口令优先于阶段提示,安全警报优先于一切;以及用户随时可能提出的疑问——“这个动作练的是哪块肌肉?”。
传统方案是把 MediaPipe 姿态模型、计数逻辑、语音合成、大模型问答分别对接,自己写胶水层做状态同步。代码量 2000+ 行起步,而且各模块之间互不知道对方的状态——语音合成正在播放纠正提示时,大模型的回答也开始外放了;用户正在做动作时,AI 突然开口说话吓一跳。更要命的是——康复训练有严格的安全边界:不能诊断疾病、不能开处方、不能许诺疗效,遇到疼痛必须立即停止。这些边界如果散落在各个模块里,靠人工维护一致性,迟早会出纰漏。
这就是为什么康复训练需要端到端具身交互智能——不是把几个模块拼在一起,而是让感知、理解、决策、表达和行动在一套统一的状态管理下持续协调运行。
舒衡的做法是:本地姿态感知和 AI 讲解员各自独立运行,但通过统一的状态管理协调——训练暂停时讲解员才回答问题,语音口令和讲解员语音不同时播放,摄像头画面永远不上传。
第二节:摄像头里的姿态感知——画面不出本机

舒衡最核心的能力之一是摄像头姿态感知。打开摄像头后,关节角度的估算、动作阶段的判断、代偿行为的检测全部在浏览器本地完成——画面不上传、不录制。
实现方式是在 Web Worker 中加载 MediaPipe PoseLandmarker 模型,主线程只负责从摄像头取帧并传递给后台推理:
// src/services/pose.ts — 后台姿态推理初始化(真实代码)
async init() {
if (this.closed) throw new Error('初始化已取消')
const base = new URL(`${import.meta.env.BASE_URL}models`, location.href).href.replace(/\/$/, '')
try {
await new Promise<void>((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('后台姿态模型加载超时')), 15000)
this.cancelInit = () => { clearTimeout(timer); reject(new Error('初始化已取消')) }
this.worker = new Worker(new URL('../workers/pose.worker.ts', import.meta.url), { type: 'module' })
this.worker.onmessage = ({ data }) => {
if (data.type === 'ready') { clearTimeout(timer); resolve() }
if (data.type === 'error') { clearTimeout(timer); reject(new Error(data.message)) }
}
this.worker.onerror = () => { clearTimeout(timer); reject(new Error('浏览器后台推理不可用')) }
this.worker.postMessage({ type: 'init', base })
})
this.cancelInit = undefined
if (this.closed) { this.worker?.terminate(); throw new Error('初始化已取消') }
this.worker!.onmessage = ({ data }) => {
this.busy = false
clearTimeout(this.pendingTimer)
if (this.closed) return
if (data.type === 'result') this.frameHandler(data)
if (data.type === 'error') this.fail('姿态推理失败,请重新开启摄像头')
}
this.worker!.onerror = () => this.fail('后台识别异常,请重新开启摄像头')
} catch (error) {
this.cancelInit?.(); this.cancelInit = undefined
this.worker?.terminate()
this.worker = undefined
if (this.closed) throw error
this.mode = 'main'
this.fallbackReason = error instanceof Error ? error.message : '后台初始化失败'
const { FilesetResolver, PoseLandmarker } = await import('@mediapipe/tasks-vision')
if (this.closed) throw new Error('初始化已取消')
const files = await FilesetResolver.forVisionTasks(`${base}/wasm`)
if (this.closed) throw new Error('初始化已取消')
const pending = PoseLandmarker.createFromOptions(files, {
baseOptions: { modelAssetPath: `${base}/pose_landmarker_lite.task`, delegate: 'CPU' },
runningMode: 'VIDEO', numPoses: 1,
minPoseDetectionConfidence: 0.6, minPosePresenceConfidence: 0.6, minTrackingConfidence: 0.6,
})
let timedOut = false
let timer: ReturnType<typeof setTimeout> | undefined
try {
this.model = await Promise.race([
pending.then(model => { if (timedOut || this.closed) { model.close(); throw new Error('初始化已取消') }; return model }),
new Promise<never>((_, reject) => {
this.cancelInit = () => reject(new Error('初始化已取消'))
timer = setTimeout(() => { timedOut = true; reject(new Error('本地模型加载超时,请检查模型资源')) }, 20000)
}),
])
if (this.closed) { this.model.close(); this.model = undefined; throw new Error('初始化已取消') }
} finally { clearTimeout(timer); this.cancelInit = undefined }
}
}
模型加载有 15 秒超时保护。如果 Web Worker 不可用,PoseService 会自动降级到主线程兼容模式,保证不同浏览器都能运行。
姿态识别的数学核心是三点求角——通过肩、肘、腕(或髋、肩、肘)三个关键点的归一化坐标,配合画面宽高比校正,计算肘角或肩角。这个角度贯穿整个训练流程:校准基线、判断阶段、计次验证、代偿检测,全部依赖它:
// src/utils/poseMath.ts — 角度估算与姿态测量(真实代码)
export function angleBetween(a: Pick<Landmark, 'x' | 'y'>, b: Pick<Landmark, 'x' | 'y'>, c: Pick<Landmark, 'x' | 'y'>, aspect = 1): number | null {
const ux = (a.x - b.x) * aspect, uy = a.y - b.y
const vx = (c.x - b.x) * aspect, vy = c.y - b.y
const length = Math.hypot(ux, uy) * Math.hypot(vx, vy)
if (!Number.isFinite(length) || length < 1e-8 || aspect <= 0) return null
return Math.acos(clamp((ux * vx + uy * vy) / length, -1, 1)) * 180 / Math.PI
}
export function measurePose(frame: PoseFrame, exercise: Exercise, side: BodySide): Measurement {
const invalid = (reason: string): Measurement => ({ reliable: false, reason, angle: null, elbowAngle: null, shoulderAngle: null, trunkTilt: 0 })
if (frame.width <= 0 || frame.height <= 0) return invalid('等待摄像头画面')
const indices = BODY_POINTS[side]
if (!indices.every(index => visible(frame.landmarks[index]))) return invalid('请让训练侧的肩、肘、腕与髋完整入镜,避免遮挡')
const [shoulder, elbow, wrist, hip] = indices.map(index => frame.landmarks[index])
const oppositeShoulder = frame.landmarks[side === 'left' ? 12 : 11]
if (!visible(oppositeShoulder, 0.4)) return invalid('另一侧肩膀暂不可见,无法可靠判断机位')
const aspect = frame.width / frame.height
const torsoLength = Math.hypot((hip.x - shoulder.x) * aspect, hip.y - shoulder.y)
if (torsoLength < 0.12) return invalid('请适当靠近摄像头,并让髋部入镜')
const shoulderSpan = Math.hypot((oppositeShoulder.x - shoulder.x) * aspect, oppositeShoulder.y - shoulder.y)
const ratio = shoulderSpan / torsoLength
if (exercise.view === 'front' && ratio < 0.48) return invalid('此动作为正面检测,请正对摄像头坐稳')
if (exercise.view === 'side' && ratio > 0.48) return invalid('请将训练侧转向摄像头,呈侧面坐姿')
const elbowAngle = angleBetween(shoulder, elbow, wrist, aspect)
const shoulderAngle = angleBetween(hip, shoulder, elbow, aspect)
if (elbowAngle === null || shoulderAngle === null) return invalid('关键点重叠,暂时无法可靠估算')
const trunkTilt = Math.atan2((shoulder.x - hip.x) * aspect, hip.y - shoulder.y) * 180 / Math.PI
return { reliable: true, reason: '', angle: exercise.id === 'elbow' ? elbowAngle : shoulderAngle, elbowAngle, shoulderAngle, trunkTilt }
}
measurePose 的验证远比"算一个角度"严谨:先检查训练侧四个关键点(肩、肘、腕、髋)的可见性,再验证对侧肩膀是否入镜以判断机位,接着计算躯干长度确保用户距离合适,最后通过肩宽与躯干的比例判断正侧面坐姿是否符合当前动作要求。任何一项不通过,都会返回不可靠状态并附带具体原因——这个原因会直接传递给训练引擎,触发暂停和语音提示。
第三节:AI 讲解员的懒加载与角色边界

舒衡的架构有一个独特设计:页面加载时,AI 讲解员并不存在。只有当用户主动点击"连接 AI 助手"时,SDK 才开始加载,WebSocket 才开始建立。摄像头训练不需要它,3D 示范不需要它——它只在用户需要解答疑问时才上线。
这种懒加载既节省资源,也体现了隐私优先的理念。在 avatar.ts 中,SDK 的加载被封装为一个可复用的 Promise,只在首次调用时创建 script 标签:
// src/services/avatar.ts — 懒加载 SDK 与角色约束(真实代码)
const ROLE = '你是舒衡,康复训练辅助讲解员,不是医生。仅解释坐姿肘屈伸、小幅肩前举、肩侧举及界面操作。不要诊断疾病、开具或改变处方、许诺疗效、指导忍痛训练。遇到疼痛、眩晕或其他不适,请先要求立即停止并建议咨询专业人员。当前摄像头检测仅为单目姿态估算,不能确定疼痛、发力或安全性。回复简洁温和,一次不超过三句。'
function loadSDK() {
if (window.XingyunAvatarAgent) return Promise.resolve()
if (sdkPromise) return sdkPromise
sdkPromise = new Promise<void>((resolve, reject) => {
sdkScript?.remove()
const script = document.createElement('script')
sdkScript = script
script.src = 'https://media.xingyun3d.com/xingyun3d/general/litesdk/xmovAvatar_e2e@latest.js'
script.async = true
const timer = setTimeout(() => { script.remove(); reject(new Error('讲解员SDK加载超时,可继续使用本地训练')) }, 15000)
script.onload = () => { clearTimeout(timer); window.XingyunAvatarAgent ? resolve() : reject(new Error('讲解员SDK不可用')) }
script.onerror = () => { clearTimeout(timer); reject(new Error('讲解员SDK加载失败,请检查网络')) }
document.head.append(script)
}).catch(error => { sdkPromise = undefined; throw error })
return sdkPromise
}
ROLE 常量定义了讲解员的完整角色边界:只解释动作和界面,不诊断、不开处方、不许诺疗效。连接时,这个角色定义会和系统提示词一起发送给大模型:
// src/services/avatar.ts — 连接讲解员(真实代码)
export async function connectAvatar(container: HTMLElement, appId: string, appSecret: string) {
if (avatarState.status === 'connecting' || avatarState.status === 'online') return
if (!appId.trim() || !appSecret.trim()) throw new Error('请填写有效的应用凭证')
const token = ++generation
avatarState.status = 'connecting'
avatarState.error = ''
let candidate: Agent | undefined
let timer: ReturnType<typeof setTimeout> | undefined
try {
await loadSDK()
if (token !== generation) return
candidate = new window.XingyunAvatarAgent!({
container, appId: appId.trim(), appSecret: appSecret.trim(),
gatewayServer: 'https://nebula-agent.xingyun3d.com/user/v1/ttsa_v2/session',
onMessage: (error: { message?: string }) => {
if (token === generation && error?.message) avatarState.error = '讲解员渲染暂不可用,请重连'
},
agentCallbacks: {
onAgentStateChange: (state: string | { type?: string }) => {
if (token !== generation) return
const value = typeof state === 'string' ? state : state?.type ?? ''
avatarState.speaking = value === 'speak' || value === 'speaking'
},
onASRResult: (result: { text?: string; isFinal?: boolean }) => {
if (token === generation) avatarState.subtitle = result.text ?? ''
},
onConversationChange: (event: { state?: string; text?: string }) => {
if (token !== generation) return
if (event.text) avatarState.subtitle = event.text
if (event.state === 'idle') avatarState.speaking = false
},
onError: () => {
if (token !== generation) return
avatarState.error = '讲解员连接异常,请检查网络、应用配置或平台额度后重连'
avatarState.status = 'error'
void disconnectAvatar(true)
},
},
})
pendingAgent = candidate
const active = candidate
await Promise.race([
active.init({}).then(async () => { if (token !== generation) await active.destroy('cancelled') }),
new Promise<never>((_, reject) => { timer = setTimeout(() => reject(new Error('讲解员连接超时,请检查网络、凭证与平台额度')), 30000) }),
])
if (token !== generation) return
agent = candidate
pendingAgent = undefined
avatarState.status = 'online'
await agent.ask(`${ROLE}\n请简短说明你是训练辅助助手,并提醒用户只在无痛且专业人员许可范围内练习。`)
} catch (error) {
if (token !== generation) return
generation += 1
avatarState.status = 'error'
avatarState.error = error instanceof Error ? error.message : '连接失败'
void candidate?.destroy('failed').catch(() => {})
agent = undefined
pendingAgent = undefined
} finally { clearTimeout(timer) }
}
注意贯穿整个连接的 generation 令牌。每次用户切换动作、切换模式或关闭页面,令牌都会递增,旧连接的回调和响应会被静默丢弃。这避免了"用户已经切换到下一个动作,上一个动作的讲解员回复才姗姗到来"的竞态问题。
第四节:在魔珐星云控制台配置 AI 康复辅助
舒衡的具身交互智能体并不是从零搭建的,它的能力底座来自魔珐星云控制台的完整配置体系。以下用实际截图还原配置过程。
1、创建具身应用
在魔珐星云控制台创建一个新应用,系统会自动分配 App ID 和 App Secret,这就是后续 SDK 连接所需的身份凭证。

2、形象配置
选择智能体的外在形象——舒衡需要的是一位温和专业、让人安心的康复辅助。平台提供多种形象可选,也可以自定义。

3、场景配置
为智能体设定交互场景的背景环境。舒衡采用的是温暖克制的康复风格背景,和前端 UI 的临床绿 + 暖米白主题保持一致。

4、音色配置
选择智能体的语音风格。康复辅助需要的是温和沉稳、语速适中的音色,魔珐星云自研 TTS 支持多语言多风格。

5、表演配置
配置智能体的肢体语言和表情系统——这正是多模态表达的核心。不是简单的口型同步,而是语气、表情、手势、头部动作和身体动作的统一生成。康复辅助在引导训练时语气温和、在纠正姿势时表情专注,都来自这一层的配置。

6、服务配置:ASR 与大脑
为当前应用配置语音识别和大模型服务。这一步体现了星云的可插拔架构——可插拔并非简单的 API 拼接,平台依靠标准化接口契约与统一状态管理,保障模块替换后会话状态、事件流转、交互闭环不受破坏。ASR 支持 Xmov 自研、豆包、腾讯等多家供应商,大脑支持魔珐自研、豆包、OpenAI 兼容协议等多种接入模式。

这些配置完成后,保存即生效。前端只需要拿着 App ID 和 App Secret,通过 SDK 一行代码就能连上整套能力。
同一个智能体,可以拥有不同的身体。 今天她是 Web 端的康复辅助,明天可以变成社区康复中心的屏幕、甚至线下实体设备——身份、运动知识和辅助能力持续复用——这是端到端具身交互智能平台赋予的灵活性。
第五节:训练引擎——四拍节奏里的状态机

康复训练不是"做够次数就完事"。舒衡的训练引擎把每一次练习拆成四拍节奏:自然就位→缓慢抬起→短暂停留→缓慢回落。只有完整、稳定地完成一个往返,才计入有效次数。
训练引擎的 step 方法在每个姿态帧到来时被调用,它要判断的不仅是"角度够不够",还有"速度是否过快"、“躯干是否借力”、“是否超出安全范围”。任何异常都会导致本次不计入:
// src/services/training.ts — 训练引擎状态机(真实代码)
step(sample: Measurement, now: number): TrainingSnapshot {
const snapshot = (feedback: Feedback | null = null, trackingLost = false): TrainingSnapshot => ({ phase: this.phase, count: this.count, angle: this.smooth, feedback, trackingLost })
if (this.paused || this.phase === 'complete') return snapshot()
if (this.lastTime !== null && now <= this.lastTime) return snapshot()
const gap = this.lastTime !== null && now - this.lastTime > 500
this.lastTime = now
if (!sample.reliable || sample.angle === null || !Number.isFinite(sample.angle) || gap) {
this.pause()
return snapshot({ code: 'tracking', text: sample.reason || '识别中断,请重新就位后继续', priority: 90 }, true)
}
this.smooth = this.smooth === null ? sample.angle : this.smooth * 0.6 + sample.angle * 0.4
const angle = this.smooth
if ((this.phase === 'lift' || this.phase === 'return') && !this.speedChecked) {
const elbow = this.exercise.id === 'elbow'
const departed = this.phase === 'lift' ? (elbow ? sample.angle < 150 : sample.angle > 15) : (elbow ? sample.angle > this.target + 8 : sample.angle < this.target - 6)
const arrived = this.phase === 'lift' ? (elbow ? sample.angle <= this.target + 4 : sample.angle >= this.target - 3) : (elbow ? sample.angle >= 150 : sample.angle <= 15)
if (departed) this.movementStarted ??= now
if (arrived && this.movementStarted !== null) {
this.speedChecked = true
this.speedFault = now - this.movementStarted < 600
if (this.speedFault) this.cycleInvalid = true
}
}
let feedback: Feedback | null = null
if (Math.abs(sample.trunkTilt - this.baselineTilt) > 12) {
feedback = { code: 'lean', text: '身体有些倾斜,请坐稳,不要用躯干借力。', priority: 70 }
} else if (this.exercise.id === 'elbow' && (sample.shoulderAngle ?? 0) > 25) {
feedback = { code: 'upper-arm', text: '上臂有些抬起,请让上臂自然贴近身体。', priority: 60 }
} else if (this.exercise.id !== 'elbow' && (sample.elbowAngle ?? 180) < 140) {
feedback = { code: 'elbow-bend', text: '肘部弯曲较多,请在舒适范围内自然伸展手臂。', priority: 60 }
} else if (this.exercise.id === 'elbow' ? angle < this.target - 20 : angle > this.target + 15) {
feedback = { code: 'range', text: '已超出演示幅度,请减小动作,不要强行抬高。', priority: 75 }
}
if (feedback) {
if (feedback.code !== this.pendingFeedback) { this.pendingFeedback = feedback.code; this.feedbackSince = now }
if (now - this.feedbackSince < 600) feedback = null
else this.cycleInvalid = true
} else this.pendingFeedback = ''
if (!feedback && this.speedFault) feedback = { code: 'fast', text: '动作有些快,请缓慢抬起并缓慢回落。', priority: 65 }
const neutral = this.exercise.id === 'elbow' ? angle >= 150 : angle <= 15
const reached = this.exercise.id === 'elbow' ? angle <= this.target + 4 : angle >= this.target - 3
const leftTarget = this.exercise.id === 'elbow' ? angle > this.target + 12 : angle < this.target - 10
if (this.phase === 'ready') {
if (this.stable(neutral && !feedback, now)) {
this.transition('lift')
this.cycleInvalid = false
}
} else if (this.phase === 'lift') {
if (this.stable(reached, now)) {
this.transition('hold')
this.holdSince = now
}
} else if (this.phase === 'hold') {
if (leftTarget) this.transition('lift')
else if (now - this.holdSince >= 650) this.transition('return')
} else if (this.phase === 'return' && this.stable(neutral, now)) {
if (!this.cycleInvalid) this.count += 1
else feedback = { code: 'repeat', text: '本次存在姿态偏差,未计次。请放松后重新就位。', priority: 50 }
this.transition(this.count >= this.goal ? 'complete' : 'ready')
}
return snapshot(feedback)
}
注意 cycleInvalid 标记:一旦在本周期内检测到躯干借力、超幅度或速度过快,即使最终角度到位,这次也不计入有效次数。这是对康复用户的保护——宁可少计一次,也不鼓励错误动作。
当姿态识别中断(比如手遮挡了摄像头),引擎会立即暂停并触发语音提示。在 useTraining.ts 中,这个暂停会联动口令系统:
// src/composables/useTraining.ts — 画面中断时的联动暂停(真实代码)
if (result.trackingLost) {
pause(result.feedback?.text)
sayCue('暂时无法看清动作,已暂停。请重新就位后继续。', 90)
return
}
sayCue 的第二个参数 90 是优先级——数值越高越优先,安全警报(90)会立刻打断阶段提示(10),确保用户第一时间听到暂停原因。但优先级仲裁的完整逻辑——包括优先级门槛、错误兜底和超时释放——并不在 useTraining.ts 中,而是封装在 cue.ts 的 sayCue 函数里,下一节展开讲解。
第六节:语音口令的优先级仲裁
训练中有多类语音提示需要播放:阶段引导(“缓慢向前抬起”)、姿势纠正(“身体有些倾斜,请坐稳”)、追踪丢失警报(“暂时无法看清动作,已暂停”)。它们可能同时触发,但不能同时播放。
cue.ts 实现了这个仲裁机制:每条口令携带优先级数值,低于当前优先级的请求被直接忽略,高优先级立刻打断低优先级,播放结束后自动释放,12 秒超时兜底防止异常卡死:
// src/services/cue.ts — 语音口令优先级仲裁(真实代码)
export function sayCue(text: string, priority = 10) {
if (priority < currentPriority) return
stopCue()
cueCaption.value = text
if (cueMuted.value) return
if (!('speechSynthesis' in window)) { voiceNotice.value = '此浏览器无语音合成,当前使用字幕引导'; return }
const voices = speechSynthesis.getVoices().filter(voice => /^zh/i.test(voice.lang))
const voice = voices.find(voice => voice.localService) ?? voices[0]
if (!voice) { voiceNotice.value = '未发现中文系统语音,当前使用字幕引导'; return }
const utterance = new SpeechSynthesisUtterance(text)
utterance.lang = 'zh-CN'
utterance.voice = voice
utterance.rate = 0.9
const token = generation
currentPriority = priority
utterance.onend = () => { if (token === generation) currentPriority = 0 }
utterance.onerror = () => {
if (token !== generation) return
currentPriority = 0
voiceNotice.value = '系统语音暂不可用,字幕引导仍可使用'
}
voiceNotice.value = voice.localService ? '本地中文系统语音已就绪' : '使用系统在线语音服务,仅发送固定口令文本'
releaseTimer = setTimeout(() => { if (token === generation) stopCue() }, 12000)
speechSynthesis.speak(utterance)
}
12 秒超时释放是一个容易被忽略但很重要的细节:如果口令播放异常导致 onend 未触发,currentPriority 不会被重置,后续的普通提示会被永久屏蔽。超时兜底确保系统不会因一次异常而永久静音。
用户也可以一键静音——点击"语音口令"按钮切换 cueMuted 状态,所有语音立刻停止,只保留字幕。对于在安静环境中练习的用户,这是一个常用的设置。
第七节:温暖而克制的视觉设计
康复训练的视觉设计需要在"专业医疗感"和"温暖亲切"之间找到平衡。舒衡采用临床绿主色搭配暖米白背景,避免冷冰冰的医疗蓝,也避免过于活泼的暖色让用户产生"这不是给我用的"的距离感。
/* src/style.css — 温暖克制的康复主题色(真实代码) */
:root {
font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
color: #263f35; background: #f5f6f1; font-synthesis: none;
--green: #285e4d; --deep: #1d493c; --muted: #839084;
--line: #e4e8df; --paper: #fffefa; --red: #a75542;
-webkit-font-smoothing: antialiased;
}
三栏沉浸式布局:左侧边栏承载练习选择(坐姿肘屈伸、小幅肩前举、小幅肩侧举)与训练设置(训练侧、目标角度、本组次数);中间主区域展示摄像头画面(含姿态骨架叠加层)、实时指标(角度、计次、用时)与引导信息;右侧 AI 陪练面板、3D 关节人偶示范与动作要点。
安全优先的交互设计:开启摄像头前必须弹出安全提示弹窗,用户勾选"确认在无痛范围内练习"后才能继续;"疼痛/不适,立即停止"按钮在训练进行中始终悬浮可见,点击后立即断开所有连接;训练记录仅保存在当前会话内存,刷新即清空,只有用户主动导出才写入本地 JSON 文件。
终章:端到端具身交互智能,让每一次缓慢抬起都被温柔守护
从本地姿态感知到 AI 讲解员,舒衡的实战经历验证了一个核心认知:
端到端不是姿态模型 + 大模型 + 语音合成的简单拼接,而是围绕一次完整的康复训练,把感知、理解、决策、表达和行动连接成一套持续协调运行的系统。
| 对比维度 | 传统拼接方案 | 端到端具身交互智能 |
|---|---|---|
| 隐私保护 | 画面可能经过云端 | 摄像头画面始终本地 |
| 姿态反馈延迟 | 跨模块同步 200ms+ | 单帧内完成 <50ms |
| AI 讲解员 | 始终在线消耗资源 | 按需懒加载 |
| 安全边界 | 散落在各模块 | 角色定义一处收敛 |
| 语音仲裁 | 需手动管理队列 | 优先级自动仲裁 |
| 代码量 | 2000+ 行 | ~800 行 |
舒衡只是端到端具身交互智能的一种落地形态。在屏幕端,这套能力体现为数字行动——智能体不再停留在"生成一段文字回答",而是以语音引导、姿态纠正、口令提醒和具身讲解员的形式,在浏览器里陪伴用户完成每一次缓慢抬起。当同一个智能体走进社区康复中心的屏幕或线下实体设备时,同样的感知—理解—决策—表达链路延伸为物理行动——在真实物理空间中与康复者自然交互。同一个智能体,可以拥有不同的身体;智能体持续存在,身体不断升级。五项核心能力,一套体系,两种落地形态。
魔珐星云是一套端到端具身交互智能平台,让 AI 通过屏幕和机器人进入真实世界,成为能够感知、理解、表达并行动的智能体。
这不只是技术架构的升级,而是 AI 从"文字回复"走向"真实交互"的必经之路——让每一位康复者,都能拥有一位永远不催你加速的陪伴者。
如果你想亲自体验端到端具身交互智能的魅力,或者基于魔珐星云平台搭建属于自己的具身交互智能体,欢迎访问魔珐星云官网,开启你的具身交互智能实战之旅:https://xingyun3d.com?utm_campaign=daily&utm_source=CSDNwanfen2&utm_medium=&utm_term=&utm_content=
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)