@lalternative/tornade-sdk-react 0.1.0 → 0.1.1
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 +2 -2
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,5 +21,5 @@ function PlayButton({ messageId }: { messageId: string }) {
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
The server side is the Go `client` package of this module: `client.New` with
|
|
24
|
-
|
|
25
|
-
endpoint above returns.
|
|
24
|
+
the application's `Key` for `PrimeOpening`, and `signed.NewSigner` with the
|
|
25
|
+
same key for the URL the endpoint above returns.
|
package/dist/index.js
CHANGED
|
@@ -77,9 +77,31 @@ function useVoicePlayback(resolve) {
|
|
|
77
77
|
headers: { "Content-Type": "application/json" },
|
|
78
78
|
body: JSON.stringify(reading.body)
|
|
79
79
|
});
|
|
80
|
-
if (!res.ok || !res.body
|
|
80
|
+
if (!res.ok || !res.body) {
|
|
81
81
|
throw new Error(`unexpected response (${res.status})`);
|
|
82
82
|
}
|
|
83
|
+
const contentType = res.headers.get("Content-Type") ?? "";
|
|
84
|
+
if (contentType !== FRAMES_CONTENT_TYPE) {
|
|
85
|
+
if (!contentType.startsWith("audio/")) {
|
|
86
|
+
throw new Error(`unexpected response (${res.status}, ${contentType})`);
|
|
87
|
+
}
|
|
88
|
+
const whole = await res.arrayBuffer();
|
|
89
|
+
if (cancelled) return;
|
|
90
|
+
scheduled = 1;
|
|
91
|
+
const buffer = await audioContext.decodeAudioData(whole);
|
|
92
|
+
if (cancelled) return;
|
|
93
|
+
const source = audioContext.createBufferSource();
|
|
94
|
+
source.buffer = buffer;
|
|
95
|
+
source.connect(audioContext.destination);
|
|
96
|
+
source.start(audioContext.currentTime);
|
|
97
|
+
source.onended = () => {
|
|
98
|
+
sourcesDone += 1;
|
|
99
|
+
finishIfDone();
|
|
100
|
+
};
|
|
101
|
+
streamDone = true;
|
|
102
|
+
setState("playing");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
83
105
|
await readFrames(
|
|
84
106
|
res.body.getReader(),
|
|
85
107
|
(frame) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/frames.ts","../src/speak.ts","../src/useVoicePlayback.ts"],"sourcesContent":["/**\n * A streamed reading is a sequence of independently decodable mp3 pieces,\n * each length-prefixed in the response body: a big-endian uint32 byte count\n * followed by that many bytes. Mirrors go/audioreader's FramesContentType.\n */\nexport const FRAMES_CONTENT_TYPE = 'application/x-lalter-audio-frames'\n\n/**\n * Reads length-prefixed frames off a byte stream as they arrive, handing\n * each complete frame to onFrame as soon as it is fully buffered. A frame can\n * straddle several network chunks, or a chunk can hold several frames.\n */\nexport async function readFrames(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onFrame: (frame: Uint8Array) => void,\n signal: AbortSignal,\n): Promise<void> {\n let buffer = new Uint8Array(0)\n\n const append = (chunk: Uint8Array) => {\n const next = new Uint8Array(buffer.length + chunk.length)\n next.set(buffer)\n next.set(chunk, buffer.length)\n buffer = next\n }\n\n for (;;) {\n if (signal.aborted) return\n const { done, value } = await reader.read()\n if (value) append(value)\n if (done) return\n\n for (;;) {\n if (buffer.length < 4) break\n const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.length)\n const frameLength = view.getUint32(0)\n const total = 4 + frameLength\n if (buffer.length < total) break\n onFrame(buffer.subarray(4, total))\n buffer = buffer.subarray(total)\n }\n }\n}\n","/** Where a reading may be fetched, and what to ask for once there. */\nexport type VoiceSource = {\n url: string\n body: unknown\n}\n\n/** The reading an application's server signed a URL for. */\nexport type SignedReading = {\n /** The signed URL onto tornade's /speak, as handed out by the application. */\n url: string\n /** The exact text the signature covers: what the server read aloud, not the raw content. */\n text: string\n scope: string\n id: string\n}\n\n/**\n * Builds the request the browser sends tornade for a signed reading. Always\n * streamed: an opening the application primed is only served on the\n * streaming path, and only a stream starts playing before the end is read.\n */\nexport function speakSource(reading: SignedReading): VoiceSource {\n return {\n url: reading.url,\n body: { text: reading.text, scope: reading.scope, id: reading.id, stream: true },\n }\n}\n","import { useCallback, useRef, useState } from 'react'\nimport { FRAMES_CONTENT_TYPE, readFrames } from './frames'\nimport type { VoiceSource } from './speak'\n\nexport type VoicePlaybackState = 'idle' | 'loading' | 'playing' | 'unavailable'\n\n/**\n * Plays a reading aloud piece by piece as tornade streams it, so listening\n * starts on the first piece instead of after the whole synthesis.\n *\n * Decoded with Web Audio rather than MediaSource: mp3 in a SourceBuffer is\n * inconsistent across desktop browsers, and MediaSource is unavailable on\n * iOS Safari and in a Tauri webview, while decodeAudioData works everywhere.\n *\n * resolve is called on each press rather than once: the URL it returns is\n * signed and expires, so one resolved when the text was rendered would have\n * gone stale by the time someone presses play.\n */\nexport function useVoicePlayback(resolve: () => Promise<VoiceSource>) {\n const [state, setState] = useState<VoicePlaybackState>('idle')\n const contextRef = useRef<AudioContext | null>(null)\n const abortRef = useRef<AbortController | null>(null)\n const stopRef = useRef<(() => void) | null>(null)\n\n const stop = useCallback(() => {\n stopRef.current?.()\n stopRef.current = null\n abortRef.current?.abort()\n abortRef.current = null\n setState((s) => (s === 'unavailable' ? s : 'idle'))\n }, [])\n\n const play = useCallback(() => {\n setState('loading')\n const controller = new AbortController()\n abortRef.current = controller\n\n const audioContext = new AudioContext()\n contextRef.current = audioContext\n\n let cancelled = false\n let nextStartAt = 0\n let scheduled = 0\n let sourcesDone = 0\n let streamDone = false\n\n const finishIfDone = () => {\n if (streamDone && scheduled === sourcesDone) {\n setState((s) => (s === 'playing' ? 'idle' : s))\n }\n }\n\n stopRef.current = () => {\n cancelled = true\n audioContext.close().catch(() => {})\n }\n\n ;(async () => {\n try {\n const reading = await resolve()\n // No credentials: the audio comes from another origin, and what\n // authorises the request is the signature already in the URL.\n const res = await fetch(reading.url, {\n method: 'POST',\n signal: controller.signal,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(reading.body),\n })\n if (!res.ok || !res.body || res.headers.get('Content-Type') !== FRAMES_CONTENT_TYPE) {\n throw new Error(`unexpected response (${res.status})`)\n }\n\n await readFrames(\n res.body.getReader(),\n (frame) => {\n if (cancelled) return\n scheduled += 1\n // decodeAudioData detaches the buffer it is given, which would\n // corrupt later frames sharing the same backing ArrayBuffer.\n const bytes = frame.slice().buffer\n audioContext\n .decodeAudioData(bytes)\n .then((buffer) => {\n if (cancelled) return\n const source = audioContext.createBufferSource()\n source.buffer = buffer\n source.connect(audioContext.destination)\n const startAt = Math.max(nextStartAt, audioContext.currentTime)\n source.start(startAt)\n nextStartAt = startAt + buffer.duration\n source.onended = () => {\n sourcesDone += 1\n finishIfDone()\n }\n if (scheduled === 1) setState('playing')\n })\n .catch(() => {\n sourcesDone += 1\n finishIfDone()\n })\n },\n controller.signal,\n )\n streamDone = true\n finishIfDone()\n if (scheduled === 0) setState('unavailable')\n } catch {\n if (!cancelled) setState('unavailable')\n }\n })()\n }, [resolve])\n\n const toggle = useCallback(() => {\n if (state === 'playing' || state === 'loading') {\n stop()\n return\n }\n play()\n }, [state, play, stop])\n\n return { state, toggle, stop }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/frames.ts","../src/speak.ts","../src/useVoicePlayback.ts"],"sourcesContent":["/**\n * A streamed reading is a sequence of independently decodable mp3 pieces,\n * each length-prefixed in the response body: a big-endian uint32 byte count\n * followed by that many bytes. Mirrors go/audioreader's FramesContentType.\n */\nexport const FRAMES_CONTENT_TYPE = 'application/x-lalter-audio-frames'\n\n/**\n * Reads length-prefixed frames off a byte stream as they arrive, handing\n * each complete frame to onFrame as soon as it is fully buffered. A frame can\n * straddle several network chunks, or a chunk can hold several frames.\n */\nexport async function readFrames(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onFrame: (frame: Uint8Array) => void,\n signal: AbortSignal,\n): Promise<void> {\n let buffer = new Uint8Array(0)\n\n const append = (chunk: Uint8Array) => {\n const next = new Uint8Array(buffer.length + chunk.length)\n next.set(buffer)\n next.set(chunk, buffer.length)\n buffer = next\n }\n\n for (;;) {\n if (signal.aborted) return\n const { done, value } = await reader.read()\n if (value) append(value)\n if (done) return\n\n for (;;) {\n if (buffer.length < 4) break\n const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.length)\n const frameLength = view.getUint32(0)\n const total = 4 + frameLength\n if (buffer.length < total) break\n onFrame(buffer.subarray(4, total))\n buffer = buffer.subarray(total)\n }\n }\n}\n","/** Where a reading may be fetched, and what to ask for once there. */\nexport type VoiceSource = {\n url: string\n body: unknown\n}\n\n/** The reading an application's server signed a URL for. */\nexport type SignedReading = {\n /** The signed URL onto tornade's /speak, as handed out by the application. */\n url: string\n /** The exact text the signature covers: what the server read aloud, not the raw content. */\n text: string\n scope: string\n id: string\n}\n\n/**\n * Builds the request the browser sends tornade for a signed reading. Always\n * streamed: an opening the application primed is only served on the\n * streaming path, and only a stream starts playing before the end is read.\n */\nexport function speakSource(reading: SignedReading): VoiceSource {\n return {\n url: reading.url,\n body: { text: reading.text, scope: reading.scope, id: reading.id, stream: true },\n }\n}\n","import { useCallback, useRef, useState } from 'react'\nimport { FRAMES_CONTENT_TYPE, readFrames } from './frames'\nimport type { VoiceSource } from './speak'\n\nexport type VoicePlaybackState = 'idle' | 'loading' | 'playing' | 'unavailable'\n\n/**\n * Plays a reading aloud piece by piece as tornade streams it, so listening\n * starts on the first piece instead of after the whole synthesis.\n *\n * Decoded with Web Audio rather than MediaSource: mp3 in a SourceBuffer is\n * inconsistent across desktop browsers, and MediaSource is unavailable on\n * iOS Safari and in a Tauri webview, while decodeAudioData works everywhere.\n *\n * resolve is called on each press rather than once: the URL it returns is\n * signed and expires, so one resolved when the text was rendered would have\n * gone stale by the time someone presses play.\n */\nexport function useVoicePlayback(resolve: () => Promise<VoiceSource>) {\n const [state, setState] = useState<VoicePlaybackState>('idle')\n const contextRef = useRef<AudioContext | null>(null)\n const abortRef = useRef<AbortController | null>(null)\n const stopRef = useRef<(() => void) | null>(null)\n\n const stop = useCallback(() => {\n stopRef.current?.()\n stopRef.current = null\n abortRef.current?.abort()\n abortRef.current = null\n setState((s) => (s === 'unavailable' ? s : 'idle'))\n }, [])\n\n const play = useCallback(() => {\n setState('loading')\n const controller = new AbortController()\n abortRef.current = controller\n\n const audioContext = new AudioContext()\n contextRef.current = audioContext\n\n let cancelled = false\n let nextStartAt = 0\n let scheduled = 0\n let sourcesDone = 0\n let streamDone = false\n\n const finishIfDone = () => {\n if (streamDone && scheduled === sourcesDone) {\n setState((s) => (s === 'playing' ? 'idle' : s))\n }\n }\n\n stopRef.current = () => {\n cancelled = true\n audioContext.close().catch(() => {})\n }\n\n ;(async () => {\n try {\n const reading = await resolve()\n // No credentials: the audio comes from another origin, and what\n // authorises the request is the signature already in the URL.\n const res = await fetch(reading.url, {\n method: 'POST',\n signal: controller.signal,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(reading.body),\n })\n if (!res.ok || !res.body) {\n throw new Error(`unexpected response (${res.status})`)\n }\n const contentType = res.headers.get('Content-Type') ?? ''\n if (contentType !== FRAMES_CONTENT_TYPE) {\n // A reading tornade already keeps comes back whole, as one audio\n // file with a Content-Length, whatever the request asked for.\n if (!contentType.startsWith('audio/')) {\n throw new Error(`unexpected response (${res.status}, ${contentType})`)\n }\n const whole = await res.arrayBuffer()\n if (cancelled) return\n scheduled = 1\n const buffer = await audioContext.decodeAudioData(whole)\n if (cancelled) return\n const source = audioContext.createBufferSource()\n source.buffer = buffer\n source.connect(audioContext.destination)\n source.start(audioContext.currentTime)\n source.onended = () => {\n sourcesDone += 1\n finishIfDone()\n }\n streamDone = true\n setState('playing')\n return\n }\n\n await readFrames(\n res.body.getReader(),\n (frame) => {\n if (cancelled) return\n scheduled += 1\n // decodeAudioData detaches the buffer it is given, which would\n // corrupt later frames sharing the same backing ArrayBuffer.\n const bytes = frame.slice().buffer\n audioContext\n .decodeAudioData(bytes)\n .then((buffer) => {\n if (cancelled) return\n const source = audioContext.createBufferSource()\n source.buffer = buffer\n source.connect(audioContext.destination)\n const startAt = Math.max(nextStartAt, audioContext.currentTime)\n source.start(startAt)\n nextStartAt = startAt + buffer.duration\n source.onended = () => {\n sourcesDone += 1\n finishIfDone()\n }\n if (scheduled === 1) setState('playing')\n })\n .catch(() => {\n sourcesDone += 1\n finishIfDone()\n })\n },\n controller.signal,\n )\n streamDone = true\n finishIfDone()\n if (scheduled === 0) setState('unavailable')\n } catch {\n if (!cancelled) setState('unavailable')\n }\n })()\n }, [resolve])\n\n const toggle = useCallback(() => {\n if (state === 'playing' || state === 'loading') {\n stop()\n return\n }\n play()\n }, [state, play, stop])\n\n return { state, toggle, stop }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lalternative/tornade-sdk-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "React hook that plays a tornade reading in the browser, straight from tornade on a URL the application signed",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|