ElevenLabs + React:建構語音互動介面
ElevenLabs + React: Building a Voice-Enabled UI
這篇教學示範如何在 React 介面串接 ElevenLabs,將用戶輸入的文字轉換成語音並在瀏覽器播放。內容提供一般生成及串流音訊的程式碼,並提及 ElevenLabs 每月免費額度為 10 k 個字元,超出後按用量收費。
Why Voice‑First UI Matters Today
If you’ve been watching the rise of voice assistants, you’ve probably noticed a shift from “nice‑to‑have” to “must‑have.” Users expect apps to respond instantly, and hearing a natural‑sounding voice can make a UI feel more personal, accessible, and engaging.
Enter ElevenLabs, a text‑to‑speech (TTS) platform that delivers ultra‑realistic voices and even lets you clone your own. The service is API‑first, which means you can drop it into any front‑end stack—React included—without wrestling with heavy SDKs or on‑prem models.
In this post I’ll walk you through wiring up a simple voice‑enabled React component that:
- Sends user‑typed text to ElevenLabs.
- Streams the generated audio back to the browser.
- Handles playback controls so the UI feels snappy.
All of this can be done with a handful of lines of JavaScript and a free ElevenLabs account (sign up via my affiliate link: https://try.elevenlabs.io/kr07zfuqn1bp).
Getting Started: Prerequisites
- Node.js (v16+ recommended)
- Create‑React‑App or any React starter of your choice
- An ElevenLabs API key (grab it from the dashboard after signing up)
Pro tip: If you want to experiment with voice cloning, upload a short sample of your own voice in the ElevenLabs console. The cloned voice works the same way as the built‑in models.
Step 1 – Set Up the React Project
npx create-react-app voice-ui-demo
cd voice-ui-demo
npm install axios
We’ll use axios for HTTP requests because it handles streaming responses nicely, but fetch works just as well.
Step 2 – Create a Tiny API Wrapper
Create a new file src/elevenlabs.js:
// src/elevenlabs.js
import axios from "axios";
const API_KEY = process.env.REACT_APP_ELEVENLABS_API_KEY;
const BASE_URL = "https://api.elevenlabs.io/v1";
export const generateSpeech = async (text, voiceId = "EXAVITQu4vr4xnGd") => {
const response = await axios({
method: "post",
url: `${BASE_URL}/text-to-speech/${voiceId}`,
headers: {
"xi-api-key": API_KEY,
"Content-Type": "application/json",
Accept: "audio/mpeg",
},
data: {
text,
// optional: voice settings like stability & similarity_boost
voice_settings: { stability: 0.75, similarity_boost: 0.85 },
},
responseType: "blob", // we want raw audio data
});
return URL.createObjectURL(response.data);
};
Note: Replace
REACT_APP_ELEVENLABS_API_KEYin your.envfile with the key you got from ElevenLabs (https://try.elevenlabs.io/kr07zfuqn1bp). React will automatically inject it at build time.
Step 3 – Build the UI Component
// src/components/VoiceInput.jsx
import { useState } from "react";
import { generateSpeech } from "../elevenlabs";
export default function VoiceInput() {
const [text, setText] = useState("");
const [audioUrl, setAudioUrl] = useState(null);
const [loading, setLoading] = useState(false);
const handleSpeak = async () => {
if (!text.trim()) return;
setLoading(true);
try {
const url = await generateSpeech(text);
setAudioUrl(url);
} catch (err) {
console.error("TTS error:", err);
} finally {
setLoading(false);
}
};
return (
<div style={{ maxWidth: "480px", margin: "auto", padding: "1rem" }}>
<h2>🗣️ Talk to Your App</h2>
<textarea
rows={4}
placeholder="Type something…"
value={text}
onChange={(e) => setText(e.target.value)}
style={{ width: "100%", marginBottom: "0.5rem" }}
/>
<button onClick={handleSpeak} disabled={loading}>
{loading ? "Generating…" : "Speak"}
</button>
{audioUrl && (
<div style={{ marginTop: "1rem" }}>
<audio controls src={audioUrl} />
</div>
)}
</div>
);
}
Add the component to App.js:
import VoiceInput from "./components/VoiceInput";
function App() {
return (
<div className="App">
<VoiceInput />
</div>
);
}
export default App;
That’s it—type a sentence, hit Speak, and you’ll hear a high‑fidelity voice rendered by ElevenLabs.
Step 4 – Streaming (Optional, but Cool)
If you want to start playback before the whole file finishes downloading, you can switch the Axios call to a ReadableStream. Here’s a quick sketch:
export const streamSpeech = async (text, voiceId = "EXAVITQu4vr4xnGd") => {
const response = await fetch(`${BASE_URL}/text-to-speech/${voiceId}`, {
method: "POST",
headers: {
"xi-api-key": API_KEY,
"Content-Type": "application/json",
Accept: "audio/mpeg",
},
body: JSON.stringify({ text, voice_settings: { stability: 0.75 } }),
});
const reader = response.body.getReader();
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
const blob = new Blob(chunks, { type: "audio/mpeg" });
return URL.createObjectURL(blob);
};
Swap generateSpeech with streamSpeech in the component and you’ll notice the audio starts playing almost instantly—a nice UX win for longer passages.
Real‑World Use Cases
| Scenario | How ElevenLabs Helps |
|---|---|
| Accessibility | Convert UI text, error messages, or form hints into speech for screen‑reader‑free experiences. |
| Interactive Games | NPCs can speak dynamically generated dialogue without pre‑recorded assets. |
| Customer Support Bots | Pair a chat‑bot with a voice channel for a truly omnichannel feel. |
| Personalized Assistants | Clone a brand’s voice (or your own) and keep the tone consistent across all touchpoints. |
Because the API is stateless, you can spin up a micro‑service that handles TTS for multiple front‑ends—React, Flutter, or even a simple curl script.
Quick curl Demo
If you just want to test the endpoint without writing code:
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/EXAVITQu4vr4xnGd" \
-H "xi-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: audio/mpeg" \
-d '{"text":"Hello from ElevenLabs!", "voice_settings":{"stability":0.7}}' \
--output hello.mp3
Open hello.mp3 and you’ll hear the same voice that powered your React component.
Handling Rate Limits & Costs
ElevenLabs offers a generous free tier (up to 10 k characters per month). After that, pricing is pay‑as‑you‑go, and the API returns 429 Too Many Requests when you exceed your quota. A simple exponential back‑off or a client‑side queue can keep the UI smooth:
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
async function safeGenerate(text) {
let attempts = 0;
while (attempts < 5) {
try {
return await generateSpeech(text);
} catch (err) {
if (err.response?.status === 429) {
await delay(2 ** attempts * 500); // back‑off
attempts++;
} else {
throw err;
}
}
}
}
Wrapping Up
Building a voice‑enabled UI in React is surprisingly straightforward when you have a solid TTS backend. ElevenLabs provides:
- Natural‑sounding voices that rival commercial assistants.
- Voice cloning for brand consistency or personal flair.
- Simple REST API that works across any language or framework.
Give it a spin, experiment with different voice settings, and watch how quickly your app feels more alive.
Ready to add a human touch to your next project? Grab an API key and start generating speech right now: https://try.elevenlabs.io/kr07zfuqn1bp. Happy coding!
來源:DEV Community · dev.to