React SDK

useScribe: Speech-to-Text-Transkription in Echtzeit mit React

Einen Überblick über Scribe und seine Funktionen finden Sie in der Speech-to-Text- Übersicht. Schritt-für-Schritt-Anleitungen finden Sie unter Clientseitiges Streaming.

Installation

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

Verwenden Sie den ElevenLabs-Speech-to-Text-Skill, um Audio mit Ihrem KI-Coding-Assistenten zu transkribieren:

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

@elevenlabs/react exportiert alles aus @elevenlabs/client erneut. Sie müssen daher nicht beide Pakete installieren.

Verwendung

Hier ist ein minimales funktionierendes Beispiel, das sich mit Scribe verbindet und die Echtzeittranskription anzeigt:

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>
);
}

Token abrufen

Scribe benötigt zur Authentifizierung einen Einmal-Token. Erstellen Sie einen API-Endpunkt auf Ihrem 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 });
});

Ihr ElevenLabs-API-Schlüssel ist vertraulich. Geben Sie ihn niemals an den Client weiter. Generieren Sie den Token immer auf dem Server.

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

Hook-Optionen

Konfigurieren Sie den Hook mit Standardoptionen und 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"),
});

Verbindungsoptionen

EigenschaftTypBeschreibung
tokenstringEinmal-Token für die WebSocket-Authentifizierung.
modelIdstringModell-ID (z. B. "scribe_v2_realtime").
baseUristringBenutzerdefinierte WebSocket-Basis-URI. Standard: wss://api.elevenlabs.io.

VAD-Optionen

Diese Optionen steuern, wann Transkripte bei Verwendung der VAD-Commit-Strategie automatisch übernommen werden.

EigenschaftTypStandardBeschreibung
commitStrategyCommitStrategy"manual""manual" oder "vad".
vadSilenceThresholdSecsnumber1.5Sekunden Stille, bevor VAD übernimmt (0.3–3.0).
vadThresholdnumber0.4VAD-Empfindlichkeit (0.1–0.9, niedriger ist empfindlicher).
minSpeechDurationMsnumber100Mindestsprachdauer in ms (50–2000).
minSilenceDurationMsnumber100Mindestdauer der Stille in ms (50–2000).

Audiooptionen

EigenschaftTypBeschreibung
languageCodestringISO-639-1- oder ISO-639-3-Sprachcode. Für automatische Erkennung leer lassen.
microphoneobjectMikrofoneinstellungen für den Mikrofonmodus. Siehe unten.
audioFormatAudioFormatAudiocodierungsformat für den manuellen Modus (z. B. AudioFormat.PCM_16000).
sampleRatenumberAbtastrate für den manuellen Modus. Muss mit audioFormat übereinstimmen.

Das Objekt microphone akzeptiert:

EigenschaftTypBeschreibung
deviceIdstringID eines bestimmten Mikrofongeräts.
echoCancellationbooleanEchounterdrückung aktivieren.
noiseSuppressionbooleanRauschunterdrückung aktivieren.
autoGainControlbooleanAutomatische Verstärkungsregelung aktivieren.

Verhaltensoptionen

EigenschaftTypStandardBeschreibung
autoConnectbooleanfalseBeim Einhängen der Komponente automatisch verbinden.
includeTimestampsbooleanfalseZeitstempel auf Wortebene empfangen. Wird automatisch aktiviert, wenn onCommittedTranscriptWithTimestamps bereitgestellt wird.

Callbacks

Alle Event-Callbacks sind optional und können als Hook-Optionen bereitgestellt werden:

  • onConnect – Handler, der aufgerufen wird, wenn die WebSocket-Verbindung hergestellt ist.
  • onDisconnect – Handler, der aufgerufen wird, wenn die WebSocket-Verbindung geschlossen wird.
  • onSessionStarted – Handler, der aufgerufen wird, wenn die Scribe-Sitzung startet.
  • onPartialTranscript – Handler, der mit vorläufigen Transkriptionsergebnissen aufgerufen wird. Empfängt { text: string }.
  • onCommittedTranscript – Handler, der mit finalisierten Transkriptionsergebnissen aufgerufen wird. Empfängt { text: string }.
  • onCommittedTranscriptWithTimestamps – Handler, der mit finalisierten Transkriptionsergebnissen einschließlich Zeitangaben auf Wortebene aufgerufen wird. Empfängt { text: string; words?: { start: number; end: number }[] }.
  • onError – Allgemeiner Fehler-Handler für alle Fehler. Empfängt Error | Event.
  • onAuthError – Handler, der bei Authentifizierungsfehlern aufgerufen wird. Empfängt { error: string }.

Fehler-Callbacks

Der allgemeine Callback onError wird bei allen Fehlern ausgelöst. Für eine detaillierte Behandlung sind auch spezifische Fehler-Callbacks verfügbar. Alle spezifischen Fehler-Callbacks empfangen { error: string }.

CallbackBeschreibung
onErrorAllgemeiner Fehler-Handler für alle Fehler.
onAuthErrorAuthentifizierungsfehler.
onQuotaExceededErrorNutzungskontingent überschritten.
onCommitThrottledErrorCommit-Anfrage gedrosselt.
onTranscriberErrorFehler der Transkriptions-Engine.
onUnacceptedTermsErrorNutzungsbedingungen nicht akzeptiert.
onRateLimitedErrorRatenlimit erreicht.
onInputErrorUngültiges Eingabeformat.
onQueueOverflowErrorVerarbeitungswarteschlange voll.
onResourceExhaustedErrorServerressourcen ausgelastet.
onSessionTimeLimitExceededErrorMaximale Sitzungsdauer erreicht.
onChunkSizeExceededErrorAudio-Chunk zu groß.
onInsufficientAudioActivityErrorNicht genug Audioaktivität, um die Verbindung aufrechtzuerhalten.

Mikrofonmodus

Streamen Sie Audio direkt vom Mikrofon des Nutzers:

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>
);
}

Manueller Audiomodus (Dateitranskription)

Transkribieren Sie vorab aufgezeichnete Audiodateien:

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>
);
}

Rückgabewerte

Status

  • status – aktueller Verbindungsstatus: "disconnected", "connecting", "connected", "transcribing" oder "error".
  • isConnected – Boolescher Wert, der angibt, ob eine Verbindung besteht.
  • isTranscribing – Boolescher Wert, der angibt, ob aktiv transkribiert wird.
  • partialTranscript – aktuelle teilweise (vorläufige) Transkriptzeichenfolge.
  • committedTranscripts – Array von TranscriptSegment-Objekten (siehe unten).
  • error – aktuelle Fehlermeldung oder 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

Jedes übernommene Transkriptsegment hat die folgende Struktur:

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

Methoden

connect(options?)

Mit Scribe verbinden. Hier angegebene Optionen überschreiben die Hook-Standardwerte:

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

disconnect()

Verbindung trennen und Ressourcen bereinigen:

scribe.disconnect();

sendAudio(audioBase64, options?)

Audiodaten senden (nur manueller 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.
});

Das Feld previousText kann nur im ersten Audio-Chunk einer Sitzung gesendet werden. Das Senden in nachfolgenden Chunks führt zu einem Fehler.

commit()

Aktuelle Transkription manuell übernehmen:

scribe.commit();

clearTranscripts()

Alle Transkripte aus dem Status löschen:

scribe.clearTranscripts();

getConnection()

Zugrunde liegende Verbindungsinstanz abrufen:

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

Commit-Strategien

Steuern Sie, wann Transkriptionen übernommen werden:

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,
});

Weitere Details finden Sie unter Transkripte und Commit-Strategien.

Vollständiges Beispiel

Hier ist ein vollständiges Beispiel einer React-Komponente, die den useScribe-Hook mit VAD-basierter Commit-Strategie verwendet:

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>
);
}