@happyvertical/speech 0.78.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/AGENT.md +51 -0
- package/LICENSE +7 -0
- package/README.md +85 -0
- package/dist/adapters/openai-compatible.d.ts +11 -0
- package/dist/adapters/openai-compatible.d.ts.map +1 -0
- package/dist/adapters/qwen3.d.ts +11 -0
- package/dist/adapters/qwen3.d.ts.map +1 -0
- package/dist/adapters/studio-server.d.ts +16 -0
- package/dist/adapters/studio-server.d.ts.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +694 -0
- package/dist/index.js.map +1 -0
- package/dist/shared/errors.d.ts +21 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/factory.d.ts +22 -0
- package/dist/shared/factory.d.ts.map +1 -0
- package/dist/shared/http.d.ts +31 -0
- package/dist/shared/http.d.ts.map +1 -0
- package/dist/shared/types.d.ts +143 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/metadata.json +31 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/shared/errors.ts","../src/shared/http.ts","../src/adapters/openai-compatible.ts","../src/adapters/qwen3.ts","../src/adapters/studio-server.ts","../src/shared/factory.ts"],"sourcesContent":["export class SpeechError extends Error {\n constructor(\n message: string,\n public code: string,\n public adapter?: string,\n ) {\n super(message);\n this.name = 'SpeechError';\n }\n}\n\nexport class SpeechConfigurationError extends SpeechError {\n constructor(message: string, adapter?: string) {\n super(message, 'SPEECH_CONFIGURATION_ERROR', adapter);\n this.name = 'SpeechConfigurationError';\n }\n}\n\nexport class InvalidSpeechAdapterError extends SpeechError {\n constructor(type: string, kind: string) {\n super(`Invalid ${kind} speech adapter type: ${type}`, 'INVALID_ADAPTER');\n this.name = 'InvalidSpeechAdapterError';\n }\n}\n\nexport class SpeechProviderError extends SpeechError {\n readonly status?: number;\n readonly responseBody?: string;\n\n constructor(\n adapter: string,\n message: string,\n options: { status?: number; responseBody?: string; cause?: unknown } = {},\n ) {\n super(message, 'SPEECH_PROVIDER_ERROR', adapter);\n this.name = 'SpeechProviderError';\n this.status = options.status;\n this.responseBody = options.responseBody;\n if (options.cause !== undefined) {\n this.cause = options.cause;\n }\n }\n}\n","import { SpeechConfigurationError, SpeechProviderError } from './errors.js';\nimport type {\n AudioInput,\n HttpSpeechOptions,\n SpeechFetch,\n SynthesisRequest,\n SynthesizedSpeech,\n TranscriptResult,\n TranscriptSegment,\n WordTiming,\n} from './types.js';\n\nexport function normalizeBaseUrl(baseUrl: string): string {\n if (!baseUrl.trim()) {\n throw new SpeechConfigurationError('Speech adapter baseUrl is required');\n }\n\n return baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n}\n\nexport function resolveSpeechUrl(baseUrl: string, path: string): string {\n return new URL(path.replace(/^\\//, ''), normalizeBaseUrl(baseUrl)).toString();\n}\n\nexport function resolveFetch(fetchOverride?: SpeechFetch): SpeechFetch {\n if (fetchOverride) {\n return fetchOverride;\n }\n\n const globalFetch = globalThis.fetch;\n if (!globalFetch) {\n throw new SpeechConfigurationError(\n 'No fetch implementation available for speech adapter',\n );\n }\n\n return globalFetch.bind(globalThis);\n}\n\nexport function mergeHeaders(\n options: Pick<HttpSpeechOptions, 'apiKey' | 'headers'>,\n extra?: HeadersInit,\n): Headers {\n const headers = new Headers(options.headers);\n\n if (options.apiKey && !headers.has('authorization')) {\n headers.set('authorization', `Bearer ${options.apiKey}`);\n }\n\n if (extra) {\n new Headers(extra).forEach((value, key) => {\n headers.set(key, value);\n });\n }\n\n return headers;\n}\n\nexport abstract class HttpSpeechAdapter {\n protected readonly baseUrl: string;\n protected readonly fetchImpl: SpeechFetch;\n protected readonly apiKey?: string;\n protected readonly headers?: HeadersInit;\n protected readonly timeoutMs?: number;\n\n constructor(options: HttpSpeechOptions) {\n this.baseUrl = options.baseUrl;\n this.fetchImpl = resolveFetch(options.fetch);\n this.apiKey = options.apiKey;\n this.headers = options.headers;\n this.timeoutMs = options.timeoutMs;\n }\n\n protected async post<T>(\n adapterName: string,\n path: string,\n init: Omit<RequestInit, 'method'>,\n readResponse: (response: Response) => Promise<T>,\n ): Promise<T> {\n const timeoutController =\n this.timeoutMs && this.timeoutMs > 0 ? new AbortController() : undefined;\n const timeout =\n timeoutController && this.timeoutMs\n ? setTimeout(() => timeoutController.abort(), this.timeoutMs)\n : undefined;\n const requestSignal = composeAbortSignals(\n init.signal,\n timeoutController?.signal,\n );\n\n try {\n const response = await this.fetchImpl(\n resolveSpeechUrl(this.baseUrl, path),\n {\n ...init,\n method: 'POST',\n headers: mergeHeaders(\n { apiKey: this.apiKey, headers: this.headers },\n init.headers,\n ),\n signal: requestSignal.signal,\n },\n );\n await assertOk(response, adapterName);\n return await readResponse(response);\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n requestSignal.cleanup();\n }\n }\n}\n\nfunction composeAbortSignals(\n ...signals: Array<AbortSignal | undefined | null>\n): { signal?: AbortSignal; cleanup: () => void } {\n const activeSignals = signals.filter((signal): signal is AbortSignal =>\n Boolean(signal),\n );\n\n if (activeSignals.length === 0) {\n return { cleanup: () => undefined };\n }\n\n if (activeSignals.length === 1) {\n return { signal: activeSignals[0], cleanup: () => undefined };\n }\n\n const controller = new AbortController();\n let cleanup = () => undefined;\n\n const abortFrom = (signal: AbortSignal) => {\n if (!controller.signal.aborted) {\n controller.abort(signal.reason);\n }\n cleanup();\n };\n\n const onAbort = (event: Event) => {\n abortFrom(event.target as AbortSignal);\n };\n\n cleanup = () => {\n for (const signal of activeSignals) {\n signal.removeEventListener('abort', onAbort);\n }\n };\n\n for (const signal of activeSignals) {\n if (signal.aborted) {\n abortFrom(signal);\n return { signal: controller.signal, cleanup: () => undefined };\n }\n }\n\n for (const signal of activeSignals) {\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n return { signal: controller.signal, cleanup };\n}\n\nasync function assertOk(\n response: Response,\n adapterName: string,\n): Promise<void> {\n if (response.ok) {\n return;\n }\n\n const responseBody = await response.text().catch(() => undefined);\n throw new SpeechProviderError(\n adapterName,\n `${adapterName} speech request failed with HTTP ${response.status}`,\n {\n status: response.status,\n responseBody,\n },\n );\n}\n\nexport function appendAudioInput(\n form: FormData,\n audio: AudioInput,\n fieldName = 'audio',\n): void {\n const filename = audio.filename ?? 'audio';\n const data = audio.data;\n\n if (typeof Blob !== 'undefined' && data instanceof Blob) {\n const contentType =\n audio.contentType ?? (data.type || 'application/octet-stream');\n const blob =\n data.type === contentType\n ? data\n : new Blob([data], { type: contentType });\n form.append(fieldName, blob, filename);\n return;\n }\n\n const contentType = audio.contentType ?? 'application/octet-stream';\n const blobPart =\n data instanceof Uint8Array ? arrayBufferFromBytes(data) : data;\n form.append(fieldName, new Blob([blobPart], { type: contentType }), filename);\n}\n\nexport function appendOptionalFormValue(\n form: FormData,\n name: string,\n value: unknown,\n): void {\n if (value === undefined || value === null) {\n return;\n }\n\n form.append(name, String(value));\n}\n\nexport function createHappyVerticalSynthesisForm(\n request: SynthesisRequest,\n defaultVoice?: string,\n): FormData {\n const form = new FormData();\n const voice =\n request.voice && typeof request.voice !== 'string'\n ? request.voice\n : undefined;\n form.set('text', request.text);\n appendOptionalFormValue(\n form,\n 'language',\n request.language ?? voice?.language,\n );\n appendOptionalFormValue(\n form,\n 'speaker',\n voiceToString(request.voice, defaultVoice),\n );\n appendOptionalFormValue(form, 'speed', request.speed);\n\n appendOptionalFormValue(form, 'voice_prompt', voice?.prompt);\n\n return form;\n}\n\nexport function voiceToString(\n voice:\n | string\n | { id?: string; name?: string; speakerId?: string }\n | undefined,\n fallback?: string,\n): string | undefined {\n if (!voice) {\n return fallback;\n }\n\n if (typeof voice === 'string') {\n return voice;\n }\n\n return voice.id ?? voice.name ?? voice.speakerId ?? fallback;\n}\n\nexport function compactJson(\n value: Record<string, unknown>,\n): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(value).filter(([, entryValue]) => entryValue !== undefined),\n );\n}\n\nexport function contentTypeToFormat(contentType: string): string | undefined {\n const match = /^audio\\/([^;]+)/.exec(contentType);\n return match?.[1];\n}\n\nexport function arrayBufferFromBytes(bytes: Uint8Array): ArrayBuffer {\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy.buffer;\n}\n\nexport function decodeBase64(base64: string): ArrayBuffer {\n if (typeof Buffer !== 'undefined') {\n return arrayBufferFromBytes(Buffer.from(base64, 'base64'));\n }\n\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes.buffer;\n}\n\nfunction getNumber(\n value: Record<string, unknown>,\n ...keys: string[]\n): number | undefined {\n for (const key of keys) {\n const candidate = value[key];\n if (typeof candidate === 'number') {\n return candidate;\n }\n }\n\n return undefined;\n}\n\nfunction getString(\n value: Record<string, unknown>,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const candidate = value[key];\n if (typeof candidate === 'string') {\n return candidate;\n }\n }\n\n return undefined;\n}\n\nexport function normalizeWordTimings(value: unknown): WordTiming[] | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n return value.flatMap((entry): WordTiming[] => {\n if (!entry || typeof entry !== 'object') {\n return [];\n }\n\n const record = entry as Record<string, unknown>;\n const word = getString(record, 'word', 'text', 'token');\n const startSeconds = getNumber(\n record,\n 'startSeconds',\n 'start',\n 'start_time',\n );\n const endSeconds = getNumber(record, 'endSeconds', 'end', 'end_time');\n\n if (!word || startSeconds === undefined || endSeconds === undefined) {\n return [];\n }\n\n return [\n {\n word,\n startSeconds,\n endSeconds,\n confidence: getNumber(record, 'confidence'),\n speakerId: getString(record, 'speakerId', 'speaker', 'speaker_id'),\n },\n ];\n });\n}\n\nexport function normalizeTranscriptSegments(\n value: unknown,\n): TranscriptSegment[] | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n return value.flatMap((entry): TranscriptSegment[] => {\n if (!entry || typeof entry !== 'object') {\n return [];\n }\n\n const record = entry as Record<string, unknown>;\n const text = getString(record, 'text', 'transcript');\n if (!text) {\n return [];\n }\n\n return [\n {\n text,\n startSeconds: getNumber(record, 'startSeconds', 'start', 'start_time'),\n endSeconds: getNumber(record, 'endSeconds', 'end', 'end_time'),\n confidence: getNumber(record, 'confidence'),\n speakerId: getString(record, 'speakerId', 'speaker', 'speaker_id'),\n },\n ];\n });\n}\n\nexport async function readTranscriptResponse(\n response: Response,\n adapterName: string,\n): Promise<TranscriptResult> {\n const contentType = response.headers.get('content-type') ?? '';\n\n if (!contentType.includes('application/json')) {\n const text = await response.text();\n return {\n text,\n provider: adapterName,\n };\n }\n\n const json = (await response.json()) as Record<string, unknown>;\n const text = getString(json, 'text', 'transcript', 'transcription') ?? '';\n\n return {\n text,\n language: getString(json, 'language', 'lang'),\n durationSeconds: getNumber(json, 'durationSeconds', 'duration'),\n words: normalizeWordTimings(\n json.words ?? json.wordTimings ?? json.word_timings,\n ),\n segments: normalizeTranscriptSegments(json.segments),\n provider: getString(json, 'provider') ?? adapterName,\n model: getString(json, 'model'),\n raw: json,\n };\n}\n\nexport async function readSynthesizedSpeechResponse(\n response: Response,\n adapterName: string,\n): Promise<SynthesizedSpeech> {\n const responseContentType =\n response.headers.get('content-type') ?? 'application/octet-stream';\n\n if (!responseContentType.includes('application/json')) {\n const audio = await response.arrayBuffer();\n const sampleRate = parseHeaderNumber(response, 'x-sample-rate');\n return {\n audio,\n contentType: responseContentType,\n format: contentTypeToFormat(responseContentType),\n sampleRate,\n provider: adapterName,\n };\n }\n\n const json = (await response.json()) as Record<string, unknown>;\n const contentType =\n getString(json, 'contentType', 'content_type', 'mimeType', 'mime_type') ??\n 'application/octet-stream';\n const encodedAudio = getString(\n json,\n 'audio',\n 'audioContent',\n 'audio_content',\n );\n\n if (!encodedAudio) {\n throw new SpeechProviderError(\n adapterName,\n `${adapterName} JSON speech response did not include base64 audio`,\n );\n }\n\n return {\n audio: decodeBase64(encodedAudio),\n contentType,\n format:\n getString(json, 'format', 'response_format') ??\n contentTypeToFormat(contentType),\n sampleRate: getNumber(json, 'sampleRate', 'sample_rate'),\n channels: getNumber(json, 'channels'),\n durationSeconds: getNumber(json, 'durationSeconds', 'duration'),\n words: normalizeWordTimings(\n json.words ?? json.wordTimings ?? json.word_timings,\n ),\n provider: getString(json, 'provider') ?? adapterName,\n model: getString(json, 'model'),\n raw: json,\n };\n}\n\nfunction parseHeaderNumber(\n response: Response,\n headerName: string,\n): number | undefined {\n const value = response.headers.get(headerName);\n if (!value) {\n return undefined;\n }\n\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n","import {\n compactJson,\n HttpSpeechAdapter,\n readSynthesizedSpeechResponse,\n voiceToString,\n} from '../shared/http.js';\nimport type {\n OpenAICompatibleSpeechSynthesizerOptions,\n SpeechSynthesizer,\n SynthesisRequest,\n SynthesizedSpeech,\n} from '../shared/types.js';\n\nexport class OpenAICompatibleSpeechSynthesizer\n extends HttpSpeechAdapter\n implements SpeechSynthesizer\n{\n readonly type = 'openai-compatible' as const;\n\n private readonly speechPath: string;\n private readonly defaultModel: string;\n private readonly defaultVoice: string;\n\n constructor(options: OpenAICompatibleSpeechSynthesizerOptions) {\n super(options);\n this.speechPath = options.speechPath ?? '/v1/audio/speech';\n this.defaultModel = options.defaultModel ?? 'tts-1';\n this.defaultVoice = options.defaultVoice ?? 'alloy';\n }\n\n async synthesize(request: SynthesisRequest): Promise<SynthesizedSpeech> {\n const outputFormat = request.outputFormat ?? 'mp3';\n const payload = compactJson({\n model: request.model ?? this.defaultModel,\n input: request.text,\n voice: voiceToString(request.voice, this.defaultVoice),\n // biome-ignore lint/style/useNamingConvention: OpenAI-compatible API uses snake_case.\n response_format: outputFormat,\n speed: request.speed,\n });\n\n const speech = await this.post(\n this.type,\n this.speechPath,\n {\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify(payload),\n signal: request.signal,\n },\n (response) => readSynthesizedSpeechResponse(response, this.type),\n );\n\n return {\n ...speech,\n format: speech.format ?? outputFormat,\n model: speech.model ?? String(payload.model),\n };\n }\n}\n","import {\n createHappyVerticalSynthesisForm,\n HttpSpeechAdapter,\n readSynthesizedSpeechResponse,\n} from '../shared/http.js';\nimport type {\n Qwen3SpeechSynthesizerOptions,\n SpeechSynthesizer,\n SynthesisRequest,\n SynthesizedSpeech,\n} from '../shared/types.js';\n\nexport class Qwen3SpeechSynthesizer\n extends HttpSpeechAdapter\n implements SpeechSynthesizer\n{\n readonly type = 'qwen3-tts' as const;\n\n private readonly speechPath: string;\n private readonly defaultModel: string;\n private readonly defaultVoice?: string;\n\n constructor(options: Qwen3SpeechSynthesizerOptions) {\n super(options);\n this.speechPath = options.speechPath ?? '/v1/audio/speech';\n this.defaultModel = options.defaultModel ?? 'qwen3-tts';\n this.defaultVoice = options.defaultVoice;\n }\n\n async synthesize(request: SynthesisRequest): Promise<SynthesizedSpeech> {\n const form = createHappyVerticalSynthesisForm(request, this.defaultVoice);\n const speech = await this.post(\n this.type,\n this.speechPath,\n {\n body: form,\n signal: request.signal,\n },\n (response) => readSynthesizedSpeechResponse(response, this.type),\n );\n\n return {\n ...speech,\n format: speech.format ?? request.outputFormat,\n model: speech.model ?? request.model ?? this.defaultModel,\n };\n }\n}\n","import {\n appendAudioInput,\n appendOptionalFormValue,\n createHappyVerticalSynthesisForm,\n HttpSpeechAdapter,\n readSynthesizedSpeechResponse,\n readTranscriptResponse,\n} from '../shared/http.js';\nimport type {\n SpeechSynthesizer,\n StudioServerSpeechSynthesizerOptions,\n StudioServerTranscriberOptions,\n SynthesisRequest,\n SynthesizedSpeech,\n Transcriber,\n TranscriptionRequest,\n TranscriptResult,\n} from '../shared/types.js';\n\nexport class StudioServerTranscriber\n extends HttpSpeechAdapter\n implements Transcriber\n{\n readonly type = 'studio-server' as const;\n private readonly transcribePath: string;\n\n constructor(options: StudioServerTranscriberOptions) {\n super(options);\n this.transcribePath = options.transcribePath ?? '/v1/transcribe';\n }\n\n async transcribe(request: TranscriptionRequest): Promise<TranscriptResult> {\n const form = new FormData();\n appendAudioInput(form, request.audio);\n appendOptionalFormValue(form, 'language', request.language);\n\n return this.post(\n this.type,\n this.transcribePath,\n {\n body: form,\n signal: request.signal,\n },\n (response) => readTranscriptResponse(response, this.type),\n );\n }\n}\n\nexport class StudioServerSpeechSynthesizer\n extends HttpSpeechAdapter\n implements SpeechSynthesizer\n{\n readonly type = 'studio-server' as const;\n private readonly synthesizePath: string;\n private readonly defaultVoice?: string;\n\n constructor(options: StudioServerSpeechSynthesizerOptions) {\n super(options);\n this.synthesizePath = options.synthesizePath ?? '/v1/tts/synthesize';\n this.defaultVoice = options.defaultVoice;\n }\n\n async synthesize(request: SynthesisRequest): Promise<SynthesizedSpeech> {\n const form = createHappyVerticalSynthesisForm(request, this.defaultVoice);\n\n return this.post(\n this.type,\n this.synthesizePath,\n {\n body: form,\n signal: request.signal,\n },\n (response) => readSynthesizedSpeechResponse(response, this.type),\n );\n }\n}\n","import { OpenAICompatibleSpeechSynthesizer } from '../adapters/openai-compatible.js';\nimport { Qwen3SpeechSynthesizer } from '../adapters/qwen3.js';\nimport {\n StudioServerSpeechSynthesizer,\n StudioServerTranscriber,\n} from '../adapters/studio-server.js';\nimport {\n InvalidSpeechAdapterError,\n SpeechConfigurationError,\n} from './errors.js';\nimport type {\n GetSpeechOptions,\n GetSpeechSynthesizerOptions,\n GetTranscriberOptions,\n OpenAICompatibleSpeechSynthesizerOptions,\n Qwen3SpeechSynthesizerOptions,\n Speech,\n SpeechAdapterAvailability,\n SpeechFetch,\n SpeechSynthesizer,\n StudioServerSpeechSynthesizerOptions,\n StudioServerTranscriberOptions,\n SynthesisRequest,\n SynthesizedSpeech,\n Transcriber,\n TranscriptionRequest,\n TranscriptResult,\n} from './types.js';\n\ninterface SpeechEnv {\n [key: string]: string | undefined;\n}\n\nexport interface SpeechFactoryContext {\n env?: SpeechEnv;\n fetch?: SpeechFetch;\n headers?: HeadersInit;\n}\n\n/**\n * Creates a speech service from explicit options and/or environment variables.\n *\n * Explicit options win over environment defaults. If no STT or TTS config is\n * available, the returned service is still usable for dependency injection, but\n * calling the missing operation throws a configuration error.\n */\nexport async function getSpeech(\n options: GetSpeechOptions = {},\n context: SpeechFactoryContext = {},\n): Promise<Speech> {\n const transcriber =\n options.transcriber === false\n ? undefined\n : await getOptionalTranscriber(options.transcriber, context);\n const synthesizer =\n options.synthesizer === false\n ? undefined\n : await getOptionalSpeechSynthesizer(options.synthesizer, context);\n\n return {\n transcriber,\n synthesizer,\n async transcribe(request: TranscriptionRequest): Promise<TranscriptResult> {\n if (!transcriber) {\n throw new SpeechConfigurationError('No STT provider configured');\n }\n return transcriber.transcribe(request);\n },\n async synthesize(request: SynthesisRequest): Promise<SynthesizedSpeech> {\n if (!synthesizer) {\n throw new SpeechConfigurationError('No TTS provider configured');\n }\n return synthesizer.synthesize(request);\n },\n };\n}\n\nexport async function getTranscriber(\n options: GetTranscriberOptions = {},\n context: SpeechFactoryContext = {},\n): Promise<Transcriber> {\n const resolved = normalizeTranscriberOptions(options, context);\n\n switch (resolved.type) {\n case 'studio-server':\n return new StudioServerTranscriber(resolved);\n default:\n throw new InvalidSpeechAdapterError(\n (resolved as { type?: string }).type ?? 'unknown',\n 'STT',\n );\n }\n}\n\nexport async function getSpeechSynthesizer(\n options?: GetSpeechSynthesizerOptions,\n context: SpeechFactoryContext = {},\n): Promise<SpeechSynthesizer> {\n const resolved = normalizeSpeechSynthesizerOptions(options, context);\n\n switch (resolved.type) {\n case 'studio-server':\n return new StudioServerSpeechSynthesizer(resolved);\n case 'qwen3-tts':\n return new Qwen3SpeechSynthesizer(resolved);\n case 'openai-compatible':\n return new OpenAICompatibleSpeechSynthesizer(resolved);\n default:\n throw new InvalidSpeechAdapterError(\n (resolved as { type?: string }).type ?? 'unknown',\n 'TTS',\n );\n }\n}\n\nexport function getAvailableSpeechAdapters(): SpeechAdapterAvailability {\n return {\n transcribers: ['studio-server'],\n synthesizers: ['studio-server', 'qwen3-tts', 'openai-compatible'],\n };\n}\n\nasync function getOptionalTranscriber(\n options: GetTranscriberOptions | undefined,\n context: SpeechFactoryContext,\n): Promise<Transcriber | undefined> {\n if (!options && !hasTranscriberEnv(context.env ?? defaultEnv())) {\n return undefined;\n }\n\n return getTranscriber(options, context);\n}\n\nasync function getOptionalSpeechSynthesizer(\n options: GetSpeechSynthesizerOptions | undefined,\n context: SpeechFactoryContext,\n): Promise<SpeechSynthesizer | undefined> {\n if (!options && !hasSynthesizerEnv(context.env ?? defaultEnv())) {\n return undefined;\n }\n\n return getSpeechSynthesizer(options, context);\n}\n\nfunction normalizeTranscriberOptions(\n options: GetTranscriberOptions = {},\n context: SpeechFactoryContext,\n): StudioServerTranscriberOptions {\n const env = context.env ?? defaultEnv();\n const type =\n options.type ??\n readEnv(\n env,\n 'HAVE_SPEECH_STT_TYPE',\n 'HAVE_SPEECH_STT_ADAPTER',\n 'STT_ADAPTER',\n ) ??\n 'studio-server';\n const baseUrl =\n options.baseUrl ?? readEnv(env, 'HAVE_SPEECH_STT_BASE_URL', 'STT_BASE_URL');\n\n if (type !== 'studio-server') {\n throw new InvalidSpeechAdapterError(type, 'STT');\n }\n\n if (!baseUrl?.trim()) {\n throw new SpeechConfigurationError('STT baseUrl is required', type);\n }\n\n return {\n ...options,\n type,\n baseUrl: baseUrl.trim(),\n fetch: options.fetch ?? context.fetch,\n headers: options.headers ?? context.headers,\n apiKey:\n options.apiKey ??\n readEnv(env, 'HAVE_SPEECH_STT_API_KEY', 'STT_API_KEY', 'SPEECH_API_KEY'),\n timeoutMs:\n options.timeoutMs ??\n parseOptionalInteger(\n readEnv(env, 'HAVE_SPEECH_STT_TIMEOUT_MS', 'STT_TIMEOUT_MS'),\n ),\n transcribePath:\n options.transcribePath ??\n readEnv(env, 'HAVE_SPEECH_STT_PATH', 'STT_PATH'),\n };\n}\n\nfunction normalizeSpeechSynthesizerOptions(\n options: GetSpeechSynthesizerOptions | undefined,\n context: SpeechFactoryContext,\n):\n | StudioServerSpeechSynthesizerOptions\n | Qwen3SpeechSynthesizerOptions\n | OpenAICompatibleSpeechSynthesizerOptions {\n const env = context.env ?? defaultEnv();\n const type =\n options?.type ??\n (readEnv(\n env,\n 'HAVE_SPEECH_TTS_TYPE',\n 'HAVE_SPEECH_TTS_ADAPTER',\n 'TTS_ADAPTER',\n ) as GetSpeechSynthesizerOptions['type'] | undefined);\n const baseUrl =\n options?.baseUrl ??\n readEnv(env, 'HAVE_SPEECH_TTS_BASE_URL', 'TTS_BASE_URL');\n\n if (!type) {\n throw new SpeechConfigurationError('TTS provider type is required');\n }\n\n if (\n type !== 'studio-server' &&\n type !== 'qwen3-tts' &&\n type !== 'openai-compatible'\n ) {\n throw new InvalidSpeechAdapterError(type, 'TTS');\n }\n\n if (!baseUrl?.trim()) {\n throw new SpeechConfigurationError('TTS baseUrl is required', type);\n }\n\n const shared = {\n type,\n baseUrl: baseUrl.trim(),\n fetch: options?.fetch ?? context.fetch,\n headers: options?.headers ?? context.headers,\n apiKey:\n options?.apiKey ??\n readEnv(env, 'HAVE_SPEECH_TTS_API_KEY', 'TTS_API_KEY', 'SPEECH_API_KEY'),\n timeoutMs:\n options?.timeoutMs ??\n parseOptionalInteger(\n readEnv(env, 'HAVE_SPEECH_TTS_TIMEOUT_MS', 'TTS_TIMEOUT_MS'),\n ),\n };\n\n if (type === 'studio-server') {\n return {\n ...shared,\n type,\n synthesizePath:\n options?.synthesizePath ??\n readEnv(env, 'HAVE_SPEECH_TTS_PATH', 'TTS_PATH'),\n defaultVoice:\n options?.defaultVoice ??\n readEnv(env, 'HAVE_SPEECH_TTS_VOICE', 'TTS_VOICE'),\n };\n }\n\n if (type === 'qwen3-tts') {\n return {\n ...shared,\n type,\n speechPath:\n options?.speechPath ?? readEnv(env, 'HAVE_SPEECH_TTS_PATH', 'TTS_PATH'),\n defaultModel:\n options?.defaultModel ??\n readEnv(env, 'HAVE_SPEECH_TTS_MODEL', 'TTS_MODEL'),\n defaultVoice:\n options?.defaultVoice ??\n readEnv(env, 'HAVE_SPEECH_TTS_VOICE', 'TTS_VOICE'),\n };\n }\n\n if (type === 'openai-compatible') {\n return {\n ...shared,\n type,\n speechPath:\n options?.speechPath ?? readEnv(env, 'HAVE_SPEECH_TTS_PATH', 'TTS_PATH'),\n defaultModel:\n options?.defaultModel ??\n readEnv(env, 'HAVE_SPEECH_TTS_MODEL', 'TTS_MODEL'),\n defaultVoice:\n options?.defaultVoice ??\n readEnv(env, 'HAVE_SPEECH_TTS_VOICE', 'TTS_VOICE'),\n };\n }\n\n throw new InvalidSpeechAdapterError(type, 'TTS');\n}\n\nfunction hasTranscriberEnv(env: SpeechEnv): boolean {\n return hasAnyEnv(\n env,\n 'HAVE_SPEECH_STT_TYPE',\n 'HAVE_SPEECH_STT_ADAPTER',\n 'HAVE_SPEECH_STT_BASE_URL',\n 'STT_ADAPTER',\n 'STT_BASE_URL',\n );\n}\n\nfunction hasSynthesizerEnv(env: SpeechEnv): boolean {\n return hasAnyEnv(\n env,\n 'HAVE_SPEECH_TTS_TYPE',\n 'HAVE_SPEECH_TTS_ADAPTER',\n 'HAVE_SPEECH_TTS_BASE_URL',\n 'TTS_ADAPTER',\n 'TTS_BASE_URL',\n );\n}\n\nfunction readEnv(env: SpeechEnv, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const value = env[key];\n if (value?.trim()) {\n return value.trim();\n }\n }\n\n return undefined;\n}\n\nfunction hasAnyEnv(env: SpeechEnv, ...keys: string[]): boolean {\n return keys.some((key) => Boolean(env[key]?.trim()));\n}\n\nfunction parseOptionalInteger(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const parsed = Number.parseInt(value, 10);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction defaultEnv(): SpeechEnv {\n return globalThis.process?.env ?? {};\n}\n"],"names":["contentType","text"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class SpeechError extends Error {
|
|
2
|
+
code: string;
|
|
3
|
+
adapter?: string | undefined;
|
|
4
|
+
constructor(message: string, code: string, adapter?: string | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class SpeechConfigurationError extends SpeechError {
|
|
7
|
+
constructor(message: string, adapter?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class InvalidSpeechAdapterError extends SpeechError {
|
|
10
|
+
constructor(type: string, kind: string);
|
|
11
|
+
}
|
|
12
|
+
export declare class SpeechProviderError extends SpeechError {
|
|
13
|
+
readonly status?: number;
|
|
14
|
+
readonly responseBody?: string;
|
|
15
|
+
constructor(adapter: string, message: string, options?: {
|
|
16
|
+
status?: number;
|
|
17
|
+
responseBody?: string;
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAY,SAAQ,KAAK;IAG3B,IAAI,EAAE,MAAM;IACZ,OAAO,CAAC,EAAE,MAAM;gBAFvB,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,YAAA;CAK1B;AAED,qBAAa,wBAAyB,SAAQ,WAAW;gBAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAI9C;AAED,qBAAa,yBAA0B,SAAQ,WAAW;gBAC5C,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAIvC;AAED,qBAAa,mBAAoB,SAAQ,WAAW;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAG7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAU5E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { GetSpeechOptions, GetSpeechSynthesizerOptions, GetTranscriberOptions, Speech, SpeechAdapterAvailability, SpeechFetch, SpeechSynthesizer, Transcriber } from './types.js';
|
|
2
|
+
interface SpeechEnv {
|
|
3
|
+
[key: string]: string | undefined;
|
|
4
|
+
}
|
|
5
|
+
export interface SpeechFactoryContext {
|
|
6
|
+
env?: SpeechEnv;
|
|
7
|
+
fetch?: SpeechFetch;
|
|
8
|
+
headers?: HeadersInit;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates a speech service from explicit options and/or environment variables.
|
|
12
|
+
*
|
|
13
|
+
* Explicit options win over environment defaults. If no STT or TTS config is
|
|
14
|
+
* available, the returned service is still usable for dependency injection, but
|
|
15
|
+
* calling the missing operation throws a configuration error.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getSpeech(options?: GetSpeechOptions, context?: SpeechFactoryContext): Promise<Speech>;
|
|
18
|
+
export declare function getTranscriber(options?: GetTranscriberOptions, context?: SpeechFactoryContext): Promise<Transcriber>;
|
|
19
|
+
export declare function getSpeechSynthesizer(options?: GetSpeechSynthesizerOptions, context?: SpeechFactoryContext): Promise<SpeechSynthesizer>;
|
|
20
|
+
export declare function getAvailableSpeechAdapters(): SpeechAdapterAvailability;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/shared/factory.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,gBAAgB,EAChB,2BAA2B,EAC3B,qBAAqB,EAGrB,MAAM,EACN,yBAAyB,EACzB,WAAW,EACX,iBAAiB,EAKjB,WAAW,EAGZ,MAAM,YAAY,CAAC;AAEpB,UAAU,SAAS;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,OAAO,GAAE,gBAAqB,EAC9B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAED,wBAAsB,cAAc,CAClC,OAAO,GAAE,qBAA0B,EACnC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,WAAW,CAAC,CAYtB;AAED,wBAAsB,oBAAoB,CACxC,OAAO,CAAC,EAAE,2BAA2B,EACrC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,iBAAiB,CAAC,CAgB5B;AAED,wBAAgB,0BAA0B,IAAI,yBAAyB,CAKtE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AudioInput, HttpSpeechOptions, SpeechFetch, SynthesisRequest, SynthesizedSpeech, TranscriptResult, TranscriptSegment, WordTiming } from './types.js';
|
|
2
|
+
export declare function normalizeBaseUrl(baseUrl: string): string;
|
|
3
|
+
export declare function resolveSpeechUrl(baseUrl: string, path: string): string;
|
|
4
|
+
export declare function resolveFetch(fetchOverride?: SpeechFetch): SpeechFetch;
|
|
5
|
+
export declare function mergeHeaders(options: Pick<HttpSpeechOptions, 'apiKey' | 'headers'>, extra?: HeadersInit): Headers;
|
|
6
|
+
export declare abstract class HttpSpeechAdapter {
|
|
7
|
+
protected readonly baseUrl: string;
|
|
8
|
+
protected readonly fetchImpl: SpeechFetch;
|
|
9
|
+
protected readonly apiKey?: string;
|
|
10
|
+
protected readonly headers?: HeadersInit;
|
|
11
|
+
protected readonly timeoutMs?: number;
|
|
12
|
+
constructor(options: HttpSpeechOptions);
|
|
13
|
+
protected post<T>(adapterName: string, path: string, init: Omit<RequestInit, 'method'>, readResponse: (response: Response) => Promise<T>): Promise<T>;
|
|
14
|
+
}
|
|
15
|
+
export declare function appendAudioInput(form: FormData, audio: AudioInput, fieldName?: string): void;
|
|
16
|
+
export declare function appendOptionalFormValue(form: FormData, name: string, value: unknown): void;
|
|
17
|
+
export declare function createHappyVerticalSynthesisForm(request: SynthesisRequest, defaultVoice?: string): FormData;
|
|
18
|
+
export declare function voiceToString(voice: string | {
|
|
19
|
+
id?: string;
|
|
20
|
+
name?: string;
|
|
21
|
+
speakerId?: string;
|
|
22
|
+
} | undefined, fallback?: string): string | undefined;
|
|
23
|
+
export declare function compactJson(value: Record<string, unknown>): Record<string, unknown>;
|
|
24
|
+
export declare function contentTypeToFormat(contentType: string): string | undefined;
|
|
25
|
+
export declare function arrayBufferFromBytes(bytes: Uint8Array): ArrayBuffer;
|
|
26
|
+
export declare function decodeBase64(base64: string): ArrayBuffer;
|
|
27
|
+
export declare function normalizeWordTimings(value: unknown): WordTiming[] | undefined;
|
|
28
|
+
export declare function normalizeTranscriptSegments(value: unknown): TranscriptSegment[] | undefined;
|
|
29
|
+
export declare function readTranscriptResponse(response: Response, adapterName: string): Promise<TranscriptResult>;
|
|
30
|
+
export declare function readSynthesizedSpeechResponse(response: Response, adapterName: string): Promise<SynthesizedSpeech>;
|
|
31
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/shared/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,YAAY,CAAC,aAAa,CAAC,EAAE,WAAW,GAAG,WAAW,CAarE;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,SAAS,CAAC,EACtD,KAAK,CAAC,EAAE,WAAW,GAClB,OAAO,CAcT;AAED,8BAAsB,iBAAiB;IACrC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAC1C,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;gBAE1B,OAAO,EAAE,iBAAiB;cAQtB,IAAI,CAAC,CAAC,EACpB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,EACjC,YAAY,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAC/C,OAAO,CAAC,CAAC,CAAC;CAkCd;AAsED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,UAAU,EACjB,SAAS,SAAU,GAClB,IAAI,CAmBN;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,IAAI,CAMN;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,gBAAgB,EACzB,YAAY,CAAC,EAAE,MAAM,GACpB,QAAQ,CAsBV;AAED,wBAAgB,aAAa,CAC3B,KAAK,EACD,MAAM,GACN;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD,SAAS,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIzB;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG3E;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAInE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAWxD;AA8BD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,EAAE,GAAG,SAAS,CAkC7E;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,GACb,iBAAiB,EAAE,GAAG,SAAS,CA0BjC;AAED,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CA0B3B;AAED,wBAAsB,6BAA6B,CACjD,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAkD5B"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
export type SpeechAdapterType = 'studio-server' | 'qwen3-tts' | 'openai-compatible';
|
|
2
|
+
export type TranscriberType = 'studio-server';
|
|
3
|
+
export type SpeechSynthesizerType = 'studio-server' | 'qwen3-tts' | 'openai-compatible';
|
|
4
|
+
export interface SpeechAdapterAvailability {
|
|
5
|
+
transcribers: TranscriberType[];
|
|
6
|
+
synthesizers: SpeechSynthesizerType[];
|
|
7
|
+
}
|
|
8
|
+
export type AudioBytes = ArrayBuffer | Uint8Array | Blob;
|
|
9
|
+
export interface AudioInput {
|
|
10
|
+
data: AudioBytes;
|
|
11
|
+
contentType?: string;
|
|
12
|
+
filename?: string;
|
|
13
|
+
sampleRate?: number;
|
|
14
|
+
channels?: number;
|
|
15
|
+
durationSeconds?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface WordTiming {
|
|
18
|
+
word: string;
|
|
19
|
+
startSeconds: number;
|
|
20
|
+
endSeconds: number;
|
|
21
|
+
confidence?: number;
|
|
22
|
+
speakerId?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface TranscriptSegment {
|
|
25
|
+
text: string;
|
|
26
|
+
startSeconds?: number;
|
|
27
|
+
endSeconds?: number;
|
|
28
|
+
confidence?: number;
|
|
29
|
+
speakerId?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface TranscriptResult {
|
|
32
|
+
text: string;
|
|
33
|
+
language?: string;
|
|
34
|
+
durationSeconds?: number;
|
|
35
|
+
words?: WordTiming[];
|
|
36
|
+
segments?: TranscriptSegment[];
|
|
37
|
+
provider?: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
raw?: unknown;
|
|
40
|
+
}
|
|
41
|
+
export interface TranscriptionRequest {
|
|
42
|
+
audio: AudioInput;
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
language?: string;
|
|
45
|
+
model?: string;
|
|
46
|
+
prompt?: string;
|
|
47
|
+
temperature?: number;
|
|
48
|
+
responseFormat?: 'json' | 'text' | 'verbose_json';
|
|
49
|
+
metadata?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
export interface SpeechVoice {
|
|
52
|
+
id?: string;
|
|
53
|
+
name?: string;
|
|
54
|
+
language?: string;
|
|
55
|
+
speakerId?: string;
|
|
56
|
+
/** Opaque pre-extracted prompt for providers that support voice cloning. */
|
|
57
|
+
prompt?: string;
|
|
58
|
+
metadata?: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
export type SpeechVoiceInput = string | SpeechVoice;
|
|
61
|
+
export interface SynthesisRequest {
|
|
62
|
+
text: string;
|
|
63
|
+
signal?: AbortSignal;
|
|
64
|
+
voice?: SpeechVoiceInput;
|
|
65
|
+
model?: string;
|
|
66
|
+
language?: string;
|
|
67
|
+
outputFormat?: string;
|
|
68
|
+
sampleRate?: number;
|
|
69
|
+
speed?: number;
|
|
70
|
+
pitch?: number;
|
|
71
|
+
responseFormat?: 'audio' | 'json';
|
|
72
|
+
metadata?: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
export interface SynthesizedSpeech {
|
|
75
|
+
audio: ArrayBuffer;
|
|
76
|
+
contentType: string;
|
|
77
|
+
format?: string;
|
|
78
|
+
sampleRate?: number;
|
|
79
|
+
channels?: number;
|
|
80
|
+
durationSeconds?: number;
|
|
81
|
+
words?: WordTiming[];
|
|
82
|
+
provider?: string;
|
|
83
|
+
model?: string;
|
|
84
|
+
raw?: unknown;
|
|
85
|
+
}
|
|
86
|
+
export interface Transcriber {
|
|
87
|
+
readonly type: TranscriberType;
|
|
88
|
+
transcribe(request: TranscriptionRequest): Promise<TranscriptResult>;
|
|
89
|
+
}
|
|
90
|
+
export interface SpeechSynthesizer {
|
|
91
|
+
readonly type: SpeechSynthesizerType;
|
|
92
|
+
synthesize(request: SynthesisRequest): Promise<SynthesizedSpeech>;
|
|
93
|
+
}
|
|
94
|
+
export interface Speech {
|
|
95
|
+
readonly transcriber?: Transcriber;
|
|
96
|
+
readonly synthesizer?: SpeechSynthesizer;
|
|
97
|
+
transcribe(request: TranscriptionRequest): Promise<TranscriptResult>;
|
|
98
|
+
synthesize(request: SynthesisRequest): Promise<SynthesizedSpeech>;
|
|
99
|
+
}
|
|
100
|
+
export type SpeechFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
101
|
+
export interface HttpSpeechOptions {
|
|
102
|
+
baseUrl: string;
|
|
103
|
+
fetch?: SpeechFetch;
|
|
104
|
+
apiKey?: string;
|
|
105
|
+
headers?: HeadersInit;
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
}
|
|
108
|
+
export interface StudioServerTranscriberOptions extends HttpSpeechOptions {
|
|
109
|
+
type?: 'studio-server';
|
|
110
|
+
transcribePath?: string;
|
|
111
|
+
}
|
|
112
|
+
export interface StudioServerSpeechSynthesizerOptions extends HttpSpeechOptions {
|
|
113
|
+
type: 'studio-server';
|
|
114
|
+
synthesizePath?: string;
|
|
115
|
+
defaultVoice?: string;
|
|
116
|
+
}
|
|
117
|
+
export interface Qwen3SpeechSynthesizerOptions extends HttpSpeechOptions {
|
|
118
|
+
type: 'qwen3-tts';
|
|
119
|
+
speechPath?: string;
|
|
120
|
+
defaultModel?: string;
|
|
121
|
+
defaultVoice?: string;
|
|
122
|
+
}
|
|
123
|
+
export interface OpenAICompatibleSpeechSynthesizerOptions extends HttpSpeechOptions {
|
|
124
|
+
type: 'openai-compatible';
|
|
125
|
+
speechPath?: string;
|
|
126
|
+
defaultModel?: string;
|
|
127
|
+
defaultVoice?: string;
|
|
128
|
+
}
|
|
129
|
+
export interface GetTranscriberOptions extends Partial<StudioServerTranscriberOptions> {
|
|
130
|
+
type?: TranscriberType;
|
|
131
|
+
}
|
|
132
|
+
export interface GetSpeechSynthesizerOptions extends Partial<HttpSpeechOptions> {
|
|
133
|
+
type?: SpeechSynthesizerType;
|
|
134
|
+
synthesizePath?: string;
|
|
135
|
+
speechPath?: string;
|
|
136
|
+
defaultModel?: string;
|
|
137
|
+
defaultVoice?: string;
|
|
138
|
+
}
|
|
139
|
+
export interface GetSpeechOptions {
|
|
140
|
+
transcriber?: GetTranscriberOptions | false;
|
|
141
|
+
synthesizer?: GetSpeechSynthesizerOptions | false;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
|
package/metadata.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/speech",
|
|
3
|
+
"path": "packages/speech",
|
|
4
|
+
"position": {
|
|
5
|
+
"index": 26,
|
|
6
|
+
"count": 31
|
|
7
|
+
},
|
|
8
|
+
"description": "Speech provider abstraction for STT and TTS backends",
|
|
9
|
+
"provides": [
|
|
10
|
+
"Speech provider abstraction for STT and TTS backends"
|
|
11
|
+
],
|
|
12
|
+
"implements": [
|
|
13
|
+
"Studio Server STT",
|
|
14
|
+
"Studio Server TTS",
|
|
15
|
+
"Qwen3 TTS",
|
|
16
|
+
"OpenAI-compatible TTS"
|
|
17
|
+
],
|
|
18
|
+
"requires": {
|
|
19
|
+
"workspace": [],
|
|
20
|
+
"externalHappyVertical": [],
|
|
21
|
+
"external": []
|
|
22
|
+
},
|
|
23
|
+
"dependents": [],
|
|
24
|
+
"stability": {
|
|
25
|
+
"level": "experimental",
|
|
26
|
+
"reason": "Marked as preview or experimental in package guidance."
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"speech"
|
|
30
|
+
]
|
|
31
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/speech",
|
|
3
|
+
"version": "0.78.0",
|
|
4
|
+
"description": "Speech provider abstraction for STT and TTS backends",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "25.0.10",
|
|
16
|
+
"typescript": "^5.9.3",
|
|
17
|
+
"vite": "7.3.2",
|
|
18
|
+
"vite-plugin-dts": "4.5.4",
|
|
19
|
+
"vitest": "^4.1.5"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"speech",
|
|
23
|
+
"stt",
|
|
24
|
+
"tts",
|
|
25
|
+
"studio-server",
|
|
26
|
+
"qwen3-tts"
|
|
27
|
+
],
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"AGENT.md",
|
|
33
|
+
"metadata.json"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"registry": "https://registry.npmjs.org",
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/happyvertical/sdk.git",
|
|
42
|
+
"directory": "packages/speech"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/happyvertical/sdk/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/happyvertical/sdk/tree/main/packages/speech#readme",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "npx vitest run",
|
|
51
|
+
"test:watch": "npx vitest",
|
|
52
|
+
"build": "vite build",
|
|
53
|
+
"build:watch": "vite build --watch",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"clean": "rm -rf dist",
|
|
56
|
+
"dev": "vite build --watch"
|
|
57
|
+
}
|
|
58
|
+
}
|