@scribeberry/sdk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/dist/index.js +3 -3
- package/dist/react.d.mts +120 -0
- package/dist/react.d.ts +120 -0
- package/dist/react.js +956 -0
- package/dist/react.mjs +919 -0
- package/package.json +34 -17
package/README.md
CHANGED
|
@@ -263,6 +263,66 @@ const result = await session.stop(); // Stop and get final result
|
|
|
263
263
|
|
|
264
264
|
---
|
|
265
265
|
|
|
266
|
+
## React Hooks
|
|
267
|
+
|
|
268
|
+
The SDK includes optional React bindings via `@scribeberry/sdk/react`. These
|
|
269
|
+
handle microphone access, audio processing, and WebSocket streaming with a
|
|
270
|
+
simple hook interface.
|
|
271
|
+
|
|
272
|
+
> **Peer dependency:** Requires `react >= 18`.
|
|
273
|
+
|
|
274
|
+
### `useTranscription(options)`
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
import { useTranscription } from '@scribeberry/sdk/react';
|
|
278
|
+
|
|
279
|
+
function Recorder() {
|
|
280
|
+
const {
|
|
281
|
+
status, // 'idle' | 'connecting' | 'recording' | 'error'
|
|
282
|
+
transcript, // Full confirmed transcript string
|
|
283
|
+
partial, // Interim text (updates rapidly, not yet confirmed)
|
|
284
|
+
segments, // All confirmed TranscriptSegment objects
|
|
285
|
+
error, // Error message or null
|
|
286
|
+
durationSeconds, // Session duration (available after stop)
|
|
287
|
+
start, // Start recording from microphone
|
|
288
|
+
stop, // Stop recording
|
|
289
|
+
clear, // Clear transcript and reset to idle
|
|
290
|
+
} = useTranscription({
|
|
291
|
+
getRealtimeToken: async () => {
|
|
292
|
+
const res = await fetch('/api/realtime-token', { method: 'POST' });
|
|
293
|
+
return res.json(); // { token, expiresAt }
|
|
294
|
+
},
|
|
295
|
+
language: 'en-US', // optional, default: 'en-US'
|
|
296
|
+
enableDiarization: true, // optional, default: true
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
return (
|
|
300
|
+
<div>
|
|
301
|
+
<button onClick={status === 'recording' ? stop : start}>
|
|
302
|
+
{status === 'recording' ? '⏹ Stop' : '🎙 Record'}
|
|
303
|
+
</button>
|
|
304
|
+
<p>
|
|
305
|
+
{transcript}
|
|
306
|
+
<span style={{ opacity: 0.5 }}>{partial}</span>
|
|
307
|
+
</p>
|
|
308
|
+
{transcript && <button onClick={clear}>Clear</button>}
|
|
309
|
+
</div>
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
| Option | Type | Required | Description |
|
|
315
|
+
| ------------------- | ---------- | -------- | ------------------------------------------------------------ |
|
|
316
|
+
| `getRealtimeToken` | `function` | ✅ | Async callback returning `{ token, expiresAt }` from your server |
|
|
317
|
+
| `language` | `string` | | Language code (default: `en-US`) |
|
|
318
|
+
| `enableDiarization` | `boolean` | | Speaker identification (default: `true`) |
|
|
319
|
+
|
|
320
|
+
The hook manages the full lifecycle: microphone permissions → AudioWorklet
|
|
321
|
+
processing → WebSocket streaming → React state updates. Your API key never
|
|
322
|
+
leaves the server — only short-lived `sb_rt_*` tokens are used in the browser.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
266
326
|
## Audio Format Requirements
|
|
267
327
|
|
|
268
328
|
For realtime transcription, audio must be:
|
package/dist/index.js
CHANGED
|
@@ -28,15 +28,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
33
|
AuthenticationError: () => AuthenticationError,
|
|
34
34
|
RateLimitError: () => RateLimitError,
|
|
35
35
|
RealtimeTranscriptionSession: () => RealtimeTranscriptionSession,
|
|
36
36
|
Scribeberry: () => Scribeberry,
|
|
37
37
|
ScribeberryError: () => ScribeberryError
|
|
38
38
|
});
|
|
39
|
-
module.exports = __toCommonJS(
|
|
39
|
+
module.exports = __toCommonJS(src_exports);
|
|
40
40
|
|
|
41
41
|
// src/lib/errors.ts
|
|
42
42
|
var ScribeberryError = class extends Error {
|
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A confirmed transcript segment from the realtime stream.
|
|
3
|
+
*/
|
|
4
|
+
interface TranscriptSegment {
|
|
5
|
+
/** Confirmed text content. */
|
|
6
|
+
text: string;
|
|
7
|
+
/** Speaker identifier (if diarization is enabled). */
|
|
8
|
+
speaker?: number;
|
|
9
|
+
/** Segment start time in milliseconds from session start. */
|
|
10
|
+
startMs: number;
|
|
11
|
+
/** Segment end time in milliseconds from session start. */
|
|
12
|
+
endMs: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Result from a `getRealtimeToken` callback.
|
|
17
|
+
*/
|
|
18
|
+
interface RealtimeTokenResult {
|
|
19
|
+
/** Temporary token prefixed with `sb_rt_`. */
|
|
20
|
+
token: string;
|
|
21
|
+
/** ISO 8601 expiration timestamp. */
|
|
22
|
+
expiresAt: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Status of the transcription session. */
|
|
26
|
+
type TranscriptionStatus = 'idle' | 'connecting' | 'recording' | 'error';
|
|
27
|
+
/** Configuration for `useTranscription`. */
|
|
28
|
+
interface UseTranscriptionOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Async callback that returns a temporary realtime token from your server.
|
|
31
|
+
*
|
|
32
|
+
* This is called each time `start()` is invoked. Your server should call
|
|
33
|
+
* `sb.realtime.createToken()` with a full API key and return the result.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* useTranscription({
|
|
38
|
+
* getRealtimeToken: async () => {
|
|
39
|
+
* const res = await fetch('/api/realtime-token', { method: 'POST' });
|
|
40
|
+
* return res.json(); // { token, expiresAt }
|
|
41
|
+
* },
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
getRealtimeToken: () => Promise<RealtimeTokenResult>;
|
|
46
|
+
/** Source language for transcription. Default: `'en-US'`. */
|
|
47
|
+
language?: string;
|
|
48
|
+
/** Enable speaker diarization. Default: `true`. */
|
|
49
|
+
enableDiarization?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/** State returned by the `useTranscription` hook. */
|
|
52
|
+
interface TranscriptionState {
|
|
53
|
+
/** Current lifecycle status. */
|
|
54
|
+
status: TranscriptionStatus;
|
|
55
|
+
/** All confirmed transcript segments (stable text). */
|
|
56
|
+
segments: TranscriptSegment[];
|
|
57
|
+
/** Interim text that updates rapidly as words are recognized. */
|
|
58
|
+
partial: string;
|
|
59
|
+
/** Full confirmed transcript as a single string. */
|
|
60
|
+
transcript: string;
|
|
61
|
+
/** Session duration in seconds (available after stop). */
|
|
62
|
+
durationSeconds: number | null;
|
|
63
|
+
/** Error message if something went wrong, otherwise `null`. */
|
|
64
|
+
error: string | null;
|
|
65
|
+
}
|
|
66
|
+
/** Actions returned by the `useTranscription` hook. */
|
|
67
|
+
interface TranscriptionActions {
|
|
68
|
+
/** Request microphone access and start transcribing. */
|
|
69
|
+
start: () => Promise<void>;
|
|
70
|
+
/** Stop the session and release the microphone. */
|
|
71
|
+
stop: () => Promise<void>;
|
|
72
|
+
/** Clear all state and return to idle. */
|
|
73
|
+
clear: () => void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* React hook for realtime medical transcription.
|
|
77
|
+
*
|
|
78
|
+
* Manages the full lifecycle: microphone access → AudioWorklet processing →
|
|
79
|
+
* WebSocket streaming → transcript state. Your API key never leaves the
|
|
80
|
+
* server — the hook uses a token callback to obtain short-lived credentials.
|
|
81
|
+
*
|
|
82
|
+
* @param options - Configuration including the required `getRealtimeToken` callback.
|
|
83
|
+
* @returns Transcription state and actions (`start`, `stop`, `clear`).
|
|
84
|
+
*
|
|
85
|
+
* @example Basic usage
|
|
86
|
+
* ```tsx
|
|
87
|
+
* import { useTranscription } from '@scribeberry/sdk/react';
|
|
88
|
+
*
|
|
89
|
+
* function Recorder() {
|
|
90
|
+
* const { status, transcript, partial, start, stop, clear } = useTranscription({
|
|
91
|
+
* getRealtimeToken: async () => {
|
|
92
|
+
* const res = await fetch('/api/realtime-token', { method: 'POST' });
|
|
93
|
+
* return res.json();
|
|
94
|
+
* },
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* return (
|
|
98
|
+
* <div>
|
|
99
|
+
* <button onClick={status === 'recording' ? stop : start}>
|
|
100
|
+
* {status === 'recording' ? 'Stop' : 'Record'}
|
|
101
|
+
* </button>
|
|
102
|
+
* <p>{transcript}<span style={{ opacity: 0.5 }}>{partial}</span></p>
|
|
103
|
+
* {transcript && <button onClick={clear}>Clear</button>}
|
|
104
|
+
* </div>
|
|
105
|
+
* );
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example With language and diarization options
|
|
110
|
+
* ```tsx
|
|
111
|
+
* const transcription = useTranscription({
|
|
112
|
+
* getRealtimeToken: fetchToken,
|
|
113
|
+
* language: 'fr-FR',
|
|
114
|
+
* enableDiarization: false,
|
|
115
|
+
* });
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function useTranscription(options: UseTranscriptionOptions): TranscriptionState & TranscriptionActions;
|
|
119
|
+
|
|
120
|
+
export { type TranscriptionActions, type TranscriptionState, type TranscriptionStatus, type UseTranscriptionOptions, useTranscription };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A confirmed transcript segment from the realtime stream.
|
|
3
|
+
*/
|
|
4
|
+
interface TranscriptSegment {
|
|
5
|
+
/** Confirmed text content. */
|
|
6
|
+
text: string;
|
|
7
|
+
/** Speaker identifier (if diarization is enabled). */
|
|
8
|
+
speaker?: number;
|
|
9
|
+
/** Segment start time in milliseconds from session start. */
|
|
10
|
+
startMs: number;
|
|
11
|
+
/** Segment end time in milliseconds from session start. */
|
|
12
|
+
endMs: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Result from a `getRealtimeToken` callback.
|
|
17
|
+
*/
|
|
18
|
+
interface RealtimeTokenResult {
|
|
19
|
+
/** Temporary token prefixed with `sb_rt_`. */
|
|
20
|
+
token: string;
|
|
21
|
+
/** ISO 8601 expiration timestamp. */
|
|
22
|
+
expiresAt: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Status of the transcription session. */
|
|
26
|
+
type TranscriptionStatus = 'idle' | 'connecting' | 'recording' | 'error';
|
|
27
|
+
/** Configuration for `useTranscription`. */
|
|
28
|
+
interface UseTranscriptionOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Async callback that returns a temporary realtime token from your server.
|
|
31
|
+
*
|
|
32
|
+
* This is called each time `start()` is invoked. Your server should call
|
|
33
|
+
* `sb.realtime.createToken()` with a full API key and return the result.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* useTranscription({
|
|
38
|
+
* getRealtimeToken: async () => {
|
|
39
|
+
* const res = await fetch('/api/realtime-token', { method: 'POST' });
|
|
40
|
+
* return res.json(); // { token, expiresAt }
|
|
41
|
+
* },
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
getRealtimeToken: () => Promise<RealtimeTokenResult>;
|
|
46
|
+
/** Source language for transcription. Default: `'en-US'`. */
|
|
47
|
+
language?: string;
|
|
48
|
+
/** Enable speaker diarization. Default: `true`. */
|
|
49
|
+
enableDiarization?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/** State returned by the `useTranscription` hook. */
|
|
52
|
+
interface TranscriptionState {
|
|
53
|
+
/** Current lifecycle status. */
|
|
54
|
+
status: TranscriptionStatus;
|
|
55
|
+
/** All confirmed transcript segments (stable text). */
|
|
56
|
+
segments: TranscriptSegment[];
|
|
57
|
+
/** Interim text that updates rapidly as words are recognized. */
|
|
58
|
+
partial: string;
|
|
59
|
+
/** Full confirmed transcript as a single string. */
|
|
60
|
+
transcript: string;
|
|
61
|
+
/** Session duration in seconds (available after stop). */
|
|
62
|
+
durationSeconds: number | null;
|
|
63
|
+
/** Error message if something went wrong, otherwise `null`. */
|
|
64
|
+
error: string | null;
|
|
65
|
+
}
|
|
66
|
+
/** Actions returned by the `useTranscription` hook. */
|
|
67
|
+
interface TranscriptionActions {
|
|
68
|
+
/** Request microphone access and start transcribing. */
|
|
69
|
+
start: () => Promise<void>;
|
|
70
|
+
/** Stop the session and release the microphone. */
|
|
71
|
+
stop: () => Promise<void>;
|
|
72
|
+
/** Clear all state and return to idle. */
|
|
73
|
+
clear: () => void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* React hook for realtime medical transcription.
|
|
77
|
+
*
|
|
78
|
+
* Manages the full lifecycle: microphone access → AudioWorklet processing →
|
|
79
|
+
* WebSocket streaming → transcript state. Your API key never leaves the
|
|
80
|
+
* server — the hook uses a token callback to obtain short-lived credentials.
|
|
81
|
+
*
|
|
82
|
+
* @param options - Configuration including the required `getRealtimeToken` callback.
|
|
83
|
+
* @returns Transcription state and actions (`start`, `stop`, `clear`).
|
|
84
|
+
*
|
|
85
|
+
* @example Basic usage
|
|
86
|
+
* ```tsx
|
|
87
|
+
* import { useTranscription } from '@scribeberry/sdk/react';
|
|
88
|
+
*
|
|
89
|
+
* function Recorder() {
|
|
90
|
+
* const { status, transcript, partial, start, stop, clear } = useTranscription({
|
|
91
|
+
* getRealtimeToken: async () => {
|
|
92
|
+
* const res = await fetch('/api/realtime-token', { method: 'POST' });
|
|
93
|
+
* return res.json();
|
|
94
|
+
* },
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* return (
|
|
98
|
+
* <div>
|
|
99
|
+
* <button onClick={status === 'recording' ? stop : start}>
|
|
100
|
+
* {status === 'recording' ? 'Stop' : 'Record'}
|
|
101
|
+
* </button>
|
|
102
|
+
* <p>{transcript}<span style={{ opacity: 0.5 }}>{partial}</span></p>
|
|
103
|
+
* {transcript && <button onClick={clear}>Clear</button>}
|
|
104
|
+
* </div>
|
|
105
|
+
* );
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example With language and diarization options
|
|
110
|
+
* ```tsx
|
|
111
|
+
* const transcription = useTranscription({
|
|
112
|
+
* getRealtimeToken: fetchToken,
|
|
113
|
+
* language: 'fr-FR',
|
|
114
|
+
* enableDiarization: false,
|
|
115
|
+
* });
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function useTranscription(options: UseTranscriptionOptions): TranscriptionState & TranscriptionActions;
|
|
119
|
+
|
|
120
|
+
export { type TranscriptionActions, type TranscriptionState, type TranscriptionStatus, type UseTranscriptionOptions, useTranscription };
|