Compare commits
6 Commits
deprecate-
...
update-ava
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a25c1d520 | ||
|
|
e0150f55b3 | ||
|
|
e259bdfe23 | ||
|
|
d012ef3e3c | ||
|
|
e2763a2cb4 | ||
|
|
ba8fbf7be4 |
3
.env
3
.env
@@ -1 +1,2 @@
|
||||
HEYGEN_API_KEY=your Heygen API key
|
||||
HEYGEN_API_KEY="your Heygen API key"
|
||||
NEXT_PUBLIC_BASE_API_URL=https://api.heygen.com
|
||||
|
||||
@@ -5,18 +5,16 @@ export async function POST() {
|
||||
if (!HEYGEN_API_KEY) {
|
||||
throw new Error("API key is missing from .env");
|
||||
}
|
||||
const baseApiUrl = process.env.NEXT_PUBLIC_BASE_API_URL;
|
||||
|
||||
const res = await fetch(
|
||||
"https://api.heygen.com/v1/streaming.create_token",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"x-api-key": HEYGEN_API_KEY,
|
||||
},
|
||||
const res = await fetch(`${baseApiUrl}/v1/streaming.create_token`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"x-api-key": HEYGEN_API_KEY,
|
||||
},
|
||||
);
|
||||
const data = await res.json();
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
return new Response(data.data.token, {
|
||||
status: 200,
|
||||
});
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
export const AVATARS = [
|
||||
{
|
||||
avatar_id: "Eric_public_pro2_20230608",
|
||||
name: "Edward in Blue Shirt",
|
||||
avatar_id: "Ann_Therapist_public",
|
||||
name: "Ann Therapist",
|
||||
},
|
||||
{
|
||||
avatar_id: "Tyler-incasualsuit-20220721",
|
||||
name: "Tyler in Casual Suit",
|
||||
avatar_id: "Shawn_Therapist_public",
|
||||
name: "Shawn Therapist",
|
||||
},
|
||||
{
|
||||
avatar_id: "Anna_public_3_20240108",
|
||||
name: "Anna in Brown T-shirt",
|
||||
avatar_id: "Bryan_FitnessCoach_public",
|
||||
name: "Bryan Fitness Coach",
|
||||
},
|
||||
{
|
||||
avatar_id: "Susan_public_2_20240328",
|
||||
name: "Susan in Black Shirt",
|
||||
avatar_id: "Dexter_Doctor_Standing2_public",
|
||||
name: "Dexter Doctor Standing",
|
||||
},
|
||||
{
|
||||
avatar_id: "josh_lite3_20230714",
|
||||
name: "Joshua Heygen CEO",
|
||||
avatar_id: "Elenora_IT_Sitting_public",
|
||||
name: "Elenora Tech Expert",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ import type { StartAvatarResponse } from "@heygen/streaming-avatar";
|
||||
|
||||
import StreamingAvatar, {
|
||||
AvatarQuality,
|
||||
StreamingEvents, TaskMode, TaskType, VoiceEmotion,
|
||||
StreamingEvents,
|
||||
TaskMode,
|
||||
TaskType,
|
||||
VoiceEmotion,
|
||||
} from "@heygen/streaming-avatar";
|
||||
import {
|
||||
Button,
|
||||
@@ -23,7 +26,7 @@ import { useMemoizedFn, usePrevious } from "ahooks";
|
||||
|
||||
import InteractiveAvatarTextInput from "./InteractiveAvatarTextInput";
|
||||
|
||||
import {AVATARS, STT_LANGUAGE_LIST} from "@/app/lib/constants";
|
||||
import { AVATARS, STT_LANGUAGE_LIST } from "@/app/lib/constants";
|
||||
|
||||
export default function InteractiveAvatar() {
|
||||
const [isLoadingSession, setIsLoadingSession] = useState(false);
|
||||
@@ -32,7 +35,7 @@ export default function InteractiveAvatar() {
|
||||
const [debug, setDebug] = useState<string>();
|
||||
const [knowledgeId, setKnowledgeId] = useState<string>("");
|
||||
const [avatarId, setAvatarId] = useState<string>("");
|
||||
const [language, setLanguage] = useState<string>('en');
|
||||
const [language, setLanguage] = useState<string>("en");
|
||||
|
||||
const [data, setData] = useState<StartAvatarResponse>();
|
||||
const [text, setText] = useState<string>("");
|
||||
@@ -41,6 +44,10 @@ export default function InteractiveAvatar() {
|
||||
const [chatMode, setChatMode] = useState("text_mode");
|
||||
const [isUserTalking, setIsUserTalking] = useState(false);
|
||||
|
||||
function baseApiUrl() {
|
||||
return process.env.NEXT_PUBLIC_BASE_API_URL;
|
||||
}
|
||||
|
||||
async function fetchAccessToken() {
|
||||
try {
|
||||
const response = await fetch("/api/get-access-token", {
|
||||
@@ -64,6 +71,7 @@ export default function InteractiveAvatar() {
|
||||
|
||||
avatar.current = new StreamingAvatar({
|
||||
token: newToken,
|
||||
basePath: baseApiUrl(),
|
||||
});
|
||||
avatar.current.on(StreamingEvents.AVATAR_START_TALKING, (e) => {
|
||||
console.log("Avatar started talking", e);
|
||||
@@ -95,6 +103,12 @@ export default function InteractiveAvatar() {
|
||||
voice: {
|
||||
rate: 1.5, // 0.5 ~ 1.5
|
||||
emotion: VoiceEmotion.EXCITED,
|
||||
// elevenlabsSettings: {
|
||||
// stability: 1,
|
||||
// similarity_boost: 1,
|
||||
// style: 1,
|
||||
// use_speaker_boost: false,
|
||||
// },
|
||||
},
|
||||
language: language,
|
||||
disableIdleTimeout: true,
|
||||
@@ -103,7 +117,7 @@ export default function InteractiveAvatar() {
|
||||
setData(res);
|
||||
// default to voice mode
|
||||
await avatar.current?.startVoiceChat({
|
||||
useSilencePrompt: false
|
||||
useSilencePrompt: false,
|
||||
});
|
||||
setChatMode("voice_mode");
|
||||
} catch (error) {
|
||||
@@ -120,9 +134,11 @@ export default function InteractiveAvatar() {
|
||||
return;
|
||||
}
|
||||
// speak({ text: text, task_type: TaskType.REPEAT })
|
||||
await avatar.current.speak({ text: text, taskType: TaskType.REPEAT, taskMode: TaskMode.SYNC }).catch((e) => {
|
||||
setDebug(e.message);
|
||||
});
|
||||
await avatar.current
|
||||
.speak({ text: text, taskType: TaskType.REPEAT, taskMode: TaskMode.SYNC })
|
||||
.catch((e) => {
|
||||
setDebug(e.message);
|
||||
});
|
||||
setIsLoadingRepeat(false);
|
||||
}
|
||||
async function handleInterrupt() {
|
||||
@@ -131,11 +147,9 @@ export default function InteractiveAvatar() {
|
||||
|
||||
return;
|
||||
}
|
||||
await avatar.current
|
||||
.interrupt()
|
||||
.catch((e) => {
|
||||
setDebug(e.message);
|
||||
});
|
||||
await avatar.current.interrupt().catch((e) => {
|
||||
setDebug(e.message);
|
||||
});
|
||||
}
|
||||
async function endSession() {
|
||||
await avatar.current?.stopAvatar();
|
||||
@@ -261,9 +275,7 @@ export default function InteractiveAvatar() {
|
||||
}}
|
||||
>
|
||||
{STT_LANGUAGE_LIST.map((lang) => (
|
||||
<SelectItem key={lang.key}>
|
||||
{lang.label}
|
||||
</SelectItem>
|
||||
<SelectItem key={lang.key}>{lang.label}</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "^0.0.34",
|
||||
"@heygen/streaming-avatar": "^2.0.8",
|
||||
"@heygen/streaming-avatar": "^2.0.10",
|
||||
"@nextui-org/button": "2.0.34",
|
||||
"@nextui-org/chip": "^2.0.32",
|
||||
"@nextui-org/code": "2.0.29",
|
||||
@@ -32,7 +32,6 @@
|
||||
"ahooks": "^3.8.1",
|
||||
"ai": "^3.2.15",
|
||||
"clsx": "2.1.1",
|
||||
"framer-motion": "~11.1.1",
|
||||
"intl-messageformat": "^10.5.0",
|
||||
"next": "14.2.4",
|
||||
"next-themes": "^0.2.1",
|
||||
|
||||
8575
pnpm-lock.yaml
generated
Normal file
8575
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user