diff --git a/.dumirc.ts b/.dumirc.ts
index 41f4e30..61b4025 100644
--- a/.dumirc.ts
+++ b/.dumirc.ts
@@ -52,10 +52,7 @@ export default defineConfig({
'process.env': process.env,
},
favicons: ['https://lobehub.com/favicon.ico'],
- locales: [
- { id: 'en-US', name: 'English' },
- { id: 'zh-CN', name: '简体中文' },
- ],
+ locales: [{ id: 'en-US', name: 'English' }],
// mfsu: isWin ? undefined : {},
mfsu: false,
npmClient: 'pnpm',
diff --git a/api/edge-speech.ts b/api/edge-speech.ts
index e8e6ab6..8751336 100644
--- a/api/edge-speech.ts
+++ b/api/edge-speech.ts
@@ -1,4 +1,5 @@
-import { EdgeSpeechPayload, createEdgeSpeech } from '../src/core/EdgeSpeechTTS/createEdgeSpeech';
+import cors from '../lib/cors';
+import { EdgeSpeechPayload, EdgeSpeechTTS } from '../src/core';
export const config = {
runtime: 'edge',
@@ -6,8 +7,9 @@ export const config = {
export default async (req: Request) => {
if (req.method !== 'POST') return new Response('Method Not Allowed', { status: 405 });
-
const payload = (await req.json()) as EdgeSpeechPayload;
- return createEdgeSpeech({ payload });
+ const res = await EdgeSpeechTTS.createRequest({ payload });
+
+ return cors(req, res);
};
diff --git a/api/microsoft-speech.ts b/api/microsoft-speech.ts
index 5d95e62..4f3d2a1 100644
--- a/api/microsoft-speech.ts
+++ b/api/microsoft-speech.ts
@@ -1,7 +1,5 @@
-import {
- MicrosoftSpeechPayload,
- createMicrosoftSpeech,
-} from '../src/core/MicrosoftSpeechTTS/createMicrosoftSpeech';
+import cors from '../lib/cors';
+import { MicrosoftSpeechPayload, MicrosoftSpeechTTS } from '../src/core';
export const config = {
runtime: 'edge',
@@ -11,5 +9,7 @@ export default async (req: Request) => {
if (req.method !== 'POST') return new Response('Method Not Allowed', { status: 405 });
const payload = (await req.json()) as MicrosoftSpeechPayload;
- return createMicrosoftSpeech({ payload });
+ const res = await MicrosoftSpeechTTS.createRequest({ payload });
+
+ return cors(req, res);
};
diff --git a/api/openai-stt.ts b/api/openai-stt.ts
index 722f807..e457a02 100644
--- a/api/openai-stt.ts
+++ b/api/openai-stt.ts
@@ -2,6 +2,7 @@ import OpenAI from 'openai';
import { OpenAISTTPayload } from '@/core';
+import cors from '../lib/cors';
import { createOpenaiAudioTranscriptions } from '../src/server/createOpenaiAudioTranscriptions';
export const config = {
@@ -21,9 +22,12 @@ export default async (req: Request) => {
const openai = new OpenAI({ apiKey: OPENAI_API_KEY, baseURL: OPENAI_BASE_URL });
const res = await createOpenaiAudioTranscriptions({ openai, payload });
- return new Response(JSON.stringify(res), {
- headers: {
- 'content-type': 'application/json;charset=UTF-8',
- },
- });
+ return cors(
+ req,
+ new Response(JSON.stringify(res), {
+ headers: {
+ 'content-type': 'application/json;charset=UTF-8',
+ },
+ }),
+ );
};
diff --git a/api/openai-tts.ts b/api/openai-tts.ts
index 5d627ba..5e10734 100644
--- a/api/openai-tts.ts
+++ b/api/openai-tts.ts
@@ -2,6 +2,7 @@ import OpenAI from 'openai';
import { OpenAITTSPayload } from '@/core';
+import cors from '../lib/cors';
import { createOpenaiAudioSpeech } from '../src/server/createOpenaiAudioSpeech';
export const config = {
@@ -10,6 +11,7 @@ export const config = {
export default async (req: Request) => {
if (req.method !== 'POST') return new Response('Method Not Allowed', { status: 405 });
+
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL;
@@ -19,5 +21,7 @@ export default async (req: Request) => {
const openai = new OpenAI({ apiKey: OPENAI_API_KEY, baseURL: OPENAI_BASE_URL });
- return createOpenaiAudioSpeech({ openai, payload });
+ const res = await createOpenaiAudioSpeech({ openai, payload });
+
+ return cors(req, res);
};
diff --git a/docs/STT.tsx b/docs/STT.tsx
new file mode 100644
index 0000000..ea65f88
--- /dev/null
+++ b/docs/STT.tsx
@@ -0,0 +1,25 @@
+import { Icon } from '@lobehub/ui';
+import { Button, Input } from 'antd';
+import { Mic, StopCircle } from 'lucide-react';
+import { Flexbox } from 'react-layout-kit';
+
+import { useSpeechRecognition } from '@/react';
+
+export default () => {
+ const { text, start, stop, isLoading, formattedTime, url } = useSpeechRecognition('zh-CN');
+ return (
+
+ {isLoading ? (
+ } onClick={stop}>
+ Stop {formattedTime}
+
+ ) : (
+ } onClick={start} type={'primary'}>
+ Recognition
+
+ )}
+
+ {url && }
+
+ );
+};
diff --git a/docs/TTS.tsx b/docs/TTS.tsx
new file mode 100644
index 0000000..0a0b2a8
--- /dev/null
+++ b/docs/TTS.tsx
@@ -0,0 +1,34 @@
+import { Icon } from '@lobehub/ui';
+import { Button, Input } from 'antd';
+import { Volume2 } from 'lucide-react';
+import { Flexbox } from 'react-layout-kit';
+
+import { AudioPlayer, useEdgeSpeech } from '@/react';
+
+export default () => {
+ const { setText, isGlobalLoading, start, stop, audio } = useEdgeSpeech('Edge Speech Example', {
+ api: {},
+ options: {
+ voice: 'zh-CN-YunxiaNeural',
+ },
+ });
+
+ return (
+
+ {isGlobalLoading ? (
+
+ ) : (
+ } onClick={start} type={'primary'}>
+ Speak
+
+ )}
+ setText(e.target.value)}
+ />
+
+
+ );
+};
diff --git a/docs/api-reference/edge-speech-tts.md b/docs/api-reference/edge-speech-tts.md
index 4fb3a39..510c961 100644
--- a/docs/api-reference/edge-speech-tts.md
+++ b/docs/api-reference/edge-speech-tts.md
@@ -1,10 +1,12 @@
---
-group: TTS
+group: API Reference
title: EdgeSpeechTTS
apiHeader:
pkg: '@lobehub/tts'
---
+## Introduction
+
`EdgeSpeechTTS` is a class for text-to-speech conversion based on Edge Speech Service.
This class supports converting text to speech and provides a set of methods to retrieve voice options and create speech synthesis requests.
diff --git a/docs/api-reference/edge-speech-tts.zh-CN.md b/docs/api-reference/edge-speech-tts.zh-CN.md
index 322bf32..5af48e8 100644
--- a/docs/api-reference/edge-speech-tts.zh-CN.md
+++ b/docs/api-reference/edge-speech-tts.zh-CN.md
@@ -1,10 +1,12 @@
---
-group: TTS
+group: API Reference
title: EdgeSpeechTTS
apiHeader:
pkg: '@lobehub/tts'
---
+## 介绍
+
`EdgeSpeechTTS` 是一个基于 Edge 语音服务的文本转语音方法类。
该类支持将文本转换为语音,并提供了一系列方法来获取语音选项,创建语音合成请求。
diff --git a/docs/api-reference/index.md b/docs/api-reference/index.md
deleted file mode 100644
index 0d2c37b..0000000
--- a/docs/api-reference/index.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: API Reference
-nav:
- title: API
- order: 10
----
-
-# API Reference Guide
-
-## TTS
-
-- [EdgeSpeechTTS](./edge-speech-tts.en-US.md)
-- [MicrosoftSpeechTTS](microsoft-speech-tts.en-US.md)
-- [OpenaiTTS](openai-tts.en-US.md)
diff --git a/docs/api-reference/index.zh-CN.md b/docs/api-reference/index.zh-CN.md
deleted file mode 100644
index 60baeb4..0000000
--- a/docs/api-reference/index.zh-CN.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: API Reference
-nav:
- title: API
- order: 10
----
-
-# API 参考指南
-
-## TTS
-
-- [EdgeSpeechTTS](./edge-speech-tts.zh-CN.md)
-- [MicrosoftSpeechTTS](microsoft-speech-tts.zh-CN.md)
-- [OpenaiTTS](openai-tts.zh-CN.md)
diff --git a/docs/api-reference/microsoft-speech-tts.md b/docs/api-reference/microsoft-speech-tts.md
index bcb251a..50f9636 100644
--- a/docs/api-reference/microsoft-speech-tts.md
+++ b/docs/api-reference/microsoft-speech-tts.md
@@ -1,10 +1,12 @@
---
-group: TTS
+group: API Reference
title: MicrosoftSpeechTTS
apiHeader:
pkg: '@lobehub/tts'
---
+## Introduction
+
`MicrosoftSpeechTTS` is a class for text-to-speech using Microsoft Speech Services.
This class supports converting text to speech and provides a series of methods to retrieve speech options and create speech synthesis requests.
@@ -23,7 +25,6 @@ constructor(options: MicrosoftSpeechAPI): MicrosoftSpeechTTS
```js
// index.js
-// index.js
import { MicrosoftSpeechTTS } from '@lobehub/tts';
// get MicrosoftSpeechTTS instance
diff --git a/docs/api-reference/microsoft-speech-tts.zh-CN.md b/docs/api-reference/microsoft-speech-tts.zh-CN.md
index 96f8912..a41e922 100644
--- a/docs/api-reference/microsoft-speech-tts.zh-CN.md
+++ b/docs/api-reference/microsoft-speech-tts.zh-CN.md
@@ -1,10 +1,12 @@
---
-group: TTS
+group: API Reference
title: MicrosoftSpeechTTS
apiHeader:
pkg: '@lobehub/tts'
---
+## 介绍
+
`MicrosoftSpeechTTS` 是一个基于 Microsoft 语音服务的文本转语音方法类。
该类支持将文本转换为语音,并提供了一系列方法来获取语音选项,创建语音合成请求。
diff --git a/docs/api-reference/openai-tts.md b/docs/api-reference/openai-tts.md
index 95c24bc..db4f525 100644
--- a/docs/api-reference/openai-tts.md
+++ b/docs/api-reference/openai-tts.md
@@ -1,10 +1,12 @@
---
-group: TTS
+group: API Reference
title: OpenAITTS
apiHeader:
pkg: '@lobehub/tts'
---
+## Introduction
+
`OpenAITTS` is a class for text-to-speech using the OpenAI voice service.
This class supports converting text into speech and provides a set of methods for getting voice options and creating speech synthesis requests.
diff --git a/docs/api-reference/openai-tts.zh-CN.md b/docs/api-reference/openai-tts.zh-CN.md
index c9b31b7..d23b28e 100644
--- a/docs/api-reference/openai-tts.zh-CN.md
+++ b/docs/api-reference/openai-tts.zh-CN.md
@@ -1,10 +1,12 @@
---
-group: TTS
+group: API Reference
title: OpenAITTS
apiHeader:
pkg: '@lobehub/tts'
---
+## 介绍
+
`OpenAITTS` 是一个基于 OpenAI 语音服务的文本转语音方法类。
该类支持将文本转换为语音,并提供了一系列方法来获取语音选项,创建语音合成请求。
diff --git a/docs/index.tsx b/docs/index.tsx
index 4504e2e..df9ea7e 100644
--- a/docs/index.tsx
+++ b/docs/index.tsx
@@ -1,11 +1,25 @@
-import { Snippet } from '@lobehub/ui';
-import { Center } from 'react-layout-kit';
+import { Grid, Snippet } from '@lobehub/ui';
+import { Card } from 'antd';
+import { Center, Flexbox } from 'react-layout-kit';
+
+import STT from './STT';
+import TTS from './TTS';
export default () => {
return (
-
- To install Lobe TTS, run the following command:
- {'$ bun add @lobehub/tts'}
-
+
+
+ To install Lobe TTS, run the following command:
+ {'$ bun add @lobehub/tts'}
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/lib/cors.ts b/lib/cors.ts
new file mode 100644
index 0000000..4b57f45
--- /dev/null
+++ b/lib/cors.ts
@@ -0,0 +1,140 @@
+/**
+ * Multi purpose CORS lib.
+ * Note: Based on the `cors` package in npm but using only
+ * web APIs. Feel free to use it in your own projects.
+ */
+
+type StaticOrigin = boolean | string | RegExp | (boolean | string | RegExp)[];
+
+type OriginFn = (origin: string | undefined, req: Request) => StaticOrigin | Promise;
+
+interface CorsOptions {
+ allowedHeaders?: string | string[];
+ credentials?: boolean;
+ exposedHeaders?: string | string[];
+ maxAge?: number;
+ methods?: string | string[];
+ optionsSuccessStatus?: number;
+ origin?: StaticOrigin | OriginFn;
+ preflightContinue?: boolean;
+}
+
+const defaultOptions: CorsOptions = {
+ methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
+ optionsSuccessStatus: 204,
+ origin: '*',
+ preflightContinue: false,
+};
+
+function isOriginAllowed(origin: string, allowed: StaticOrigin): boolean {
+ return Array.isArray(allowed)
+ ? allowed.some((o) => isOriginAllowed(origin, o))
+ : typeof allowed === 'string'
+ ? origin === allowed
+ : allowed instanceof RegExp
+ ? allowed.test(origin)
+ : !!allowed;
+}
+
+function getOriginHeaders(reqOrigin: string | undefined, origin: StaticOrigin) {
+ const headers = new Headers();
+
+ if (origin === '*') {
+ // Allow any origin
+ headers.set('Access-Control-Allow-Origin', '*');
+ } else if (typeof origin === 'string') {
+ // Fixed origin
+ headers.set('Access-Control-Allow-Origin', origin);
+ headers.append('Vary', 'Origin');
+ } else {
+ const allowed = isOriginAllowed(reqOrigin ?? '', origin);
+
+ if (allowed && reqOrigin) {
+ headers.set('Access-Control-Allow-Origin', reqOrigin);
+ }
+ headers.append('Vary', 'Origin');
+ }
+
+ return headers;
+}
+
+// originHeadersFromReq
+
+async function originHeadersFromReq(req: Request, origin: StaticOrigin | OriginFn) {
+ const reqOrigin = req.headers.get('Origin') || undefined;
+ const value = typeof origin === 'function' ? await origin(reqOrigin, req) : origin;
+
+ if (!value) return;
+ return getOriginHeaders(reqOrigin, value);
+}
+
+function getAllowedHeaders(req: Request, allowed?: string | string[]) {
+ const headers = new Headers();
+
+ if (!allowed) {
+ allowed = req.headers.get('Access-Control-Request-Headers')!;
+ headers.append('Vary', 'Access-Control-Request-Headers');
+ } else if (Array.isArray(allowed)) {
+ // If the allowed headers is an array, turn it into a string
+ allowed = allowed.join(',');
+ }
+ if (allowed) {
+ headers.set('Access-Control-Allow-Headers', allowed);
+ }
+
+ return headers;
+}
+
+export default async function cors(req: Request, res: Response, options?: CorsOptions) {
+ const opts = { ...defaultOptions, ...options };
+ const { headers } = res;
+ const originHeaders = await originHeadersFromReq(req, opts.origin ?? false);
+ const mergeHeaders = (v: string, k: string) => {
+ if (k === 'Vary') headers.append(k, v);
+ else headers.set(k, v);
+ };
+
+ // If there's no origin we won't touch the response
+ if (!originHeaders) return res;
+
+ originHeaders.forEach(mergeHeaders);
+
+ if (opts.credentials) {
+ headers.set('Access-Control-Allow-Credentials', 'true');
+ }
+
+ const exposed = Array.isArray(opts.exposedHeaders)
+ ? opts.exposedHeaders.join(',')
+ : opts.exposedHeaders;
+
+ if (exposed) {
+ headers.set('Access-Control-Expose-Headers', exposed);
+ }
+
+ // Handle the preflight request
+ if (req.method === 'OPTIONS') {
+ if (opts.methods) {
+ const methods = Array.isArray(opts.methods) ? opts.methods.join(',') : opts.methods;
+
+ headers.set('Access-Control-Allow-Methods', methods);
+ }
+
+ getAllowedHeaders(req, opts.allowedHeaders).forEach(mergeHeaders);
+
+ if (typeof opts.maxAge === 'number') {
+ headers.set('Access-Control-Max-Age', String(opts.maxAge));
+ }
+
+ if (opts.preflightContinue) return res;
+
+ headers.set('Content-Length', '0');
+ return new Response(null, { headers, status: opts.optionsSuccessStatus });
+ }
+
+ // If we got here, it's a normal request
+ return res;
+}
+
+export function initCors(options?: CorsOptions) {
+ return (req: Request, res: Response) => cors(req, res, options);
+}
diff --git a/package.json b/package.json
index 28e414a..508aaf7 100644
--- a/package.json
+++ b/package.json
@@ -45,20 +45,19 @@
"build": "father build",
"ci": "npm run lint && npm run type-check && npm run doctor",
"dev": "father dev",
- "docs:build": "npm run setup && npm run build && dumi build",
+ "docs:build": "npm run build && dumi build",
"docs:build-analyze": "ANALYZE=1 dumi build",
- "docs:dev": "npm run setup && dumi dev",
+ "docs:dev": "concurrently -n docs,api -c blue,yellow \"dumi dev\" \"vercel dev -y\"",
"doctor": "father doctor",
"i18n-md": "lobe-i18n md",
"lint": "eslint \"{src,api,lib}/**/*.{js,jsx,ts,tsx}\" --fix",
"lint:md": "remark . --quiet --frail --output",
"lint:style": "stylelint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
- "prepare": "husky install",
+ "prepare": "husky install && npm run setup",
"prepublishOnly": "npm run build",
"prettier": "prettier -c --write \"**/**\"",
"release": "semantic-release",
"setup": "dumi setup",
- "start": "vercel dev",
"type-check": "tsc --noEmit"
},
"lint-staged": {
@@ -90,10 +89,10 @@
"not ie <= 10"
],
"dependencies": {
- "@babel/runtime": "^7.24.7",
+ "@babel/runtime": "^7.26.0",
"lodash-es": "^4.17.21",
- "query-string": "^9.0.0",
- "react-error-boundary": "^4.0.13",
+ "query-string": "^9.1.1",
+ "react-error-boundary": "^4.1.2",
"remark-gfm": "^3.0.1",
"remark-parse": "^10.0.2",
"swr": "^2.2.5",
@@ -103,30 +102,31 @@
"uuid": "^10.0.0"
},
"devDependencies": {
- "@commitlint/cli": "^19.3.0",
- "@lobehub/i18n-cli": "^1.18.1",
- "@lobehub/lint": "^1.24.3",
- "@lobehub/ui": "^1.146.4",
+ "@commitlint/cli": "^19.6.0",
+ "@lobehub/i18n-cli": "^1.20.0",
+ "@lobehub/lint": "^1.24.4",
+ "@lobehub/ui": "^1.153.0",
"@types/lodash-es": "^4.17.12",
- "@types/node": "^20.14.9",
- "@types/react": "^18.3.3",
- "@types/react-dom": "^18.3.0",
+ "@types/node": "^20.17.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
"@types/uuid": "^9.0.8",
- "@vercel/node": "^3.2.0",
- "commitlint": "^19.3.0",
- "dumi": "2.2.17",
- "dumi-theme-lobehub": "^1.8.1",
- "eslint": "^8.57.0",
- "father": "4.3.1",
- "husky": "^9.0.11",
- "lint-staged": "^15.2.7",
- "prettier": "^3.3.2",
+ "@vercel/node": "^3.2.26",
+ "commitlint": "^19.6.0",
+ "concurrently": "^9.0.1",
+ "dumi": "^2.4.14",
+ "dumi-theme-lobehub": "^1.8.3",
+ "eslint": "^8.57.1",
+ "father": "^4.5.1",
+ "husky": "^9.1.7",
+ "lint-staged": "^15.2.10",
+ "prettier": "^3.3.3",
"remark": "^14.0.3",
"remark-cli": "^11.0.0",
"semantic-release": "^21.1.2",
"stylelint": "^15.11.0",
- "tsx": "^4.16.0",
- "typescript": "^5.5.2",
+ "tsx": "^4.19.2",
+ "typescript": "^5.6.3",
"vercel": "^28.20.0"
},
"peerDependencies": {
diff --git a/src/core/MicrosoftSpeechTTS/createMicrosoftSpeech.ts b/src/core/MicrosoftSpeechTTS/createMicrosoftSpeech.ts
index 36a9693..5847867 100644
--- a/src/core/MicrosoftSpeechTTS/createMicrosoftSpeech.ts
+++ b/src/core/MicrosoftSpeechTTS/createMicrosoftSpeech.ts
@@ -49,7 +49,7 @@ export const createMicrosoftSpeech = async (
SpeakTriggerSource: 'AccTuningPagePlayButton',
},
ssml: genSSML(input, options),
- ttsAudioFormat: 'audio-24khz-160kbitrate-mono-mp3',
+ ttsAudioFormat: 'audio-24khz-48kbitrate-mono-mp3',
});
return fetch(proxyUrl ? proxyUrl : MICROSOFT_SPEECH_URL, {
diff --git a/src/react/AudioPlayer/index.md b/src/react/AudioPlayer/index.md
index 2e6aa53..a54eabf 100644
--- a/src/react/AudioPlayer/index.md
+++ b/src/react/AudioPlayer/index.md
@@ -2,8 +2,10 @@
nav: Components
group: UI
title: AudioPlayer
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## default
+## Default
diff --git a/src/react/AudioPlayer/index.zh-CN.md b/src/react/AudioPlayer/index.zh-CN.md
deleted file mode 100644
index 515b04a..0000000
--- a/src/react/AudioPlayer/index.zh-CN.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: AudioPlayer
-group: UI
-nav: 组件
-apiHeader:
- pkg: '@lobehub/tts/react'
----
-
-## default
-
-
diff --git a/src/react/AudioVisualizer/index.md b/src/react/AudioVisualizer/index.md
index 2f70b44..6ff54cc 100644
--- a/src/react/AudioVisualizer/index.md
+++ b/src/react/AudioVisualizer/index.md
@@ -2,8 +2,10 @@
nav: Components
group: UI
title: AudioVisualizer
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## default
+## Default
diff --git a/src/react/AudioVisualizer/index.zh-CN.md b/src/react/AudioVisualizer/index.zh-CN.md
deleted file mode 100644
index 04c808d..0000000
--- a/src/react/AudioVisualizer/index.zh-CN.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: AudioVisualizer
-group: UI
-nav: 组件
-apiHeader:
- pkg: '@lobehub/tts/react'
----
-
-## default
-
-
diff --git a/src/react/useAudioRecorder/index.md b/src/react/useAudioRecorder/index.md
index 6ced734..f74512b 100644
--- a/src/react/useAudioRecorder/index.md
+++ b/src/react/useAudioRecorder/index.md
@@ -2,8 +2,10 @@
nav: Components
group: STT
title: useAudioRecorder
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks
diff --git a/src/react/useEdgeSpeech/index.md b/src/react/useEdgeSpeech/index.md
index 74698df..b63bc78 100644
--- a/src/react/useEdgeSpeech/index.md
+++ b/src/react/useEdgeSpeech/index.md
@@ -2,8 +2,10 @@
nav: Components
group: TTS
title: useEdgeSpeech
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks
diff --git a/src/react/useMicrosoftSpeech/index.md b/src/react/useMicrosoftSpeech/index.md
index 6f77e91..e7505dc 100644
--- a/src/react/useMicrosoftSpeech/index.md
+++ b/src/react/useMicrosoftSpeech/index.md
@@ -2,9 +2,11 @@
nav: Components
group: TTS
title: useMicrosoftSpeech
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks
- ENV: `MICROSOFT_SPEECH_BACKEND_URL`
diff --git a/src/react/useOpenAISTT/index.md b/src/react/useOpenAISTT/index.md
index 00d46af..b77c96c 100644
--- a/src/react/useOpenAISTT/index.md
+++ b/src/react/useOpenAISTT/index.md
@@ -2,9 +2,11 @@
nav: Components
group: STT
title: useOpenAISTT
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks
- ENV: `OPENAI_API_KEY` `OPENAI_BASE_URL`
diff --git a/src/react/useOpenAITTS/index.md b/src/react/useOpenAITTS/index.md
index 4c5a571..bdbb7ec 100644
--- a/src/react/useOpenAITTS/index.md
+++ b/src/react/useOpenAITTS/index.md
@@ -2,9 +2,11 @@
nav: Components
group: TTS
title: useOpenAITTS
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks
- ENV: `OPENAI_API_KEY` `OPENAI_BASE_URL`
diff --git a/src/react/useSpeechRecognition/index.md b/src/react/useSpeechRecognition/index.md
index c8bc7c2..ad7a035 100644
--- a/src/react/useSpeechRecognition/index.md
+++ b/src/react/useSpeechRecognition/index.md
@@ -2,9 +2,11 @@
nav: Components
group: STT
title: useSpeechRecognition
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks
diff --git a/src/react/useSpeechSynthes/index.md b/src/react/useSpeechSynthes/index.md
index 26427a0..65dc31e 100644
--- a/src/react/useSpeechSynthes/index.md
+++ b/src/react/useSpeechSynthes/index.md
@@ -2,8 +2,10 @@
nav: Components
group: TTS
title: useSpeechSynthes
+apiHeader:
+ pkg: '@lobehub/tts/react'
---
-## hooks
+## React Hooks