# Klleon Chat SDK > AI Avatar Chat JavaScript Library - Web SDK for embedding AI avatar chat interfaces ## en - [📦 SDK Changelog](/en/docs/1.2.0/changelog): Check the major changes for each version of the SDK. - [📦 Klleon Chat SDK v1.0.0](/en/docs/1.2.0/changelog/v1.0.0): Klleon Chat SDK v1.0.0 Release Notes - [📦 Klleon Chat SDK v1.1.0](/en/docs/1.2.0/changelog/v1.1.0): Klleon Chat SDK v1.1.0 Release Notes - [📦 Klleon Chat SDK v1.2.0](/en/docs/1.2.0/changelog/v1.2.0): Klleon Chat SDK v1.2.0 Release Notes - [Custom React Example](/en/docs/1.2.0/examples/custom-react): An advanced example of implementing the Klleon Chat SDK fully in React without using web components. You can build a flexible UI using SDK methods like echo, changeAvatar, STT, and manage state directly. - [React](/en/docs/1.2.0/examples/react): Learn how to integrate Klleon Chat SDK into your React project. From script tag installation to avatar component usage and echo message testing, this example guides you step-by-step. - [Complete Vanilla JS Example](/en/docs/1.2.0/examples/vanilla-js): Run the Klleon Chat SDK directly without any installation using a Vanilla JS example. A single index.html file lets you initialize the SDK, send messages, and test echo speech. - [TypeScript Support](/en/docs/1.2.0/guides/typescript-support): Learn how to use Klleon Chat SDK's TypeScript declaration file (.d.ts) in your project. Safely apply types like KlleonChat interface, InitOption, and ChatData. - [Introduction to Klleon Chat SDK](/en/docs/1.2.0/intro): Klleon Chat SDK is a JavaScript library for easily implementing real-time avatar chat, speech synthesis (TTS), LLM integration, and lip sync in web applications. Start talking with avatars without any server setup. - [Getting Started](/en/docs/1.2.0/setup/getting-started): Step-by-step guide to install Klleon Chat SDK and integrate avatar chat into your web application. Includes domain setup, SDK key issuance, script integration, and a working React example. - [Event Handling](/en/docs/1.2.0/usage/sdk-event): Learn how to handle avatar state changes and chat messages using onChatEvent and onStatusEvent in the Klleon Chat SDK. Detailed flow of VIDEO_CAN_PLAY, chat_type, and status included. - [SDK Methods](/en/docs/1.2.0/usage/sdk-method): Comprehensive guide to using Klleon Chat SDK methods. Learn how to use init, destroy, sendTextMessage, startStt, echo, changeAvatar and more to build interactive avatar chat applications. - [Using UI Components](/en/docs/1.2.0/usage/ui-components): Learn how to use the Klleon Chat SDK's avatar-container and chat-container web components. Understand how to control props, apply styles, and integrate with React. - [📦 SDK Changelog](/en/docs/changelog): Check the major changes for each version of the SDK. - [📦 Klleon Chat SDK v1.0.0](/en/docs/changelog/v1.0.0): Klleon Chat SDK v1.0.0 Release Notes - [📦 Klleon Chat SDK v1.1.0](/en/docs/changelog/v1.1.0): Klleon Chat SDK v1.1.0 Release Notes - [📦 Klleon Chat SDK v1.2.0](/en/docs/changelog/v1.2.0): Klleon Chat SDK v1.2.0 Release Notes - [📦 Klleon Chat SDK v1.3.0](/en/docs/changelog/v1.3.0): Klleon Chat SDK v1.3.0 Release Notes - [Custom React Example](/en/docs/examples/custom-react): An advanced example of implementing the Klleon Chat SDK fully in React without using web components. You can build a flexible UI using SDK methods like echo, changeAvatar, STT, and manage state directly. - [React](/en/docs/examples/react): Learn how to integrate Klleon Chat SDK into your React project. From script tag installation to avatar component usage and echo message testing, this example guides you step-by-step. - [Complete Vanilla JS Example](/en/docs/examples/vanilla-js): Run the Klleon Chat SDK directly without any installation using a Vanilla JS example. A single index.html file lets you initialize the SDK, send messages, and test echo speech. - [TypeScript Support](/en/docs/guides/typescript-support): Learn how to use Klleon Chat SDK's TypeScript declaration file (.d.ts) in your project. Safely apply types like KlleonChat interface, InitOption, and ChatData. - [Introduction to Klleon Chat SDK](/en/docs/intro): Klleon Chat SDK is a JavaScript library for easily implementing real-time avatar chat, speech synthesis (TTS), LLM integration, and lip sync in web applications. Start talking with avatars without any server setup. - [Getting Started](/en/docs/setup/getting-started): Step-by-step guide to install Klleon Chat SDK and integrate avatar chat into your web application. Includes domain setup, SDK key issuance, script integration, and a working React example. - [Event Handling](/en/docs/usage/sdk-event): Learn how to handle avatar state changes, chat messages, and errors using onChatEvent, onStatusEvent, and onErrorEvent in the Klleon Chat SDK. Includes detailed ErrorCode descriptions and error event flow. - [SDK Methods](/en/docs/usage/sdk-method): Comprehensive guide to using Klleon Chat SDK methods. Learn how to use init, destroy, sendTextMessage, startStt, echo, changeAvatar and more to build interactive avatar chat applications. - [Using UI Components](/en/docs/usage/ui-components): Learn how to use the Klleon Chat SDK's avatar-container and chat-container web components. Understand how to control props, apply styles, and integrate with React. --- # Full Documentation Content # 📦 SDK Changelog Check the major changes for each version of the SDK. ## ✨ Latest Version: **v1.2.0** ✨[​](#-latest-version-v120- "Direct link to -latest-version-v120-") * [v1.2.0](/en/docs/changelog/v1.2.0) * [v1.1.0](/en/docs/changelog/v1.1.0) * [v1.0.0](/en/docs/changelog/v1.0.0) --- # 📦 Klleon Chat SDK v1.0.0 ## ✨ Features[​](#-features "Direct link to ✨ Features") * Added `onStatusEvent` event * Added `changeAvatar` method * TypeScript support ## 🔁 Changed[​](#-changed "Direct link to 🔁 Changed") * Renamed `stopEcho` to `stopSpeech` method ## 🛠️ Others[​](#️-others "Direct link to 🛠️ Others") * Changed UI to WebComponent-based * Avatar: `KlleonChat.showStreaming()` → `` * Chat: `KlleonChat.showChatUi()` → `` --- # 📦 Klleon Chat SDK v1.1.0 ## ✨ Features[​](#-features "Direct link to ✨ Features") * Added `cancelStt` method * Added `volume` props to `` --- # 📦 Klleon Chat SDK v1.2.0 ## ✨ Features[​](#-features "Direct link to ✨ Features") * Added `user_key` option to `initOption` --- # Custom React Example This example demonstrates how to implement a fully customized chat interface using the Klleon Chat SDK without relying on its default web components. You’ll be able to design a flexible UI by leveraging SDK events and methods. ## Key Features[​](#key-features "Direct link to Key Features") * **Build Your Own UI**: Use React to construct your own components without relying on SDK web components. * **Reactive UI with SDK Events**: Automatically update the UI using real-time SDK events. * **Direct Method Access**: Explicitly test and control key SDK features. * **UX Based on Avatar Status**: Dynamically control input states based on avatar status. ## Prerequisites[​](#prerequisites "Direct link to Prerequisites") ### Add SDK Script[​](#add-sdk-script "Direct link to Add SDK Script") Add the following script tag inside the `` section of your `public/index.html`. Replace `{VERSION}` with your actual SDK version (e.g., 1.2.0). public/index.html ``` ``` ## Custom React Component[​](#custom-react-component "Direct link to Custom React Component") CSS Styles custom-react-example.css ``` .custom-react-example-page { display: flex; width: 100%; gap: 24px; height: 720px; .klleon-chat-container { display: flex; flex: 1; flex-direction: column; gap: 12px; .avatar-container { flex: 1; } .chat-container { display: flex; flex-direction: column; flex: 1; overflow-y: auto; border-radius: 24px; border: 1px solid #ccc; padding: 12px; gap: 12px; &::-webkit-scrollbar { display: none; } .chat-item { display: flex; flex-direction: column; gap: 12px; background: grey; color: #fff; padding: 12px; border-radius: 12px; } } } .control-container { display: flex; flex-direction: column; flex: 1; gap: 12px; .log-container { display: flex; flex-direction: column; gap: 12px; } .method-container { display: flex; flex-direction: column; flex: 1; gap: 12px; input { width: 320px; } .horizontal-control-item { display: flex; gap: 12px; } .vertical-control-item { display: flex; flex-direction: column; gap: 12px; } } } } ``` App.tsx ``` import { ChatData, ResponseChatType, Status } from "@site/src/types/global"; import { CSSProperties, useEffect, useRef, useState } from "react"; interface AvatarProps { videoStyle?: CSSProperties; volume?: number; } const SDK_KEY = "YOUR_SDK_KEY"; const AVATAR_ID = "YOUR_AVATAR_ID"; const App = () => { const [isLoading, setIsLoading] = useState(false); const [status, setStatus] = useState("IDLE"); const [chatData, setChatData] = useState([]); const [chatType, setChatType] = useState(); const [message, setMessage] = useState(""); const [echoMessage, setEchoMessage] = useState(""); const [isAvatarSpeaking, setIsAvatarSpeaking] = useState(false); const [guideText, setGuideText] = useState( "Please click the start chat button to connect." ); const avatarContainerRef = useRef(null); const chatContainerRef = useRef(null); useEffect(() => { if (avatarContainerRef.current) { avatarContainerRef.current.videoStyle = { borderRadius: "24px", objectFit: "cover", }; } }, []); useEffect(() => { if (chatContainerRef.current) { const observer = new MutationObserver(() => { chatContainerRef.current?.scrollTo({ top: chatContainerRef.current.scrollHeight, behavior: "smooth", }); }); observer.observe(chatContainerRef.current, { childList: true, subtree: true, }); } }, [chatContainerRef.current]); const sdkHandler = { startChat: async () => { const { KlleonChat } = window; KlleonChat.onStatusEvent((status) => { setStatus(status); setIsLoading(status !== "VIDEO_CAN_PLAY"); }); KlleonChat.onChatEvent((chatData) => { setChatType(chatData.chat_type); setChatData((prev) => [...prev, chatData]); if (chatData.chat_type === "PREPARING_RESPONSE") { setIsAvatarSpeaking(true); setGuideText("The avatar is preparing a response. Please wait."); } if (chatData.chat_type === "TEXT") { setGuideText( "The avatar is speaking. You can stop it with stopSpeech." ); } if (chatData.chat_type === "RESPONSE_IS_ENDED") { setIsAvatarSpeaking(false); setGuideText( "The avatar has finished speaking. You can send a new message." ); } }); await KlleonChat.init({ sdk_key: SDK_KEY, avatar_id: AVATAR_ID, }); setGuideText("Connection established."); }, disconnect: () => { const { KlleonChat } = window; KlleonChat.destroy(); setGuideText( "Disconnected. Please click the start chat button to reconnect." ); }, sendTextMessage: () => { const { KlleonChat } = window; KlleonChat.sendTextMessage(message); setMessage(""); }, startStt: () => { const { KlleonChat } = window; KlleonChat.startStt(); setGuideText("Recording... Use endStt or cancelStt to proceed."); }, endStt: () => { const { KlleonChat } = window; KlleonChat.endStt(); setGuideText("Recording finished."); }, cancelStt: () => { const { KlleonChat } = window; KlleonChat.cancelStt(); setGuideText("Recording canceled."); }, stopSpeech: () => { const { KlleonChat } = window; if (chatType === "PREPARING_RESPONSE") { setGuideText("Cannot stop speech while preparing response."); return; } KlleonChat.stopSpeech(); setGuideText("Speech stopped."); }, clearMessage: () => { setChatData([]); }, clearMessageList: () => { const { KlleonChat } = window; KlleonChat.clearMessageList(); }, echo: () => { const { KlleonChat } = window; KlleonChat.echo(echoMessage); setEchoMessage(""); }, changeAvatar: () => { const { KlleonChat } = window; const avatarList = [ "Avatar_ID_1", "Avatar_ID_2", "Avatar_ID_3", "Avatar_ID_4", ]; const randomAvatarId = avatarList[Math.floor(Math.random() * avatarList.length)]; KlleonChat.changeAvatar({ avatar_id: randomAvatarId }); setGuideText("Avatar has been changed."); }, }; return (
{chatData.map((item) => (
ChatType: {item.chat_type}
Message: {item.message}
))}
{isLoading &&
loading...
}
Guide: {guideText}
Status: {status}
setMessage(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" && !e.nativeEvent.isComposing) { sdkHandler.sendTextMessage(); } }} />
setEchoMessage(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" && !e.nativeEvent.isComposing) { sdkHandler.echo(); } }} />
); }; export default App; ``` ## Example Output[​](#example-output "Direct link to Example Output") ##### Guide: Please connect using the start chat button ##### Status: IDLE SDK Lifecycle:start chatdisconnect Send Text Message: Please enter a message.sendTextMessage Send Voice Message:startSttendStt Message ControlcancelSttstopSpeechclearMessage Echo Function Please enter a message.echo Change AvatarchangeAvatar --- # React ## Prerequisites[​](#prerequisites "Direct link to Prerequisites") ### 1. Add SDK Script[​](#1-add-sdk-script "Direct link to 1. Add SDK Script") Add the SDK script inside the `` tag of your `public/index.html` file. public/index.html ``` {/* ... other meta tags and links ... */} React + Klleon Chat SDK {/* TODO: Replace {VERSION} with the actual SDK version (e.g., 1.2.0) */}
``` ### 2. TypeScript Type Support (Optional)[​](#2-typescript-type-support-optional "Direct link to 2. TypeScript Type Support (Optional)") Klleon Chat SDK provides TypeScript declaration files. If you include these `.d.ts` files in your project, you can benefit from full type safety and autocomplete for `window.KlleonChat`, SDK methods, and web component props. ## React Example (`App.tsx`)[​](#react-example-apptsx "Direct link to react-example-apptsx") CSS Styles custom.css ``` .base-react-example-page { width: 100%; height: 100%; .header { margin-bottom: 30px; } .loading-text { position: absolute; font-size: 1.5em; color: #555; padding: 50px; } .start-chat-button { width: 150px; height: 50px; background-color: #3579CC; color: #fff; border-radius: 10px; font-size: 16px; font-weight: 600; border: none; cursor: pointer; } .sdk-container { display: flex; width: 100%; height: 720px; gap: 0px 24px; .avatar-container { flex: 1; } .chat-control-container { display: flex; flex-direction: column; flex: 1; gap: 24px 0px; .chat-container { flex: 1; border-radius: 24px; } .chat-echo-container { display: flex; flex-direction: column; .echo-input { width: 100%; height: 40px; border: 1px solid #ccc; border-radius: 4px; padding: 0 10px; font-size: 16px; margin-bottom: 10px; } .echo-button { width: 100%; height: 40px; border: 1px solid #ccc; border-radius: 4px; padding: 0 10px; background-color: #3579CC; color: #fff; font-size: 16px; font-weight: 600; cursor: pointer; &:disabled { background-color: #ccc; color: #fff; cursor: not-allowed; } } } } } } ``` src/App.tsx ``` import { ChatData, Status } from "@site/src/types/global"; import { useEffect, useRef, useState, CSSProperties } from "react"; // TODO: Replace with your actual SDK key and Avatar ID const SDK_KEY = "YOUR_SDK_KEY"; const AVATAR_ID = "YOUR_AVATAR_ID"; interface AvatarProps { videoStyle?: CSSProperties; volume?: number; } interface ChatProps { delay?: number; type?: "voice" | "text"; isShowCount?: boolean; } function App() { const [echoText, setEchoText] = useState(""); const [isLoading, setIsLoading] = useState(false); const [isChatStarted, setIsChatStarted] = useState(false); const avatarContainerRef = useRef(null); const chatContainerRef = useRef(null); useEffect(() => { if (avatarContainerRef.current) { avatarContainerRef.current.videoStyle = { borderRadius: "24px", objectFit: "cover", }; avatarContainerRef.current.volume = 100; } if (chatContainerRef.current) { chatContainerRef.current.delay = 10; chatContainerRef.current.type = "text"; chatContainerRef.current.isShowCount = true; console.log("chat-container props set via ref."); } }, []); const startChat = async () => { setIsChatStarted(true); const KlleonChat = window.KlleonChat; console.log("SDK detected. Attempting initialization..."); KlleonChat.onStatusEvent((status: Status) => { console.log(`SDK Status Event: ${status}`); setIsLoading(status !== "VIDEO_CAN_PLAY"); }); KlleonChat.onChatEvent((chatData: ChatData) => { console.log("SDK Chat Event:", chatData); }); try { await KlleonChat.init({ sdk_key: SDK_KEY, avatar_id: AVATAR_ID, log_level: "debug", }); console.log("SDK initialized successfully!"); } catch (error) { console.error( `SDK initialization failed: ${(error as Error).message || error}` ); setIsLoading(false); } finally { setIsLoading(false); } }; const handleEcho = () => { window.KlleonChat.echo(echoText); setEchoText(""); }; return (
{!isChatStarted && ( )}
{isLoading && ( Klleon Avatar Loading... )}
setEchoText(e.target.value)} placeholder="Enter echo text..." disabled={isLoading} className="echo-input" />
); } export default App; ``` ## Run the Chat UI[​](#run-the-chat-ui "Direct link to Run the Chat UI") Start Chat Enter echo content...Send echo --- # Complete Vanilla JS Example Save the code below as `index.html`, replace `{VERSION}`, `YOUR_SDK_KEY`, and `YOUR_AVATAR_ID` with actual values, and open it in your browser. You can observe SDK state changes and events via the browser’s developer console. index.html ``` Klleon Chat SDK - Minimal Vanilla JS Example

Klleon Chat SDK - Method Test

``` --- # TypeScript Support Klleon Chat SDK provides a `.d.ts` type declaration file to ensure a smooth development experience and type safety when using TypeScript. This guide explains how to integrate the SDK’s type definitions into your project. ## Type Declaration File (`KlleonSDK.d.ts`)[​](#type-declaration-file-klleonsdkdts "Direct link to type-declaration-file-klleonsdkdts") KlleonSDK.d.ts ``` type BaseStatus = | "IDLE" | "CONNECTING" | "CONNECTING_FAILED" | "SOCKET_CONNECTED" | "SOCKET_FAILED" | "STREAMING_CONNECTED" | "STREAMING_FAILED" | "CONNECTED_FINISH" | "VIDEO_LOAD" | "VIDEO_CAN_PLAY"; type BaseLogLevelType = "debug" | "info" | "warn" | "error" | "silent"; type BaseVoiceCodeType = "ko_kr" | "en_us" | "ja_jp" | "id_id"; type BaseSubtitleCodeType = "ko_kr" | "en_us" | "ja_jp" | "id_id"; enum ResponseChatType { TEXT = "TEXT", STT_RESULT = "STT_RESULT", STT_ERROR = "STT_ERROR", WAIT = "WAIT", WARN_SUSPENDED = "WARN_SUSPENDED", DISABLED_TIME_OUT = "DISABLED_TIME_OUT", TEXT_ERROR = "TEXT_ERROR", TEXT_MODERATION = "TEXT_MODERATION", ERROR = "ERROR", PREPARING_RESPONSE = "PREPARING_RESPONSE", RESPONSE_IS_ENDED = "RESPONSE_IS_ENDED", RESPONSE_OK = "RESPONSE_OK", WORKER_DISCONNECTED = "WORKER_DISCONNECTED", EXCEED_CONCURRENT_QUOTA = "EXCEED_CONCURRENT_QUOTA", START_LONG_WAIT = "START_LONG_WAIT", USER_SPEECH_STARTED = "USER_SPEECH_STARTED", USER_SPEECH_STOPPED = "USER_SPEECH_STOPPED", } export type Status = BaseStatus; export type LogLevelType = BaseLogLevelType; export type VoiceCodeType = BaseVoiceCodeType; export type SubtitleCodeType = BaseSubtitleCodeType; export interface InitOption { sdk_key: string; avatar_id: string; voice_code?: VoiceCodeType; subtitle_code?: SubtitleCodeType; voice_tts_speech_speed?: number; enable_microphone?: boolean; log_level?: LogLevelType; custom_id?: string; user_key?: string; } export interface ChatData { message: string; chat_type: ResponseChatType; time: string; id: string; } export interface ChangeAvatarOption { avatar_id: string; subtitle_code?: SubtitleCodeType; voice_code?: VoiceCodeType; voice_tts_speech_speed?: number; // 0.5 ~ 2.0 } export interface KlleonChat { init: (option: InitOption) => Promise; destroy: () => void; onChatEvent: (callback: (data: ChatData) => void) => void; onStatusEvent: (callback: (status: Status) => void) => void; sendTextMessage: (message: string) => void; startStt: () => void; endStt: () => void; cancelStt: () => void; echo: (message: string) => void; startAudioEcho: (audio: string) => void; endAudioEcho: () => void; changeAvatar: (option: ChangeAvatarOption) => Promise; clearMessageList: () => void; stopSpeech: () => void; } // Declare KlleonChat type in the global window object declare global { interface Window { KlleonChat: KlleonChat; } namespace JSX { interface IntrinsicElements { "avatar-container": React.DetailedHTMLProps< Omit, "className"> & { class?: string; }, HTMLElement >; "chat-container": React.DetailedHTMLProps< Omit, "className"> & { class?: string; }, HTMLElement >; } } } ``` ## `tsconfig.json` Setup[​](#tsconfigjson-setup "Direct link to tsconfigjson-setup") To ensure that TypeScript recognizes your declaration file (`KlleonSDK.d.ts`), include its path in the `tsconfig.json` file. tsconfig.json ``` { "compilerOptions": { "jsx": "react-jsx" }, "include": ["KlleonSDK.d.ts"] } ``` --- # Introduction to Klleon Chat SDK The Klleon Chat SDK is a JavaScript library designed to help you easily integrate Klleon's real-time interactive avatars into your web applications. With this SDK, you can build a live avatar chat interface using just a few lines of code—without needing to configure WebRTC or implement server-side logic. ## Key Features[​](#key-features "Direct link to Key Features") * **Easy Integration**: Quickly set up the Klleon Chat SDK on your web page using a simple `
``` SDK Version Replace `{VERSION}` with the actual version number in `X.Y.Z` format (e.g., `1.0.0`). You can find the latest version via Klleon Studio or official announcements. Using the latest version is recommended, but you can specify a particular version if needed. ## SDK Initialization[​](#sdk-initialization "Direct link to SDK Initialization") After the SDK is loaded, initialize it using `window.KlleonChat.init()`. Initialization typically happens after the DOM is ready, usually inside your main app script. The two required options are `sdk_key` and `avatar_id`. It is recommended to register event listeners before calling `init`. App.tsx (React) ``` import { useEffect } from "react"; function App() { useEffect(() => { const { KlleonChat } = window; const init = async () => { // 1. Register status event listener KlleonChat.onStatusEvent((status) => { // See 'Usage > Event Handling' for detailed Status values and meanings. if (status === "VIDEO_CAN_PLAY") { console.log("Avatar video ready!"); } }); // 2. Register chat event listener KlleonChat.onChatEvent((chatData) => { // See 'Usage > Event Handling' for ChatData structure and chat_type details. console.log("SDK Chat Event:", chatData); }); // 3. Initialize SDK await KlleonChat.init({ sdk_key: "YOUR_SDK_KEY", avatar_id: "YOUR_AVATAR_ID", // custom_id: "YOUR_CUSTOM_ID", // user_key: "YOUR_USER_KEY", // voice_code: "en_us", // subtitle_code: "en_us", // voice_tts_speech_speed: 1, // enable_microphone: true, // log_level: "debug", }); }; init(); }, []); return <>; } export default App; ``` ### Init Options[​](#init-options "Direct link to Init Options") The `init()` method accepts various configuration options: | Parameter | Type | Required | Default | Description | | --------------------------------- | --------------- | --------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | sdk\_key | string | O | - | SDK key issued by Klleon Studio | | avatar\_id | string | O | - | Unique ID of the avatar to be used | | subtitle\_code | string | X | `ko_kr` | Avatar speech subtitle language setting.
Supported codes: `ko_kr` (Korean), `en_us` (English), `ja_jp` (Japanese), `id_id` (Indonesian), etc. | | voice\_code | string | X | `ko_kr` | Avatar speech voice language setting. | | voice\_tts\_speech\_speed | number | X | `1.0` | Avatar speech speed control feature.
Range: 0.5 \~ 2.0 | | enable\_microphone | boolean | X | `true` | When set to `true`, attempts to connect the microphone. The browser will prompt for microphone permission. | | log\_level | string | X | `debug` | Sets the detail level of SDK internal logs. Depending on the set level, the following logs are output:
- When set to `debug`: All `debug`, `info`, `warn`, `error` logs are output (for development and detailed debugging)
- When set to `info`: `info`, `warn`, `error` logs are output
- When set to `warn`: `warn`, `error` logs are output
- When set to `error`: Only `error` logs are output
- When set to `silent`: All log outputs are disabled
For production deployment, it is recommended to use `"silent"` to optimize performance and prevent unnecessary information exposure. | | custom\_id | string | X | - | Sets a custom device identifier or other user-defined identifier used in the client system. | | user\_key | string | X | - | User session management key issued through Klleon Studio's End-User creation API. It can be used for session time adjustment, etc. | About `user_key` The `user_key` is managed through the End-User API. Contact `partnership@klleon.io` for access and usage instructions. ## Full Working Example[​](#full-working-example "Direct link to Full Working Example") Here’s a complete working example showing SDK installation, event handling, and initialization. index.html ``` Vite + React
``` App.tsx ``` import { useEffect, useRef, type CSSProperties } from "react"; interface AvatarProps { videoStyle?: CSSProperties; volume?: number; } interface ChatProps { delay?: number; type?: "voice" | "text"; isShowCount?: boolean; } function App() { const avatarRef = useRef(null); const chatRef = useRef(null); useEffect(() => { const { KlleonChat } = window; const init = async () => { // 1. Register status event listener KlleonChat.onStatusEvent((status) => { // See 'Usage > Event Handling' for detailed Status values and meanings. if (status === "VIDEO_CAN_PLAY") { console.log("Avatar video ready!"); } }); // 2. Register chat event listener KlleonChat.onChatEvent((chatData) => { // See 'Usage > Event Handling' for ChatData structure and chat_type details. console.log("SDK Chat Event:", chatData); }); // 3. Initialize SDK await KlleonChat.init({ sdk_key: "YOUR_SDK_KEY", avatar_id: "YOUR_AVATAR_ID", }); }; init(); if (avatarRef.current) { avatarRef.current.videoStyle = { borderRadius: "30px", objectFit: "cover", }; avatarRef.current.volume = 100; } if (chatRef.current) { chatRef.current.delay = 30; chatRef.current.type = "text"; chatRef.current.isShowCount = true; } return () => { KlleonChat.destroy(); }; }, []); return (
); } export default App; ``` ### Live Example[​](#live-example "Direct link to Live Example") **start chat!** --- # Event Handling Klleon Chat SDK uses custom events to notify your application of real-time state changes and data. By subscribing to these events, you can build dynamic experiences aligned with the SDK’s behavior. ## Registering and Managing Event Listeners[​](#registering-and-managing-event-listeners "Direct link to Registering and Managing Event Listeners") ### `KlleonChat.onChatEvent(callback)`[​](#klleonchatonchateventcallback "Direct link to klleonchatonchateventcallback") Registers a callback function that is triggered whenever a chat message related to the avatar or user is received. This allows you to build a custom chat UI without relying on the SDK’s `` component. * **callback** (`(data: ChatData) => void`, required): A function that receives a `ChatData` object. ``` function handleChatMessage(chatData) { console.log("New chat message:", chatData); } window.KlleonChat.onChatEvent(handleChatMessage); ``` #### `ChatData` Object and `ResponseChatType` Details[​](#chatdata-object-and-responsechattype-details "Direct link to chatdata-object-and-responsechattype-details") * ChatData Object Properties * ResponseChatType Details The properties of the `ChatData` object passed to `onChatEvent` are: | Property Name | Type | Description | | ------------------ | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | | message | string | Content of the received message. | | chat\_type | string (ResponseChatType) | Indicates the type of message. For possible values, refer to the 'ResponseChatType Values Detail' tab. | | time | string | String representation of the time when the message occurred. (e.g., ISO 8601 format) | | id | string | Unique identifier of the message. | Values and meanings of the `chat_type` field in the `ChatData` object. (See `BaseResponseChatType`) | ResponseChatType Value | Description | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | TEXT | Text message sent by the avatar. Mainly occurs as an avatar response after using `KlleonChat.echo()` or `KlleonChat.sendTextMessage()` methods. | | STT\_RESULT | Result when user's voice (STT) is successfully converted to text. | | STT\_ERROR | Occurs when user voice (STT) conversion or transmission fails. Mainly occurs when there is no voice data. | | WAIT | Occurs when waiting to start chatting. | | WARN\_SUSPENDED | Warns that chatting will be suspended soon if there is no chat for a certain period (e.g., 10 seconds). | | DISABLED\_TIME\_OUT | Occurs when the session is suspended due to no chat for a long time. | | TEXT\_ERROR | Occurs when the text message sent by the user fails to transmit. | | TEXT\_MODERATION | Occurs when the message is filtered because the user used inappropriate language. | | ERROR | Delivered when a general error occurs on the server side. (e.g., internal server error, specific request processing failure, etc.) | | PREPARING\_RESPONSE | Occurs when the avatar is preparing a response to the user's message. | | RESPONSE\_IS\_ENDED | Indicates that one turn of the avatar (response that may include multiple sentences generated by LLM) has completely ended. | | RESPONSE\_OK | Indicates that the avatar has successfully prepared a response to the user's message or started speaking. | | WORKER\_DISCONNECTED | Occurs when the connection with the avatar streaming worker is disconnected. | | EXCEED\_CONCURRENT\_QUOTA | Occurs when the connection is rejected because the maximum allowed number of concurrent users is exceeded. | | START\_LONG\_WAIT | Occurs when the avatar transitions to a long wait state due to no interaction with the user for a specified time. | | USER\_SPEECH\_STARTED | Occurs when the SDK starts detecting user voice input. | | USER\_SPEECH\_STOPPED | Occurs when the SDK detects that user voice input has stopped. | | ACTIVATE\_VOICE | Occurs when voice input is activated. In this state, chat input is available even if the avatar is not in `VIDEO_CAN_PLAY` status. | | RATE\_LIMIT | Request rate limit exceeded | | HANDOVER\_START | Handover started | | HANDOVER\_SUCCESS | Handover succeeded | | HANDOVER\_FAIL | Handover failed | ### ChatData Flow[​](#chatdata-flow "Direct link to ChatData Flow") #### Sending a Text Message[​](#sending-a-text-message "Direct link to Sending a Text Message") #### Sending a Voice Message[​](#sending-a-voice-message "Direct link to Sending a Voice Message") *** ### `KlleonChat.onStatusEvent(callback)`[​](#klleonchatonstatuseventcallback "Direct link to klleonchatonstatuseventcallback") Registers a callback function that is triggered when the SDK or avatar’s internal status changes. * **callback** (`(status: Status) => void`, required): A function receiving the current status as a string. ``` function handleSdkStatus(currentStatus) { console.log("SDK Status Changed:", currentStatus); if (currentStatus === "VIDEO_CAN_PLAY") { console.log("Avatar video is ready! You can now use other SDK methods."); } } window.KlleonChat.onStatusEvent(handleSdkStatus); ``` SDK Method Usage Prerequisite Most SDK methods (e.g., sending messages, STT functions) must be called only when the avatar is fully connected and in a **`VIDEO_CAN_PLAY`** state. This state is communicated through `onStatusEvent`. Calling methods before this state may lead to unexpected behavior. `KlleonChat.init()` and event listener methods (`onChatEvent`, `onStatusEvent`) are exceptions to this rule. #### Status Event Arguments[​](#status-event-arguments "Direct link to Status Event Arguments") | Type | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | string (Status) | String representing the current status of the SDK and avatar. For possible values, refer to the 'Status Values Detail' table below. | #### Available Status Values[​](#available-status-values "Direct link to Available Status Values") | Status Value | Description | | -------------------------- | ------------------------------------------------------------------------------------------------ | | IDLE | SDK is initialized but not yet connected, in idle state. | | CONNECTING | Status after validating and passing `sdk_key` and `avatar_id` before session connection. | | CONNECTING\_FAILED | Status when validation failed due to incorrect `sdk_key` or `avatar_id` values. | | SOCKET\_CONNECTED | Status when successfully connected to the WebSocket server. | | SOCKET\_FAILED | Status when WebSocket server connection failed. | | STREAMING\_FAILED | Status when media streaming (WebRTC) server connection failed. | | CONNECTED\_FINISH | Status when all connections (WebSocket, streaming) are successfully completed. | | VIDEO\_LOAD | Status when avatar video data loading has started. | | VIDEO\_CAN\_PLAY | Avatar video is ready to play and most SDK methods can be called in this prepared state. | #### Status Event Flow[​](#status-event-flow "Direct link to Status Event Flow") Re-registering Callbacks If `onChatEvent` or `onStatusEvent` is called multiple times for the same event type, only the most recently registered callback remains active. Older callbacks are automatically removed. There’s no explicit `off` method. --- # SDK Methods Klleon Chat SDK provides a variety of methods for interactive communication within your web application. This guide covers core functionalities from SDK initialization to message sending and avatar control. ## SDK Lifecycle[​](#sdk-lifecycle "Direct link to SDK Lifecycle") Properly managing the SDK's lifecycle is crucial for preventing resource leaks and ensuring application stability. ### `KlleonChat.init(options)`[​](#klleonchatinitoptions "Direct link to klleonchatinitoptions") Initializes the SDK and prepares the connection to the server. This method should be called once when the application loads. **Initialization Options (`options`):** | Parameter | Type | Required | Default | Description | | --------------------------------- | --------------- | --------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | sdk\_key | string | O | - | SDK key issued by Klleon Studio | | avatar\_id | string | O | - | Unique ID of the avatar to be used | | subtitle\_code | string | X | `ko_kr` | Avatar speech subtitle language setting.
Supported codes: `ko_kr` (Korean), `en_us` (English), `ja_jp` (Japanese), `id_id` (Indonesian), etc. | | voice\_code | string | X | `ko_kr` | Avatar speech voice language setting. | | voice\_tts\_speech\_speed | number | X | `1.0` | Avatar speech speed control feature.
Range: 0.5 \~ 2.0 | | enable\_microphone | boolean | X | `true` | When set to `true`, attempts to connect the microphone. The browser will prompt for microphone permission. | | log\_level | string | X | `debug` | Sets the detail level of SDK internal logs. Depending on the set level, the following logs are output:
- When set to `debug`: All `debug`, `info`, `warn`, `error` logs are output (for development and detailed debugging)
- When set to `info`: `info`, `warn`, `error` logs are output
- When set to `warn`: `warn`, `error` logs are output
- When set to `error`: Only `error` logs are output
- When set to `silent`: All log outputs are disabled
For production deployment, it is recommended to use `"silent"` to optimize performance and prevent unnecessary information exposure. | | custom\_id | string | X | - | Sets a custom device identifier or other user-defined identifier used in the client system. | | user\_key | string | X | - | User session management key issued through Klleon Studio's End-User creation API. It can be used for session time adjustment, etc. | Best Practice It is recommended to call `KlleonChat.init()` only once per SDK instance. The SDK includes internal logic to prevent duplicate initialization, so even if called multiple times, only the first call will take effect. For optimal performance and clear code management, call `init()` only once during application load. ### `KlleonChat.destroy()`[​](#klleonchatdestroy "Direct link to klleonchatdestroy") Cleans up all resources used by the SDK (socket connections, WebRTC connections, event listeners, etc.) and fully shuts down the SDK. **Usage Example (Initialization and Cleanup):** App.tsx (SDK Lifecycle Management) ``` import { useEffect } from "react"; const App = () => { useEffect(() => { const init = async () => { const { KlleonChat } = window; await KlleonChat.init({ sdk_key: "YOUR_SDK_KEY", avatar_id: "YOUR_AVATAR_ID", subtitle_code: "en_us", voice_code: "en_us", voice_tts_speech_speed: 1.0, enable_microphone: true, log_level: "debug", custom_id: "YOUR_CUSTOM_ID", user_key: "YOUR_USER_KEY", }); }; return () => { // Clean up all KlleonChat SDK resources and shut down. window.KlleonChat.destroy(); }; }, []); return (
); }; export default App; ``` ## Sending Messages[​](#sending-messages "Direct link to Sending Messages") ### `KlleonChat.sendTextMessage(text)`[​](#klleonchatsendtextmessagetext "Direct link to klleonchatsendtextmessagetext") Sends a user-entered text message to the avatar. * **text** (string, required): The text message to send to the avatar. **Usage Example:** App.tsx (sendTextMessage) ``` import { useRef } from "react"; const App = () => { const inputRef = useRef(null); const handleSend = () => { const text = inputRef.current?.value.trim(); if (text) { window.KlleonChat.sendTextMessage(text); inputRef.current.value = ""; } }; return (
); }; ``` ## Voice Input (STT: Speech-to-Text)[​](#voice-input-stt-speech-to-text "Direct link to Voice Input (STT: Speech-to-Text)") A feature that converts user voice input to text and sends it to the avatar. Use `startStt()` to begin voice input and `endStt()` to finish and send. Microphone Permission To use voice conversation features, browser microphone permission is required. Setting `enable_microphone: true` (default) in `init()` will prompt the SDK to request microphone access. ### `KlleonChat.startStt()` / `KlleonChat.endStt()`[​](#klleonchatstartstt--klleonchatendstt "Direct link to klleonchatstartstt--klleonchatendstt") * **`KlleonChat.startStt()`**: Begins collecting voice data through the microphone. * **`KlleonChat.endStt()`**: Stops the ongoing voice data collection, converts the collected audio to text, and sends it as a message to the avatar. **Usage Example:** App.tsx (startStt, endStt) ``` import { useRef } from "react"; const App = () => { const recordButtonRef = useRef(null); const isRecording = useRef(false); const handleRecord = () => { if (!isRecording.current) { window.KlleonChat.startStt(); isRecording.current = true; } if (isRecording.current) { window.KlleonChat.endStt(); isRecording.current = false; } }; return (
); }; export default App; ``` ## Avatar Speech Control[​](#avatar-speech-control "Direct link to Avatar Speech Control") ### `KlleonChat.cancelStt()`[​](#klleonchatcancelstt "Direct link to klleonchatcancelstt") Cancels an ongoing voice input (after calling `startStt()`). The cancelled voice data will not be sent to the avatar, and the system returns to a state ready for new voice input. Use this when the user wants to cancel their voice input mid-recording. **Usage Example:** App.tsx (cancelStt) ``` import { useRef } from "react"; const App = () => { const recordButtonRef = useRef(null); const cancelButtonRef = useRef(null); const isRecording = useRef(false); const handleRecord = () => { if (!isRecording.current) { window.KlleonChat.startStt(); isRecording.current = true; } if (isRecording.current) { window.KlleonChat.endStt(); isRecording.current = false; } }; const handleCancel = () => { window.KlleonChat.cancelStt(); isRecording.current = false; }; return (
); }; export default App; ``` ### `KlleonChat.stopSpeech()`[​](#klleonchatstopspeech "Direct link to klleonchatstopspeech") Immediately stops the avatar's current speech (TTS) output. **Usage Example:** App.tsx (stopSpeech) ``` import { useRef } from "react"; const App = () => { const recordButtonRef = useRef(null); const stopSpeechButtonRef = useRef(null); const isRecording = useRef(false); const handleRecord = () => { if (!isRecording.current) { window.KlleonChat.startStt(); isRecording.current = true; } if (isRecording.current) { window.KlleonChat.endStt(); isRecording.current = false; } }; const handleStopSpeech = () => { window.KlleonChat.stopSpeech(); }; return (
); }; export default App; ``` ## Echo Feature[​](#echo-feature "Direct link to Echo Feature") ### `KlleonChat.echo(text)`[​](#klleonchatechotext "Direct link to klleonchatechotext") Requests the avatar to speak the provided `text` string directly via TTS. * **text** (string, required): The text message for the avatar to speak. **Usage Example:** App.tsx (echo) ``` import { useRef } from "react"; const App = () => { const inputRef = useRef(null); const handleSend = () => { const text = inputRef.current?.value.trim(); if (text) { window.KlleonChat.echo(text); inputRef.current.value = ""; } }; return (
); }; ``` ### `KlleonChat.startAudioEcho(audio)` / `KlleonChat.endAudioEcho()`[​](#klleonchatstartaudioechoaudio--klleonchatendaudioecho "Direct link to klleonchatstartaudioechoaudio--klleonchatendaudioecho") * **`KlleonChat.startAudioEcho(audio)`**: Sends Base64-encoded `audio` string data to the server, requesting the avatar to speak the audio. You must explicitly call `endAudioEcho()` to terminate the session. * `audio` (string, required): Base64-encoded audio data string. (0.1MB limit, must be valid Base64) * **`KlleonChat.endAudioEcho()`**: Terminates the audio echo session and sends a signal to the server for smooth video transition. **Usage Example:** App.tsx (startAudioEcho, endAudioEcho) ``` import { useRef } from "react"; const App = () => { const audioInputRef = useRef(null); const handleStartAudioEcho = () => { const audioData = audioInputRef.current?.value.trim(); if (audioData) { try { window.KlleonChat.startAudioEcho(audioData); console.log("Audio echo started."); // Call endAudioEcho immediately after sending audio (recommended) setTimeout(() => { window.KlleonChat.endAudioEcho(); console.log("Audio echo ended."); }, 100); } catch (error) { console.error("Failed to start audio echo:", error); } } }; const handleMultipleAudioEcho = async () => { const audioList = [ "base64_audio_data_1", "base64_audio_data_2", "base64_audio_data_3", ]; try { // Send multiple audio segments consecutively for (const audio of audioList) { await window.KlleonChat.startAudioEcho(audio); console.log("Audio sent:", audio); } // Call endAudioEcho only once after the last audio segment window.KlleonChat.endAudioEcho(); console.log("All audio echo ended."); } catch (error) { console.error("Audio echo processing failed:", error); } }; return (