support resemble tts (#559)

* support resemble tts

* wip
This commit is contained in:
Hoan Luu Huu
2025-08-13 19:17:18 +07:00
committed by GitHub
parent 9dd9cf867a
commit f1f8a7d808
5 changed files with 88 additions and 1 deletions

View File

@@ -440,6 +440,8 @@ export interface SpeechCredential {
deepgram_stt_use_tls: number; deepgram_stt_use_tls: number;
speechmatics_stt_uri: null | string; speechmatics_stt_uri: null | string;
playht_tts_uri: null | string; playht_tts_uri: null | string;
resemble_tts_uri: null | string;
resemble_tts_use_tls: number;
} }
export interface Alert { export interface Alert {

View File

@@ -37,6 +37,7 @@ import {
VENDOR_OPENAI, VENDOR_OPENAI,
VENDOR_INWORLD, VENDOR_INWORLD,
VENDOR_DEEPGRAM_RIVER, VENDOR_DEEPGRAM_RIVER,
VENDOR_RESEMBLE,
} from "src/vendor"; } from "src/vendor";
import { import {
LabelOptions, LabelOptions,
@@ -587,6 +588,7 @@ export const SpeechProviderSelection = ({
vendor.value != VENDOR_WELLSAID && vendor.value != VENDOR_WELLSAID &&
vendor.value != VENDOR_ELEVENLABS && vendor.value != VENDOR_ELEVENLABS &&
vendor.value != VENDOR_WHISPER && vendor.value != VENDOR_WHISPER &&
vendor.value !== VENDOR_RESEMBLE &&
vendor.value !== VENDOR_CUSTOM, vendor.value !== VENDOR_CUSTOM,
)} )}
onChange={(e) => { onChange={(e) => {

View File

@@ -54,6 +54,7 @@ import {
VENDOR_OPENAI, VENDOR_OPENAI,
VENDOR_INWORLD, VENDOR_INWORLD,
VENDOR_DEEPGRAM_RIVER, VENDOR_DEEPGRAM_RIVER,
VENDOR_RESEMBLE,
} from "src/vendor"; } from "src/vendor";
import { MSG_REQUIRED_FIELDS } from "src/constants"; import { MSG_REQUIRED_FIELDS } from "src/constants";
import { import {
@@ -207,6 +208,12 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
const [tmpPlayhtTtsUri, setTmpPlayhtTtsUri] = useState(""); const [tmpPlayhtTtsUri, setTmpPlayhtTtsUri] = useState("");
const [initialPlayhtOnpremCheck, setInitialPlayhtOnpremCheck] = const [initialPlayhtOnpremCheck, setInitialPlayhtOnpremCheck] =
useState(false); useState(false);
const [resembleTtsUri, setResembleTtsUri] = useState("");
const [tmpResembleTtsUri, setTmpResembleTtsUri] = useState("");
const [initialResembleOnpremCheck, setInitialResembleOnpremCheck] =
useState(false);
const [resembleTtsUseTls, setResembleTtsUseTls] = useState(false);
const [tmpResembleTtsUseTls, setTmpResembleTtsUseTls] = useState(false);
const handleFile = (file: File) => { const handleFile = (file: File) => {
const handleError = () => { const handleError = () => {
setGoogleServiceKey(null); setGoogleServiceKey(null);
@@ -481,6 +488,10 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
...(vendor === VENDOR_PLAYHT && { ...(vendor === VENDOR_PLAYHT && {
playht_tts_uri: playhtTtsUri || null, playht_tts_uri: playhtTtsUri || null,
}), }),
...(vendor === VENDOR_RESEMBLE && {
resemble_tts_uri: resembleTtsUri || null,
resemble_tts_use_tls: resembleTtsUseTls ? 1 : 0,
}),
}; };
if (credential && credential.data) { if (credential && credential.data) {
@@ -531,6 +542,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
vendor === VENDOR_WHISPER || vendor === VENDOR_WHISPER ||
vendor === VENDOR_CARTESIA || vendor === VENDOR_CARTESIA ||
vendor === VENDOR_OPENAI || vendor === VENDOR_OPENAI ||
vendor === VENDOR_RESEMBLE ||
vendor === VENDOR_DEEPGRAM_RIVER vendor === VENDOR_DEEPGRAM_RIVER
? apiKey ? apiKey
: null, : null,
@@ -798,6 +810,9 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
if (credential?.data?.playht_tts_uri) { if (credential?.data?.playht_tts_uri) {
setPlayhtTtsUri(credential.data.playht_tts_uri); setPlayhtTtsUri(credential.data.playht_tts_uri);
} }
if (credential?.data?.resemble_tts_uri) {
setResembleTtsUri(credential.data.resemble_tts_uri);
}
} }
if (credential?.data?.options) { if (credential?.data?.options) {
setOptions(credential.data.options); setOptions(credential.data.options);
@@ -867,6 +882,15 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
setSpeechmaticsEndpoint(credential.data.speechmatics_stt_uri); setSpeechmaticsEndpoint(credential.data.speechmatics_stt_uri);
} }
setInitialPlayhtOnpremCheck(hasValue(credential?.data?.playht_tts_uri)); setInitialPlayhtOnpremCheck(hasValue(credential?.data?.playht_tts_uri));
setInitialResembleOnpremCheck(hasValue(credential?.data?.resemble_tts_uri));
if (credential?.data?.resemble_tts_use_tls) {
setResembleTtsUseTls(
credential?.data?.resemble_tts_use_tls > 0 ? true : false,
);
setTmpResembleTtsUseTls(
credential?.data?.resemble_tts_use_tls > 0 ? true : false,
);
}
}, [credential]); }, [credential]);
const updateCustomVoices = ( const updateCustomVoices = (
@@ -1005,6 +1029,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
vendor !== VENDOR_PLAYHT && vendor !== VENDOR_PLAYHT &&
vendor !== VENDOR_RIMELABS && vendor !== VENDOR_RIMELABS &&
vendor !== VENDOR_INWORLD && vendor !== VENDOR_INWORLD &&
vendor !== VENDOR_RESEMBLE &&
vendor !== VENDOR_ELEVENLABS && ( vendor !== VENDOR_ELEVENLABS && (
<label htmlFor="use_for_stt" className="chk"> <label htmlFor="use_for_stt" className="chk">
<input <input
@@ -1744,6 +1769,57 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
</fieldset> </fieldset>
)} )}
{vendor === VENDOR_RESEMBLE && (
<fieldset>
<Checkzone
disabled={hasValue(credential)}
hidden
name="use_on-prem_resemble_container"
label="Use on-prem Resemble container"
initialCheck={initialResembleOnpremCheck}
handleChecked={(e) => {
setInitialResembleOnpremCheck(e.target.checked);
if (e.target.checked) {
if (tmpResembleTtsUri) {
setResembleTtsUri(tmpResembleTtsUri);
}
if (tmpResembleTtsUseTls) {
setResembleTtsUseTls(tmpResembleTtsUseTls);
}
} else {
setTmpResembleTtsUri(resembleTtsUri);
setResembleTtsUri("");
setTmpResembleTtsUseTls(resembleTtsUseTls);
setResembleTtsUseTls(false);
}
}}
>
<label htmlFor="resemble_uri_for_tts">
TTS Container URI<span>*</span>
</label>
<input
id="resemble_uri_for_tts"
required
type="text"
name="resemble_uri_for_tts"
placeholder=""
value={resembleTtsUri}
onChange={(e) => setResembleTtsUri(e.target.value)}
/>
<label htmlFor="resemble_stt_use_tls" className="chk">
<input
id="resemble_stt_use_tls"
name="resemble_stt_use_tls"
type="checkbox"
onChange={(e) => setResembleTtsUseTls(e.target.checked)}
defaultChecked={resembleTtsUseTls}
/>
<div>Use TLS</div>
</label>
</Checkzone>
</fieldset>
)}
{(vendor === VENDOR_WELLSAID || {(vendor === VENDOR_WELLSAID ||
vendor === VENDOR_ASSEMBLYAI || vendor === VENDOR_ASSEMBLYAI ||
vendor === VENDOR_VOXIST || vendor === VENDOR_VOXIST ||
@@ -1755,6 +1831,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
vendor === VENDOR_CARTESIA || vendor === VENDOR_CARTESIA ||
vendor === VENDOR_OPENAI || vendor === VENDOR_OPENAI ||
vendor === VENDOR_DEEPGRAM_RIVER || vendor === VENDOR_DEEPGRAM_RIVER ||
vendor === VENDOR_RESEMBLE ||
vendor === VENDOR_SPEECHMATICS) && ( vendor === VENDOR_SPEECHMATICS) && (
<fieldset> <fieldset>
<label htmlFor={`${vendor}_apikey`}> <label htmlFor={`${vendor}_apikey`}>

View File

@@ -29,6 +29,7 @@ export const VENDOR_INWORLD = "inworld";
export const VENDOR_VERBIO = "verbio"; export const VENDOR_VERBIO = "verbio";
export const VENDOR_CARTESIA = "cartesia"; export const VENDOR_CARTESIA = "cartesia";
export const VENDOR_OPENAI = "openai"; export const VENDOR_OPENAI = "openai";
export const VENDOR_RESEMBLE = "resemble";
export const vendors: VendorOptions[] = [ export const vendors: VendorOptions[] = [
{ {
@@ -123,6 +124,10 @@ export const vendors: VendorOptions[] = [
name: "OpenAI", name: "OpenAI",
value: VENDOR_OPENAI, value: VENDOR_OPENAI,
}, },
{
name: "Resemble",
value: VENDOR_RESEMBLE,
},
].sort((a, b) => a.name.localeCompare(b.name)) as VendorOptions[]; ].sort((a, b) => a.name.localeCompare(b.name)) as VendorOptions[];
export const AWS_CREDENTIAL_ACCESS_KEY = "access_key"; export const AWS_CREDENTIAL_ACCESS_KEY = "access_key";

3
src/vendor/types.ts vendored
View File

@@ -21,7 +21,8 @@ export type Vendor =
| "inworld" | "inworld"
| "verbio" | "verbio"
| "openai" | "openai"
| "Cartesia"; | "Cartesia"
| "Resemble";
export interface VendorOptions { export interface VendorOptions {
name: Vendor; name: Vendor;