Przejdź do nawigacji

SDK React

useScribe: transkrypcja mowy na tekst w czasie rzeczywistym w React

Przegląd Scribe i jego możliwości znajdziesz w opisie Speech to Text overview. Instrukcje użycia krok po kroku znajdziesz w Client-side streaming.

Instalacja

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

Użyj umiejętności ElevenLabs speech-to-text, aby transkrybować audio z pomocą asystenta AI do kodowania:

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

@elevenlabs/react ponownie eksportuje wszystko z @elevenlabs/client, więc nie musisz instalować obu pakietów.

Użycie

Oto minimalny działający przykład, który łączy się z Scribe i wyświetla transkrypcję w czasie rzeczywistym:

import { useScribe } from "@elevenlabs/react";
import { useEffect } from "react";
function MyComponent() {
const scribe = useScribe({
modelId: "scribe_v3_live",
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>
);
}

Pobieranie tokenu

Scribe wymaga jednorazowego tokenu do uwierzytelniania. Utwórz endpoint API na serwerze:

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

Twój klucz API ElevenLabs jest poufny. Nigdy nie udostępniaj go klientowi. Zawsze generuj token na serwerze.

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

Opcje hooka

Skonfiguruj hook za pomocą domyślnych opcji i callbacków:

const scribe = useScribe({
// Connection options (can be overridden in connect())
token: "optional-default-token",
modelId: "scribe_v3_live",
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"),
});

Opcje połączenia

WłaściwośćTypOpis
tokenstringJednorazowy token do uwierzytelniania WebSocket.
modelIdstringID modelu (np. "scribe_v3_live").
baseUristringNiestandardowy bazowy URI WebSocket. Domyślnie: wss://api.elevenlabs.io.

Opcje VAD

Te opcje określają, kiedy transkrypcje są automatycznie zatwierdzane przy strategii zatwierdzania VAD.

WłaściwośćTypDomyślnieOpis
commitStrategyCommitStrategy"manual""manual" lub "vad".
vadSilenceThresholdSecsnumber1.5Sekundy ciszy przed zatwierdzeniem przez VAD (0.3–3.0).
vadThresholdnumber0.4Czułość VAD (0.1–0.9, niższa wartość oznacza większą czułość).
minSpeechDurationMsnumber100Minimalny czas mowy w ms (50–2000).
minSilenceDurationMsnumber100Minimalny czas ciszy w ms (50–2000).

Opcje audio

WłaściwośćTypOpis
languageCodestringKod języka ISO-639-1 lub ISO-639-3. Pozostaw puste, aby wykrywać automatycznie.
microphoneobjectUstawienia mikrofonu dla trybu mikrofonowego. Zobacz niżej.
audioFormatAudioFormatFormat kodowania audio dla trybu ręcznego (np. AudioFormat.PCM_16000).
sampleRatenumberCzęstotliwość próbkowania dla trybu ręcznego. Musi pasować do audioFormat.

Obiekt microphone przyjmuje:

WłaściwośćTypOpis
deviceIdstringID konkretnego urządzenia mikrofonowego.
echoCancellationbooleanWłącza eliminację echa.
noiseSuppressionbooleanWłącza redukcję szumów.
autoGainControlbooleanWłącza automatyczną kontrolę wzmocnienia.

Opcje działania

WłaściwośćTypDomyślnieOpis
autoConnectbooleanfalseAutomatycznie łączy po zamontowaniu komponentu.
includeTimestampsbooleanfalseOtrzymuje znaczniki czasu na poziomie słów. Włączane automatycznie po podaniu onCommittedTranscriptWithTimestamps.

Callbacki

Wszystkie callbacki zdarzeń są opcjonalne i możesz podać je jako opcje hooka:

  • onConnect - obsługa wywoływana po nawiązaniu połączenia WebSocket.
  • onDisconnect - obsługa wywoływana po zamknięciu połączenia WebSocket.
  • onSessionStarted - obsługa wywoływana po rozpoczęciu sesji Scribe.
  • onPartialTranscript - obsługa wywoływana z tymczasowymi wynikami transkrypcji. Otrzymuje { text: string }.
  • onCommittedTranscript - obsługa wywoływana z zatwierdzonymi wynikami transkrypcji. Otrzymuje { text: string }.
  • onCommittedTranscriptWithTimestamps - obsługa wywoływana z zatwierdzonymi wynikami transkrypcji, w tym czasem na poziomie słów. Otrzymuje { text: string; words?: { start: number; end: number }[] }.
  • onError - ogólna obsługa wszystkich błędów. Otrzymuje Error | Event.
  • onAuthError - obsługa wywoływana przy błędach uwierzytelniania. Otrzymuje { error: string }.

Callbacki błędów

Ogólny callback onError uruchamia się przy wszystkich błędach. Dostępne są też konkretne callbacki błędów do bardziej szczegółowej obsługi. Wszystkie otrzymują { error: string }.

CallbackOpis
onErrorOgólna obsługa wszystkich błędów.
onAuthErrorBłąd uwierzytelniania.
onQuotaExceededErrorPrzekroczono limit użycia.
onCommitThrottledErrorŻądanie zatwierdzenia zostało ograniczone.
onTranscriberErrorBłąd silnika transkrypcji.
onUnacceptedTermsErrorWarunki usługi nie zostały zaakceptowane.
onRateLimitedErrorPrzekroczono limit żądań.
onInputErrorNieprawidłowy format danych wejściowych.
onQueueOverflowErrorKolejka przetwarzania jest pełna.
onResourceExhaustedErrorZasoby serwera są wyczerpane.
onSessionTimeLimitExceededErrorOsiągnięto maksymalny czas sesji.
onChunkSizeExceededErrorFragment audio jest za duży.
onInsufficientAudioActivityErrorZa mała aktywność audio, aby utrzymać połączenie.

Tryb mikrofonowy

Przesyłaj audio bezpośrednio z mikrofonu użytkownika:

function MicrophoneTranscription() {
const scribe = useScribe({
modelId: "scribe_v3_live",
});
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>
);
}

Ręczny tryb audio (transkrypcja plików)

Transkrybuj wcześniej nagrane pliki audio:

import { useScribe, AudioFormat } from "@elevenlabs/react";
import { useState } from "react";
function FileTranscription() {
const [file, setFile] = useState<File | null>(null);
const scribe = useScribe({
modelId: "scribe_v3_live",
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>
);
}

Zwracane wartości

Stan

  • status - bieżący stan połączenia: "disconnected", "connecting", "connected", "transcribing" lub "error".
  • isConnected - wartość logiczna wskazująca, czy połączono.
  • isTranscribing - wartość logiczna wskazująca, czy transkrypcja jest aktywna.
  • partialTranscript - bieżący częściowy (tymczasowy) ciąg transkrypcji.
  • committedTranscripts - tablica obiektów TranscriptSegment (zobacz niżej).
  • error - bieżący komunikat błędu lub 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

Każdy zatwierdzony segment transkrypcji ma następującą strukturę:

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

Metody

connect(options?)

Połącz z Scribe. Opcje podane tutaj zastępują domyślne opcje hooka:

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

disconnect()

Rozłącz i zwolnij zasoby:

scribe.disconnect();

sendAudio(audioBase64, options?)

Wyślij dane audio (tylko tryb ręczny):

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

Pole previousText można wysłać tylko w pierwszym fragmencie audio sesji. Wysłanie go w kolejnych fragmentach powoduje błąd.

commit()

Ręcznie zatwierdź bieżącą transkrypcję:

scribe.commit();

clearTranscripts()

Usuń wszystkie transkrypcje ze stanu:

scribe.clearTranscripts();

getConnection()

Pobierz bazową instancję połączenia:

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

Strategie zatwierdzania

Określ, kiedy transkrypcje są zatwierdzane:

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

Więcej informacji znajdziesz w Transcripts and commit strategies.

Pełny przykład

Oto pełny przykład komponentu React, który używa hooka useScribe ze strategią zatwierdzania opartą na VAD:

import { useScribe, CommitStrategy } from "@elevenlabs/react";
import { useEffect } from "react";
function ScribeDemo() {
const scribe = useScribe({
modelId: "scribe_v3_live",
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>
);
}