关于 rw-integrate-character-embed
面向 React 应用的 Runway 虚拟形象视频通话集成技能,使用 `@runwayml/avatars-react`。提供开箱即用的通话组件和基于 Hook 的自定义界面方案,前提是已创建虚拟形象并配置服务端会话端点。
主要功能
- 01在 React 中嵌入虚拟形象视频通话
- 02使用 AvatarCall 预置组件
- 03通过会话 Hook 构建自定义界面
- 04显示虚拟形象和用户视频
- 05控制麦克风并查看会话状态
适用场景
- 01在 React 页面添加虚拟形象通话
- 02创建自定义通话界面
- 03按条件显示或隐藏通话
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ runwayml/ skills --skill rw-integrate-character-embed安装后在 Claude Code 中输入/rw-integrate-character-embed确认已加载。
详细介绍
在 React 中嵌入角色(Avatars React SDK)
前置条件:
+rw-check-compatibility— 项目必须具备服务端能力(绝不能将 API 密钥暴露给客户端)+rw-fetch-api-reference— 集成前,请从 https://docs.dev.runwayml.com/api/ 加载最新的 API 参考+rw-integrate-characters— 必须已创建角色(Avatar),并且会话端点已存在- 项目必须使用 React(Next.js、Vite+React、Remix 等)
可选:
+rw-integrate-documents— 嵌入前添加知识库
使用 @runwayml/avatars-react SDK,在 React 应用中嵌入实时 Avatar 视频通话。
安装
npm install @runwayml/avatars-react
这是一个客户端软件包。服务端的 @runwayml/sdk 应已通过 +rw-integrate-characters 安装。
选项 A:简单方案 — AvatarCall 组件
嵌入角色最快捷的方式。它会自动处理 WebRTC 连接并呈现默认 UI。
'use client';
import { AvatarCall } from '@runwayml/avatars-react';
import '@runwayml/avatars-react/styles.css';
export default function CharacterPage() {
return (
<AvatarCall
avatarId="your-avatar-id-here"
connectUrl="/api/avatar/session"
onEnd={() => console.log('Call ended')}
onError={(error) => console.error('Error:', error)}
/>
);
}
AvatarCall 属性
| 属性 | 类型 | 说明 |
|---|---|---|
avatarId | string | Developer Portal 或 API 中的 Avatar UUID |
connectUrl | string | 服务端会话端点(例如 /api/avatar/session) |
onEnd | () => void | 通话正常结束时调用 |
onError | (error: Error) => void | 连接或运行时发生错误时调用 |
对于在 Developer Portal 中创建的自定义 Avatar,请将 Avatar UUID 用作 avatarId。
选项 B:完全自定义 — Hooks
如需完全控制 UI,请使用带 Hooks 的 AvatarSession。
组件与 Hooks
| 导出项 | 类型 | 说明 |
|---|---|---|
AvatarSession | 组件 | 管理 WebRTC 会话的 Provider |
AvatarVideo | 组件 | 呈现 Avatar 的视频流 |
UserVideo | 组件 | 呈现用户的摄像头画面 |
useAvatarSession | Hook | 访问会话状态:state、sessionId、error、end() |
useLocalMedia | Hook | 控制用户的媒体:isMicEnabled、toggleMic() |
自定义 UI 示例
'use client';
import {
AvatarSession,
AvatarVideo,
UserVideo,
useAvatarSession,
useLocalMedia,
} from '@runwayml/avatars-react';
import type { SessionCredentials } from '@runwayml/avatars-react';
function CallUI() {
const { state, end } = useAvatarSession();
const { isMicEnabled, toggleMic } = useLocalMedia();
return (
<div className="relative w-full h-screen">
{/* Avatar video takes full screen */}
<AvatarVideo className="w-full h-full object-cover" />
{/* User's camera in a small overlay */}
<UserVideo className="absolute bottom-4 right-4 w-48 rounded-lg" />
{/* Controls */}
<div className="absolute bottom-4 left-4 flex gap-2">
<button onClick={toggleMic}>
{isMicEnabled ? 'Mute' : 'Unmute'}
</button>
<button onClick={end}>End Call</button>
</div>
{/* Connection state */}
{state === 'connecting' && (
<div className="absolute inset-0 flex items-center justify-center bg-black/50">
Connecting...
</div>
)}
</div>
);
}
export function CustomAvatar({ credentials }: { credentials: SessionCredentials }) {
return (
<AvatarSession credentials={credentials} audio video>
<CallUI />
</AvatarSession>
);
}
为自定义 UI 获取凭据
使用 Hooks 方案时,需要从服务器端点获取凭据,并将其传递给 AvatarSession:
'use client';
import { useState, useCallback } from 'react';
import type { SessionCredentials } from '@runwayml/avatars-react';
import { CustomAvatar } from './CustomAvatar';
export default function CharacterPage() {
const [credentials, setCredentials] = useState<SessionCredentials | null>(null);
const [loading, setLoading] = useState(false);
const startCall = useCallback(async () => {
setLoading(true);
try {
const res = await fetch('/api/avatar/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ avatarId: 'your-avatar-id-here' }),
});
const data = await res.json();
setCredentials(data);
} catch (error) {
console.error('Failed to connect:', error);
} finally {
setLoading(false);
}
}, []);
if (credentials) {
return <CustomAvatar credentials={credentials} />;
}
return (
<button onClick={startCall} disabled={loading}>
{loading ? 'Connecting...' : 'Start Conversation'}
</button>
);
}
集成模式
Next.js App Router(完整示例)
服务端路由(app/api/avatar/session/route.ts):
完整的服务端会话创建代码请参阅 +rw-integrate-characters。
客户端页面(app/character/page.tsx):
'use client';
import { AvatarCall } from '@runwayml/avatars-react';
import '@runwayml/avatars-react/styles.css';
const AVATAR_ID = process.env.NEXT_PUBLIC_AVATAR_ID || 'your-avatar-id';
export default function CharacterPage() {
return (
<div className="flex items-center justify-center min-h-screen">
<AvatarCall
avatarId={AVATAR_ID}
connectUrl="/api/avatar/session"
onEnd={() => window.location.reload()}
onError={(error) => {
console.error('Avatar error:', error);
alert('Connection failed. Please try again.');
}}
/>
</div>
);
}
条件渲染(显示/隐藏)
'use client';
import { useState } from 'react';
import { AvatarCall } from '@runwayml/avatars-react';
import '@runwayml/avatars-react/styles.css';
export default function SupportPage() {
const [showAvatar, setShowAvatar] = useState(false);
return (
<div>
<h1>Customer Support</h1>
{!showAvatar ? (
<button onClick={() => setShowAvatar(true)}>
Talk to an Agent
</button>
) : (
<AvatarCall
avatarId="support-agent-id"
connectUrl="/api/avatar/session"
onEnd={() => setShowAvatar(false)}
onError={(error) => {
console.error(error);
setShowAvatar(false);
}}
/>
)}
</div>
);
}
错误处理
详细错误日志
<AvatarCall
avatarId="your-avatar-id"
connectUrl="/api/avatar/session"
onError={(error) => {
console.error('Avatar error:', error);
console.error('Error name:', error.name);
console.error('Error message:', error.message);
if (error.cause) {
console.error('Cause:', error.cause);
}
}}
/>
调试会话状态
import { useAvatarSession } from '@runwayml/avatars-react';
function DebugPanel() {
const { state, sessionId, error } = useAvatarSession();
return (
<pre style={{ fontSize: 12, position: 'fixed', top: 0, right: 0 }}>
{JSON.stringify({ state, sessionId, error: error?.message }, null, 2)}
</pre>
);
}
浏览器支持
| 浏览器 | 最低版本 |
|---|---|
| Chrome | 74+ |
| Firefox | 78+ |
| Safari | 14.1+ |
| Edge | 79+ |
用户必须在提示时授予麦克风权限。启用用户视频时,还需要摄像头权限。
提示
- 务必导入样式:使用
AvatarCall时,请导入import '@runwayml/avatars-react/styles.css' - Next.js App Router 中,所有使用 React SDK 的组件都必须添加
'use client'指令 - 会话最长持续时间为 5 分钟——处理
onEnd回调,以显示重新连接选项 - 凭据只能使用一次——如果连接失败,请获取新凭据(创建新会话)
- 完整 SDK 源码、示例和问题跟踪请参阅:github.com/runwayml/avatars-sdk-react
评论
支持 Markdown