Skip to content

Commit

Permalink
🐛 fix: Fix api
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Nov 16, 2023
1 parent da2eee2 commit 0114d30
Show file tree
Hide file tree
Showing 36 changed files with 185 additions and 150 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ This project provides some additional configuration items set with environment v
| Environment Variable | Description | Default |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| `OPENAI_API_KEY` | This is the API key you apply on the OpenAI account page | `sk-xxxxxx...xxxxxx` |
| `OPENAI_PROXY_URL` | If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL | `https://api.openai.com/v1` |
| `OPENAI_BASE_URL` | If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL | `https://api.openai.com/v1` |

<div align="right">

Expand Down
4 changes: 2 additions & 2 deletions api/openai-stt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ 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_PROXY_URL = process.env.OPENAI_PROXY_URL;
const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL;

if (!OPENAI_API_KEY) return new Response('OPENAI_API_KEY is not set', { status: 500 });

const payload = (await req.json()) as OpenAISTTPayload;

const openai = new OpenAI({ apiKey: OPENAI_API_KEY, baseURL: OPENAI_PROXY_URL });
const openai = new OpenAI({ apiKey: OPENAI_API_KEY, baseURL: OPENAI_BASE_URL });
const res = await createOpenaiAudioTranscriptions({ openai, payload });

return new Response(JSON.stringify(res), {
Expand Down
4 changes: 2 additions & 2 deletions api/openai-tts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ 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_PROXY_URL = process.env.OPENAI_PROXY_URL;
const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL;

if (!OPENAI_API_KEY) return new Response('OPENAI_API_KEY is not set', { status: 500 });

const payload = (await req.json()) as OpenAITTSPayload;

const openai = new OpenAI({ apiKey: OPENAI_API_KEY, baseURL: OPENAI_PROXY_URL });
const openai = new OpenAI({ apiKey: OPENAI_API_KEY, baseURL: OPENAI_BASE_URL });

return createOpenaiAudioSpeech({ openai, payload });
};
2 changes: 1 addition & 1 deletion src/core/EdgeSpeechTTS/createEdgeSpeech.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import qs from 'query-string';
import { v4 as uuidv4 } from 'uuid';

import { SsmlOptions, genSSML } from '../utils/genSSML';
import { type SsmlOptions, genSSML } from '../utils/genSSML';
import { genSendContent } from '../utils/genSendContent';
import { getHeadersAndData } from '../utils/getHeadersAndData';

Expand Down
26 changes: 10 additions & 16 deletions src/core/EdgeSpeechTTS/index.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
import edgeVoiceList from '@/core/EdgeSpeechTTS/edgeVoiceList';
import voiceName from '@/core/data/voiceList';
import { arrayBufferConvert } from '@/core/utils/arrayBufferConvert';
import { SsmlOptions } from '@/core/utils/genSSML';
import { getVoiceLocaleOptions } from '@/core/utils/getVoiceList';

import { createEdgeSpeech } from './createEdgeSpeech';
import { type EdgeSpeechPayload, createEdgeSpeech } from './createEdgeSpeech';
import { getEdgeVoiceOptions } from './options';

export interface EdgeSpeechPayload {
/**
* @title 语音合成的文本
*/
input: string;
/**
* @title SSML 语音合成的配置
*/
options: Pick<SsmlOptions, 'voice'>;
export type { EdgeSpeechPayload } from './createEdgeSpeech';

export interface EdgeSpeechAPI {
backendURL?: string;
}

export class EdgeSpeechTTS {
private locale?: string;
private BASE_URL: string | undefined;
private BACKEND_URL: string | undefined;

constructor({ baseURL, locale }: { baseURL?: string; locale?: string } = {}) {
constructor({ backendURL, locale }: EdgeSpeechAPI & { locale?: string } = {}) {
this.locale = locale;
this.BASE_URL = baseURL;
this.BACKEND_URL = backendURL;
}

get voiceOptions() {
Expand All @@ -37,8 +31,8 @@ export class EdgeSpeechTTS {
static createRequest = createEdgeSpeech;

private fetch = async (payload: EdgeSpeechPayload) => {
const response = await (this.BASE_URL
? fetch(this.BASE_URL, { body: JSON.stringify(payload), method: 'POST' })
const response = await (this.BACKEND_URL
? fetch(this.BACKEND_URL, { body: JSON.stringify(payload), method: 'POST' })
: createEdgeSpeech({ payload }));

if (!response.ok) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/MicrosoftSpeechTTS/createMicrosoftSpeech.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { v4 as uuidv4 } from 'uuid';

import { SsmlOptions, genSSML } from '../utils/genSSML';
import { type SsmlOptions, genSSML } from '../utils/genSSML';

const MICROSOFT_SPEECH_URL =
'https://southeastasia.api.speech.microsoft.com/accfreetrial/texttospeech/acc/v3.0-beta1/vcg/speak';
Expand Down
18 changes: 12 additions & 6 deletions src/core/MicrosoftSpeechTTS/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import styleList from '@/core/data/styleList';
import voiceName from '@/core/data/voiceList';
import { arrayBufferConvert } from '@/core/utils/arrayBufferConvert';
import { getVoiceLocaleOptions } from '@/core/utils/getVoiceList';

import { MicrosoftSpeechPayload, createMicrosoftSpeech } from './createMicrosoftSpeech';
import { type MicrosoftSpeechPayload, createMicrosoftSpeech } from './createMicrosoftSpeech';
import azureVoiceList, { getAzureVoiceOptions } from './voiceList';

export type { MicrosoftSpeechPayload } from './createMicrosoftSpeech';

export interface MicrosoftSpeechAPI {
backendUrl?: string;
}

export class MicrosoftSpeechTTS {
private locale?: string;
private BASE_URL: string | undefined;
private BACKEND_URL: string | undefined;

constructor({ baseURL, locale }: { baseURL?: string; locale?: string } = {}) {
constructor({ backendUrl, locale }: MicrosoftSpeechAPI & { locale?: string } = {}) {
this.locale = locale;
this.BASE_URL = baseURL;
this.BACKEND_URL = backendUrl;
}
get voiceOptions() {
return getAzureVoiceOptions(this.locale);
Expand All @@ -24,10 +29,11 @@ export class MicrosoftSpeechTTS {

static voiceList = azureVoiceList;
static voiceName = voiceName;
static styleList = styleList;

private fetch = async (payload: MicrosoftSpeechPayload) => {
const response = await (this.BASE_URL
? fetch(this.BASE_URL, { body: JSON.stringify(payload), method: 'POST' })
const response = await (this.BACKEND_URL
? fetch(this.BACKEND_URL, { body: JSON.stringify(payload), method: 'POST' })
: createMicrosoftSpeech({ payload }));

if (!response.ok) {
Expand Down
36 changes: 24 additions & 12 deletions src/core/OpenAISTT/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export interface OpenAISTTPayload {
speech: Blob;
}

export interface OpenAISTTAPI {
apiKey?: string;
backendUrl?: string;
baseUrl?: string;
}

const genSTTBody = ({ speech, options }: OpenAISTTPayload) => {
const mineType = options?.mineType || getRecordMineType();
const filename = `${Date.now()}.${mineType.extension}`;
Expand All @@ -35,26 +41,32 @@ const genSTTBody = ({ speech, options }: OpenAISTTPayload) => {
};

export class OpenaiSTT {
private BASE_URL: string;
private OPENAI_BASE_URL: string;
private OPENAI_API_KEY: string | undefined;
private BACKEND_URL: string | undefined;

constructor({ baseUrl, apiKey }: { apiKey?: string; baseUrl?: string } = {}) {
this.BASE_URL = baseUrl || OPENAI_BASE_URL;
constructor({ baseUrl, apiKey, backendUrl }: OpenAISTTAPI = {}) {
this.OPENAI_BASE_URL = baseUrl || OPENAI_BASE_URL;
this.OPENAI_API_KEY = apiKey;
this.BACKEND_URL = backendUrl;
}

static safeRecordMineType = getRecordMineType;

fetch = async (payload: OpenAISTTPayload) => {
const url = urlJoin(this.OPENAI_BASE_URL, 'audio/speech');
return this.BACKEND_URL
? fetch(this.BACKEND_URL, { body: JSON.stringify(payload), method: 'POST' })
: fetch(url, {
body: genSTTBody(payload),
headers: new Headers({
Authorization: `Bearer ${this.OPENAI_API_KEY}`,
}),
method: 'POST',
});
};
create = async (payload: OpenAISTTPayload): Promise<string> => {
const url = urlJoin(this.BASE_URL, 'audio/speech');

const response = await fetch(url, {
body: genSTTBody(payload),
headers: new Headers({
Authorization: `Bearer ${this.OPENAI_API_KEY}`,
}),
method: 'POST',
});
const response = await this.fetch(payload);

if (!response.ok) {
throw new Error('Network response was not ok');
Expand Down
49 changes: 32 additions & 17 deletions src/core/OpenAITTS/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import urlJoin from 'url-join';

import { OPENAI_BASE_URL } from '@/core/const/api';
import { arrayBufferConvert } from '@/core/utils/arrayBufferConvert';
import { getVoiceLocaleOptions } from '@/core/utils/getVoiceList';

import openaiVoiceList, { getOpenaiVoiceOptions } from './voiceList';
import voiceList, { getOpenaiVoiceOptions } from './voiceList';

export type OpenaiVoice = 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer';

Expand All @@ -25,33 +24,49 @@ export interface OpenAITTSPayload {
};
}

export interface OpenAITTSAPI {
apiKey?: string;
backendUrl?: string;
baseUrl?: string;
}

export class OpenAITTS {
static voiceList = openaiVoiceList;
private BASE_URL: string;
private OPENAI_BASE_URL: string;
private OPENAI_API_KEY: string | undefined;
private BACKEND_URL: string | undefined;

constructor({ baseUrl, apiKey }: { apiKey?: string; baseUrl?: string } = {}) {
this.BASE_URL = baseUrl || OPENAI_BASE_URL;
constructor({ baseUrl, apiKey, backendUrl }: OpenAITTSAPI = {}) {
this.OPENAI_BASE_URL = baseUrl || OPENAI_BASE_URL;
this.OPENAI_API_KEY = apiKey;
this.BACKEND_URL = backendUrl;
}

get voiceOptions() {
return getOpenaiVoiceOptions();
}

static localeOptions = getVoiceLocaleOptions();
static voiceList = voiceList;

create = async ({ input, options }: OpenAITTSPayload): Promise<AudioBuffer> => {
const url = urlJoin(this.BASE_URL, 'audio/speech');
fetch = async (payload: OpenAITTSPayload) => {
const url = urlJoin(this.OPENAI_BASE_URL, 'audio/speech');
return this.BACKEND_URL
? fetch(this.BACKEND_URL, { body: JSON.stringify(payload), method: 'POST' })
: fetch(url, {
body: JSON.stringify({
input: payload.input,
model: payload.options?.model || 'tts-1',
voice: payload.options.voice,
}),
headers: new Headers({
'Authorization': `Bearer ${this.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
}),
method: 'POST',
});
};

const response = await fetch(url, {
body: JSON.stringify({ input, model: options?.model || 'tts-1', voice: options.voice }),
headers: new Headers({
'Authorization': `Bearer ${this.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
}),
method: 'POST',
});
create = async (payload: OpenAITTSPayload): Promise<AudioBuffer> => {
const response = await this.fetch(payload);

if (!response.ok) {
throw new Error('Network response was not ok');
Expand Down
9 changes: 0 additions & 9 deletions src/core/VoiceList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,22 @@ export class VoiceList {
constructor(locale?: string) {
this.locale = locale;
}

get speechSynthesVoiceOptions() {
return getSpeechSynthesisVoiceOptions(this.locale);
}

static allSpeechSynthesVoiceOptions = getSpeechSynthesisVoiceOptions();

get azureVoiceOptions() {
return getAzureVoiceOptions(this.locale);
}

static allAzureVoiceOptions = getAzureVoiceOptions();

get edgeVoiceOptions() {
return getEdgeVoiceOptions(this.locale);
}

static allEdgeVoiceOptions = getEdgeVoiceOptions();

get microsoftVoiceOptions() {
return getEdgeVoiceOptions(this.locale);
}

static allMicrosoftVoiceOptions = getEdgeVoiceOptions();

static openaiVoiceOptions = getOpenaiVoiceOptions();

static localeOptions = getVoiceLocaleOptions();
Expand Down
4 changes: 4 additions & 0 deletions src/core/const/api.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export const OPENAI_BASE_URL = 'https://api.openai.com/v1';
export const OPENAI_TTS_API = '/api/openai-tts';
export const OPENAI_STT_API = '/api/openai-stt';
export const EDGE_SPEECH_API = '/api/edge-speech';
export const MICROSOFT_SPEECH_API = '/api/microsoft-speech';
13 changes: 13 additions & 0 deletions src/core/data/styleList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default [
'affectionate',
'angry',
'calm',
'cheerful',
'disgruntled',
'embarrassed',
'fearful',
'general',
'gentle',
'sad',
'serious',
] as const;
20 changes: 14 additions & 6 deletions src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
export { type EdgeSpeechPayload, EdgeSpeechTTS } from '@/core/EdgeSpeechTTS';
export { type MicrosoftSpeechPayload, MicrosoftSpeechTTS } from '@/core/MicrosoftSpeechTTS';
export { OpenaiSTT, type OpenAISTTPayload } from '@/core/OpenAISTT';
export type { OpenAITTSPayload, OpenaiVoice } from '@/core/OpenAITTS';
export { OpenAITTS } from '@/core/OpenAITTS';
export { type EdgeSpeechAPI, type EdgeSpeechPayload, EdgeSpeechTTS } from '@/core/EdgeSpeechTTS';
export {
type MicrosoftSpeechAPI,
type MicrosoftSpeechPayload,
MicrosoftSpeechTTS,
} from '@/core/MicrosoftSpeechTTS';
export { OpenaiSTT, type OpenAISTTAPI, type OpenAISTTPayload } from '@/core/OpenAISTT';
export {
OpenAITTS,
type OpenAITTSAPI,
type OpenAITTSPayload,
type OpenaiVoice,
} from '@/core/OpenAITTS';
export { SpeechSynthesisTTS } from '@/core/SpeechSynthesisTTS';
export { type RecordMineType } from '@/core/utils/getRecordMineType';
export { getRecordMineType, type RecordMineType } from '@/core/utils/getRecordMineType';
export { VoiceList } from '@/core/VoiceList';
4 changes: 2 additions & 2 deletions src/react/_util/api.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const MICROSOFT_SPEECH_API_URL = '/api/microsoft-speech';
export const EDGE_SPEECH_API_URL = '/api/edge-speech';
export const MICROSOFT_SPEECH_BACKEND_URL = '/api/microsoft-speech';
export const EDGE_SPEECH_BACKEND_URL = '/api/edge-speech';
7 changes: 5 additions & 2 deletions src/react/useEdgeSpeech/demos/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Button, Input } from 'antd';
import { Volume2 } from 'lucide-react';
import { Flexbox } from 'react-layout-kit';

import { EDGE_SPEECH_API_URL } from '../../_util/api';
import { EDGE_SPEECH_BACKEND_URL } from '../../_util/api';
import { genLevaOptions } from '../../_util/leva';

const defaultText = '这是一段使用 Edge Speech 的语音演示';
Expand All @@ -15,7 +15,10 @@ export default () => {

const api: any = useControls(
{
url: EDGE_SPEECH_API_URL,
backendUrl: {
label: 'EDGE_SPEECH_BACKEND_URL',
value: EDGE_SPEECH_BACKEND_URL,
},
},
{ store },
);
Expand Down
Loading

0 comments on commit 0114d30

Please sign in to comment.