mcpField
T
tavus-cvi-ui

tavus-cvi-ui

github.com/tavus-engineering开发960 次安装39 周前更新
代码仓库

关于 tavus-cvi-ui

Tavus CVI React UI Components 提供预构建的 React 组件和 hooks,用于在应用中嵌入 CVI 对话,面向开发 React 界面的开发者。它也提供 iframe 嵌入方案,以及通话前设备检查组件。

主要功能

  1. 01预构建的对话界面组件
  2. 02CVI 上下文提供器
  3. 03接收和发送事件的 hooks
  4. 04iframe 嵌入选项
  5. 05HairCheck 通话前设备检查
  6. 06服务端对话 API 示例

适用场景

  1. 01在 React 应用中嵌入 CVI 视频对话
  2. 02处理对话事件并发送交互
  3. 03在通话前添加设备检查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tavus-engineering/tavus-skills --skill tavus-cvi-ui

安装后在 Claude Code 中输入/tavus-cvi-ui确认已加载。

详细介绍

Tavus CVI React UI 组件

用于嵌入 CVI 对话的预构建 React 组件。

快速设置(Vite)

npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npx @tavus/cvi-ui@latest init
npx @tavus/cvi-ui@latest add conversation

创建:

src/components/cvi/components/
├── cvi-provider.tsx
└── conversation.tsx

在项目根目录中创建 cvi-components.json:

{
  "tsx": true
}

环境变量

项目根目录中的 .env:

VITE_TAVUS_API_KEY=your_api_key
VITE_REPLICA_ID=rfe12d8b9597
VITE_PERSONA_ID=pdced222244b

基本实现

import { useState } from "react";
import { CVIProvider } from "./components/cvi/components/cvi-provider";
import { Conversation } from "./components/cvi/components/conversation";

export default function App() {
  const [url, setUrl] = useState<string | null>(null);

  const startConversation = async () => {
    const res = await fetch("https://tavusapi.com/v2/conversations", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": import.meta.env.VITE_TAVUS_API_KEY,
      },
      body: JSON.stringify({
        replica_id: import.meta.env.VITE_REPLICA_ID,
        persona_id: import.meta.env.VITE_PERSONA_ID,
      }),
    });
    const data = await res.json();
    setUrl(data.conversation_url);
  };

  return (
    <CVIProvider>
      {!url ? (
        <button onClick={startConversation}>Start</button>
      ) : (
        <Conversation 
          conversationUrl={url} 
          onLeave={() => setUrl(null)} 
        />
      )}
    </CVIProvider>
  );
}

组件:CVIProvider

包装应用并提供 CVI 上下文:

import { CVIProvider } from "./components/cvi/components/cvi-provider";

function App() {
  return (
    <CVIProvider>
      {/* Your app */}
    </CVIProvider>
  );
}

组件:Conversation

主要的视频对话 UI:

<Conversation
  conversationUrl={url}
  onLeave={() => setUrl(null)}
/>

必需:父容器必须具有已定义的尺寸。

<div style={{ width: "100%", height: "600px" }}>
  <Conversation conversationUrl={url} onLeave={handleLeave} />
</div>

Hooks

useAppMessage

监听 CVI 事件:

import { useAppMessage } from "./components/cvi/hooks/use-app-message";

function MyComponent() {
  useAppMessage((event) => {
    if (event.event_type === "conversation.utterance") {
      console.log("Said:", event.properties.content);
    }
  });
  
  return <div>...</div>;
}
useSendAppMessage

向 CVI 发送交互:

import { useSendAppMessage } from "./components/cvi/hooks/use-send-app-message";

function Controls() {
  const send = useSendAppMessage();
  
  const interrupt = () => {
    send({
      message_type: "conversation",
      event_type: "conversation.interrupt",
      conversation_id: "xxx"
    });
  };
  
  return <button onClick={interrupt}>Stop</button>;
}

替代方案:iframe 嵌入

适用于非 React 环境或快速集成:

<iframe
  src="CONVERSATION_URL"
  allow="camera; microphone; display-capture"
  style="width: 100%; height: 600px; border: none;"
></iframe>

服务端 API 调用(推荐)

将 API 密钥保留在服务器上:

// pages/api/conversation.ts (Next.js)
export default async function handler(req, res) {
  const response = await fetch("https://tavusapi.com/v2/conversations", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": process.env.TAVUS_API_KEY,
    },
    body: JSON.stringify({
      replica_id: process.env.REPLICA_ID,
      persona_id: process.env.PERSONA_ID,
    }),
  });
  
  const data = await response.json();
  res.json({ conversation_url: data.conversation_url });
}

客户端调用你的 API:

const res = await fetch("/api/conversation", { method: "POST" });
const { conversation_url } = await res.json();

设置对话样式

使用带样式的容器进行包装:

<div style={{
  width: "100%",
  maxWidth: "900px",
  margin: "0 auto",
  borderRadius: "12px",
  overflow: "hidden",
  boxShadow: "0 4px 20px rgba(0,0,0,0.15)",
}}>
  <Conversation conversationUrl={url} onLeave={onLeave} />
</div>

HairCheck 组件

通话前设备检查:

npx @tavus/cvi-ui@latest add haircheck
import { HairCheck } from "./components/cvi/components/haircheck";

<HairCheck onComplete={() => setShowConversation(true)} />

示例项目

评论

支持 Markdown