Skip to navigation

React SDK

useScribe: realtime spraak-naar-teksttranscriptie in React

Voor een overzicht van Scribe en de mogelijkheden ervan, zie het overzicht van Speech to Text . Zie streaming aan clientzijde voor stapsgewijze handleidingen.

Installatie

npm install @elevenlabs/react
# or
yarn add @elevenlabs/react
# or
pnpm install @elevenlabs/react

Gebruik de ElevenLabs Speech to Text-skill om audio te transcriberen met je AI-codingassistent:

npx skills add elevenlabs/skills --skill speech-to-text

@elevenlabs/react exporteert alles opnieuw vanuit @elevenlabs/client, dus je hoeft niet beide pakketten te installeren.

Gebruik

Hier is een minimaal werkend voorbeeld dat verbinding maakt met Scribe en realtime transcriptie weergeeft:

import { useScribe } from "@elevenlabs/react";
import { useEffect } from "react";
function MyComponent() {
const scribe = useScribe({
modelId: "scribe_v2_realtime",
onPartialTranscript: (data) => {
console.log("Partial:", data.text);
},
onCommittedTranscript: (data) => {
console.log("Committed:", data.text);
},
});
// Start recording
const handleStart = async () => {
try {
const token = await fetchTokenFromServer();
await scribe.connect({
token,
microphone: {
echoCancellation: true,
noiseSuppression: true,
},
});
} catch (err) {
console.error("Failed to start recording:", err);
}
};
// Stop recording
const handleDisconnect = () => {
scribe.disconnect();
};
// Disconnect on unmount
useEffect(() => {
return () => {
if (scribe.isConnected) {
scribe.disconnect();
}
};
}, [scribe]);
return (
<div>
<button onClick={handleStart} disabled={scribe.isConnected}>
Start Recording
</button>
<button onClick={handleDisconnect} disabled={!scribe.isConnected}>
Stop
</button>
{scribe.partialTranscript && <p>Live: {scribe.partialTranscript}</p>}
<div>
{scribe.committedTranscripts.map((t) => (
<p key={t.id}>{t.text}</p>
))}
</div>
</div>
);
}

Een token ophalen

Scribe vereist een token voor eenmalig gebruik voor authenticatie. Maak een API-endpoint op je server:

// Node.js server
app.get("/scribe-token", yourAuthMiddleware, async (req, res) => {
const response = await fetch("https://api.elevenlabs.io/v1/single-use-token/realtime_scribe", {
method: "POST",
headers: {
"xi-api-key": process.env.ELEVENLABS_API_KEY,
},
});
const data = await response.json();
res.json({ token: data.token });
});

Je ElevenLabs API-sleutel is gevoelig. Stel deze nooit bloot aan de client. Genereer het token altijd op de server.

// Client
const fetchToken = async () => {
const response = await fetch("/scribe-token");
const { token } = await response.json();
return token;
};

Hookopties

Configureer de hook met standaardopties en callbacks:

const scribe = useScribe({
// Connection options (can be overridden in connect())
token: "optional-default-token",
modelId: "scribe_v2_realtime",
baseUri: "wss://api.elevenlabs.io",
// VAD options
commitStrategy: CommitStrategy.VAD,
vadSilenceThresholdSecs: 0.5,
vadThreshold: 0.5,
minSpeechDurationMs: 100,
minSilenceDurationMs: 500,
languageCode: "en",
// Microphone options (for automatic mode)
microphone: {
deviceId: "optional-device-id",
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true,
},
// Manual audio options (for file transcription)
audioFormat: AudioFormat.PCM_16000,
sampleRate: 16000,
// Auto-connect on mount
autoConnect: false,
// Event callbacks
onSessionStarted: () => console.log("Session started"),
onPartialTranscript: (data) => console.log("Partial:", data.text),
onCommittedTranscript: (data) => console.log("Committed:", data.text),
onCommittedTranscriptWithTimestamps: (data) => console.log("With timestamps:", data),
onError: (error) => console.error("Error:", error),
onAuthError: (data) => console.error("Auth error:", data.error),
onQuotaExceededError: (data) => console.error("Quota exceeded:", data.error),
onConnect: () => console.log("Connected"),
onDisconnect: () => console.log("Disconnected"),
});

Verbindingsopties

EigenschapTypeBeschrijving
tokenstringToken voor eenmalig gebruik voor WebSocket-authenticatie.
modelIdstringModel-ID (bijv. "scribe_v2_realtime").
baseUristringAangepaste WebSocket-basis-URI. Standaard is wss://api.elevenlabs.io.

VAD-opties

Deze opties bepalen wanneer transcripten automatisch worden vastgelegd bij gebruik van de VAD-commitstrategie.

EigenschapTypeStandaardBeschrijving
commitStrategyCommitStrategy"manual""manual" of "vad".
vadSilenceThresholdSecsnumber1.5Seconden stilte voordat VAD vastlegt (0.3-3.0).
vadThresholdnumber0.4VAD-gevoeligheid (0.1-0.9, lager is gevoeliger).
minSpeechDurationMsnumber100Minimale spraakduur in ms (50-2000).
minSilenceDurationMsnumber100Minimale stilteduur in ms (50-2000).

Audio-opties

EigenschapTypeBeschrijving
languageCodestringISO-639-1- of ISO-639-3-taalcode. Laat leeg voor automatische detectie.
microphoneobjectMicrofooninstellingen voor de microfoonmodus. Zie hieronder.
audioFormatAudioFormatAudio-encoderingsindeling voor handmatige modus (bijv. AudioFormat.PCM_16000).
sampleRatenumberSamplefrequentie voor handmatige modus. Moet overeenkomen met audioFormat.

Het object microphone accepteert:

EigenschapTypeBeschrijving
deviceIdstringID van een specifiek microfoonapparaat.
echoCancellationbooleanSchakel echo-onderdrukking in.
noiseSuppressionbooleanSchakel ruisonderdrukking in.
autoGainControlbooleanSchakel automatische gainregeling in.

Gedragsopties

EigenschapTypeStandaardBeschrijving
autoConnectbooleanfalseMaak automatisch verbinding wanneer het component wordt gemount.
includeTimestampsbooleanfalseOntvang tijdstempels op woordniveau. Wordt automatisch ingeschakeld wanneer onCommittedTranscriptWithTimestamps is opgegeven.

Callbacks

Alle eventcallbacks zijn optioneel en kunnen als hookopties worden opgegeven:

  • onConnect - handler die wordt aangeroepen wanneer de WebSocket-verbinding tot stand is gebracht.
  • onDisconnect - handler die wordt aangeroepen wanneer de WebSocket-verbinding wordt gesloten.
  • onSessionStarted - handler die wordt aangeroepen wanneer de Scribe-sessie start.
  • onPartialTranscript - handler die wordt aangeroepen met tussentijdse transcriptieresultaten. Ontvangt { text: string }.
  • onCommittedTranscript - handler die wordt aangeroepen met definitieve transcriptieresultaten. Ontvangt { text: string }.
  • onCommittedTranscriptWithTimestamps - handler die wordt aangeroepen met definitieve transcriptieresultaten inclusief timing op woordniveau. Ontvangt { text: string; words?: { start: number; end: number }[] }.
  • onError - algemene errorhandler voor alle fouten. Ontvangt Error | Event.
  • onAuthError - handler die wordt aangeroepen bij authenticatiefouten. Ontvangt { error: string }.

Errorcallbacks

De algemene callback onError wordt geactiveerd voor alle fouten. Er zijn ook specifieke errorcallbacks beschikbaar voor gedetailleerde afhandeling. Alle specifieke errorcallbacks ontvangen { error: string }.

CallbackBeschrijving
onErrorAlgemene errorhandler voor alle fouten.
onAuthErrorAuthenticatiefout.
onQuotaExceededErrorGebruiksquotum overschreden.
onCommitThrottledErrorCommitrequest beperkt.
onTranscriberErrorFout in transcriptie-engine.
onUnacceptedTermsErrorServicevoorwaarden niet geaccepteerd.
onRateLimitedErrorRate limit bereikt.
onInputErrorOngeldige invoerindeling.
onQueueOverflowErrorVerwerkingswachtrij vol.
onResourceExhaustedErrorServerresources hebben hun capaciteit bereikt.
onSessionTimeLimitExceededErrorMaximale sessieduur bereikt.
onChunkSizeExceededErrorAudiochunk te groot.
onInsufficientAudioActivityErrorNiet genoeg audioactiviteit om de verbinding te behouden.

Microfoonmodus

Stream audio rechtstreeks vanaf de microfoon van de gebruiker:

function MicrophoneTranscription() {
const scribe = useScribe({
modelId: "scribe_v2_realtime",
});
const startRecording = async () => {
const token = await fetchToken();
await scribe.connect({
token,
microphone: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true,
},
});
};
return (
<div>
<button onClick={startRecording} disabled={scribe.isConnected}>
{scribe.status === "connecting" ? "Connecting..." : "Start"}
</button>
<button onClick={scribe.disconnect} disabled={!scribe.isConnected}>
Stop
</button>
{scribe.partialTranscript && (
<div>
<strong>Speaking:</strong> {scribe.partialTranscript}
</div>
)}
{scribe.committedTranscripts.map((transcript) => (
<div key={transcript.id}>{transcript.text}</div>
))}
</div>
);
}

Handmatige audiomodus (bestandstranscriptie)

Transcribeer vooraf opgenomen audiobestanden:

import { useScribe, AudioFormat } from "@elevenlabs/react";
import { useState } from "react";
function FileTranscription() {
const [file, setFile] = useState<File | null>(null);
const scribe = useScribe({
modelId: "scribe_v2_realtime",
audioFormat: AudioFormat.PCM_16000,
sampleRate: 16000,
});
const transcribeFile = async () => {
if (!file) return;
const token = await fetchToken();
await scribe.connect({ token });
// Decode audio file
const arrayBuffer = await file.arrayBuffer();
const audioContext = new AudioContext({ sampleRate: 16000 });
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
// Convert to PCM16
const channelData = audioBuffer.getChannelData(0);
const pcmData = new Int16Array(channelData.length);
for (let i = 0; i < channelData.length; i++) {
const sample = Math.max(-1, Math.min(1, channelData[i]));
pcmData[i] = sample < 0 ? sample * 32768 : sample * 32767;
}
// Send in chunks
const chunkSize = 4096;
for (let offset = 0; offset < pcmData.length; offset += chunkSize) {
const chunk = pcmData.slice(offset, offset + chunkSize);
const bytes = new Uint8Array(chunk.buffer);
const base64 = btoa(String.fromCharCode(...bytes));
scribe.sendAudio(base64);
await new Promise((resolve) => setTimeout(resolve, 50));
}
// Commit transcription
scribe.commit();
};
return (
<div>
<input type="file" accept="audio/*" onChange={(e) => setFile(e.target.files?.[0] || null)} />
<button onClick={transcribeFile} disabled={!file || scribe.isConnected}>
Transcribe
</button>
{scribe.committedTranscripts.map((transcript) => (
<div key={transcript.id}>{transcript.text}</div>
))}
</div>
);
}

Retourwaarden

Status

  • status - huidige verbindingsstatus: "disconnected", "connecting", "connected", "transcribing" of "error".
  • isConnected - boolean die aangeeft of er verbinding is.
  • isTranscribing - boolean die aangeeft of er actief wordt getranscribeerd.
  • partialTranscript - huidige gedeeltelijke (tussentijdse) transcripttekenreeks.
  • committedTranscripts - array met TranscriptSegment-objecten (zie hieronder).
  • error - huidige foutmelding, of null.
const scribe = useScribe(/* options */);
console.log(scribe.status); // "connected"
console.log(scribe.isConnected); // true
console.log(scribe.partialTranscript); // "hello world"
console.log(scribe.committedTranscripts); // [{ id: "...", text: "...", words: ..., isFinal: true }]
console.log(scribe.error); // null or error string

Elk vastgelegd transcriptsegment heeft de volgende structuur:

interface TranscriptSegment {
id: string; // Unique identifier
text: string; // Transcript text
timestamp: number; // Unix timestamp
isFinal: boolean; // Always true for committed transcripts
}

Methoden

connect(options?)

Maak verbinding met Scribe. Opties die je hier opgeeft, overschrijven de standaardinstellingen van de hook:

await scribe.connect({
token: "your-token", // Required
microphone: {
/* ... */
}, // For microphone mode
// OR
audioFormat: AudioFormat.PCM_16000, // For manual mode
sampleRate: 16000,
});

disconnect()

Verbreek de verbinding en ruim resources op:

scribe.disconnect();

sendAudio(audioBase64, options?)

Verstuur audiogegevens (alleen handmatige modus):

scribe.sendAudio(base64AudioChunk, {
commit: false, // Optional: commit immediately
sampleRate: 16000, // Optional: override sample rate
previousText: "Previous transcription text", // Optional: context from a previous transcription. Can only be sent in the first audio chunk.
});

Het veld previousText kan alleen in het eerste audiochunk van een sessie worden verstuurd. Als je het in volgende chunks verstuurt, ontstaat er een fout.

commit()

Leg de huidige transcriptie handmatig vast:

scribe.commit();

clearTranscripts()

Wis alle transcripten uit de status:

scribe.clearTranscripts();

getConnection()

Haal de onderliggende verbindingsinstantie op:

const connection = scribe.getConnection();
// Returns RealtimeConnection | null

Commitstrategieën

Bepaal wanneer transcripties worden vastgelegd:

import { CommitStrategy } from '@elevenlabs/react';
// Manual (default) - you control when to commit
const scribe = useScribe({
commitStrategy: CommitStrategy.MANUAL,
});
// Later...
scribe.commit(); // Commit transcription
// Voice Activity Detection - model detects silences and automatically commits
const scribe = useScribe({
commitStrategy: CommitStrategy.VAD,
});

Zie Transcripten en commitstrategieën voor meer informatie.

Volledig voorbeeld

Hier is een volledig voorbeeld van een React-component die de hook useScribe gebruikt met een op VAD gebaseerde commitstrategie:

import { useScribe, CommitStrategy } from "@elevenlabs/react";
import { useEffect } from "react";
function ScribeDemo() {
const scribe = useScribe({
modelId: "scribe_v2_realtime",
commitStrategy: CommitStrategy.VAD,
onSessionStarted: () => console.log("Started"),
onCommittedTranscript: (data) => console.log("Committed:", data.text),
onError: (error) => console.error("Error:", error),
});
const startMicrophone = async () => {
const token = await fetchToken();
await scribe.connect({
token,
microphone: {
echoCancellation: true,
noiseSuppression: true,
},
});
};
const handleDisconnect = () => scribe.disconnect();
const handleClearTranscripts = () => scribe.clearTranscripts();
useEffect(() => {
return () => {
handleDisconnect();
};
}, []);
return (
<div>
<h1>Scribe Demo</h1>
{/* Status */}
<div>
Status: {scribe.status}
{scribe.error && <span>Error: {scribe.error}</span>}
</div>
{/* Controls */}
<div>
{!scribe.isConnected ? (
<button onClick={startMicrophone}>Start Recording</button>
) : (
<button onClick={handleDisconnect}>Stop</button>
)}
<button onClick={handleClearTranscripts}>Clear</button>
</div>
{/* Live Transcript */}
{scribe.partialTranscript && (
<div>
<strong>Live:</strong> {scribe.partialTranscript}
</div>
)}
{/* Committed Transcripts */}
<div>
<h2>Transcripts ({scribe.committedTranscripts.length})</h2>
{scribe.committedTranscripts.map((t) => (
<div key={t.id}>
<span>{new Date(t.timestamp).toLocaleTimeString()}</span>
<p>{t.text}</p>
</div>
))}
</div>
</div>
);
}