個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Voice Cloning, Voice Call, and Text-to-Speech platform. Perfect for content creators, developers, and storytellers 😉
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗gpro, gpro31, gpro38) and xAI Grok (xai), plus 6 built-in voices for callsSexyVoice.ai brings voice generation, voice cloning, and live AI calls into one app. Generate expressive speech with Gemini and Grok voices, clone your own voice, or create a character with a personality and a voice you choose. Developers can use the external API for speech generation with the same credit balance as the dashboard. See GLOSSARY.md for domain names and definitions.
achernar, kore, puck, and zephyr on Gemini 2.5, 3.1, and 3.8, Spanish role voices for Spain and Mexico, and Grok voices such as ara, carina, eve, leo, rex, sal, and zagannext-intl for global accessibility (EN/ES/DE/DA/IT/FR)apps/web/messages/*.json; getMessages() for server components, useTranslations() for client componentsapps/web - Next.js web app deployed to Vercel.apps/docs - Fumadocs docs app for docs.sexyvoice.ai.scripts - operational scripts kept outside the web app as
@sexyvoice/scripts.docs - internal engineering and operational docs.Root commands are orchestrated with Turborepo. Use package filters when you
only want one app, for example pnpm --filter @sexyvoice/web dev.
Clone the repository
git clone https://github.com/gianpaj/sexyvoice.git
cd sexyvoice
Install dependencies
pnpm install
Set up environment variables
cp apps/web/.env.example apps/web/.env.local
Fill in the required environment variables as defined in
apps/web/.env.example:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY - Safe for browser clients; database access remains controlled by RLSSUPABASE_SECRET_KEY - Server-only admin key that bypasses RLS; never expose it to clients or use a NEXT_PUBLIC_ prefixKV_REST_API_URLKV_REST_API_TOKENR2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_BUCKET_NAMER2_SPEECH_API_BUCKET_NAME - Dedicated bucket for /api/v1/speech generated audioR2_ENDPOINT - Your Cloudflare R2 endpoint URL (https://xxx.r2.cloudflarestorage.com)REPLICATE_API_TOKEN - Your Replicate API token for speech generation and one-off voice cloningFAL_KEY - Your fal.ai API key for reference audio enhancementGOOGLE_GENERATIVE_AI_API_KEY - Your Google Generative AI API key for text-to-speech and enhance text (automatically add emotion tags)XAI_API_KEY - Your xAI API key for Grok speech generation and call transcript analysisXAI_API_BASE_URL - Optional xAI REST host override for the Batch API client (default https://api.x.ai)CALL_ANALYSIS_REALTIME - Optional; set to true to analyse call transcripts inline in the webhook instead of via the xAI Batch API queue (emergency bypass)The app uses a shared banner system for both promotions and announcements:
apps/web/components/banner.tsx renders the banner UIapps/web/lib/banners/registry.ts defines supported bannersapps/web/lib/banners/resolve-banner.ts resolves the single visible banner per placementapps/web/components/banner.tsx writes dismissal cookies through
apps/web/lib/cookies.tsBanner copy is localized in apps/web/messages/*.json.
Only one banner is shown at a time, and each banner has its own dismiss cookie.
| Command | Description |
|---|---|
pnpm dev | Start all workspace dev tasks |
pnpm --filter @sexyvoice/web dev | Start only the web app dev server |
pnpm build | Build workspace apps with Turbo |
pnpm test | Run test suites |
pnpm test:db | Run Supabase pgTAP tests locally |
pnpm test:ui | Run Vitest UI for the web app |
pnpm lint | Lint web and docs code with Biome |
pnpm type-check | Run TypeScript type checking |
pnpm format | Check web and docs formatting with Biome |
pnpm check-translations | Validate all locale files have matching keys |
pnpm build:content | Build web app content layer |
pnpm clean | Check unused dependencies with Knip |
pnpm fixall | Apply Biome format, lint, and assist fixes |
Run the test suite:
pnpm test
After applying pending migrations to the local Supabase database, run the pgTAP database tests:
pnpm test:db
For the Vitest UI during development:
pnpm test:ui
Generate TypeScript types from Supabase Cloud Database:
pnpm run generate-supabase-types
Push schema changes to Supabase:
cd apps/web
supabase db push
cd ../..
Fetch database migrations:
cd apps/web
supabase migration fetch
cd ../..
Backup database and schema:
export SUPABASE_DB_URL=postgresql://postgres:[email protected]:5432/postgres
sh ./scripts/db_backups.sh
The docs site at docs.sexyvoice.ai is a Fumadocs (Next.js) app in
apps/docs. Content lives in apps/docs/content/.
pnpm --filter @sexyvoice/docs dev.pnpm --filter @sexyvoice/docs generate-openapi-docs after changing the
/api/v1/* request/response schemas.Generate waveform videos for audio files using seewav:
pip3 install seewav
seewav your_audio.mp3 --color '0.8,0.0,0.4'
# Convert WAV to MP3 with specific audio settings
# -i input.wav: Input file
# -acodec libmp3lame: Use LAME MP3 encoder
# -q:a 2: Variable bit rate quality (0=highest, 9=lowest)
# -ar 24000: Set audio sample rate to 24kHz
# -ac 1: Set audio channels to mono (1 channel)
# output.mp3: Output file
ffmpeg -i input.wav -acodec libmp3lame -q:a 2 -ar 24000 -ac 1 output.mp3
# For high quality MP3
ffmpeg -i input.wav -acodec libmp3lame -q:a 0 -ar 44100 -ac 2 output-high-quality.mp3
# For lowest quality MP3 possible
ffmpeg -i input.wav -acodec libmp3lame -q:a 9 -ar 8000 -ac 1 output-lowest.mp3
SexyVoice.ai implements multiple security layers:
We welcome contributions!
Zed with Cspell extension
npm install -g cspell @cspell/dict-de-de @cspell/dict-es-es
asdf reshim nodejs
cspell link add @cspell/dict-de-de
cspell link add @cspell/dict-es-es
# restart Zed language server
This project is licensed under the MIT License.
SexyVoice.ai is actively developed and maintained. Check the roadmap for upcoming features and improvements.
next-intlThe public catalog has 63 voices: 57 text-to-speech voices and 6 voices for AI
voice calls. Public voices live in the voices table, and GET /api/v1/voices
returns the text-to-speech subset.
| Family | Model alias | Feature | Public voices | Languages |
|---|---|---|---|---|
| Gemini 3.8 Flash TTS | gpro38 | tts | 28 | Multilingual, plus es-ES and es-MX |
| Gemini 3.1 Flash TTS | gpro31 | tts | 11 | Multilingual (70+ languages) |
| Gemini 2.5 Pro TTS | gpro | tts | 11 | Multilingual (24 languages) |
| xAI Grok | xai | tts | 7 | Multilingual with automatic detection |
| xAI Grok | xai | call | 6 | Multilingual |
gpro, gpro31, gpro38)The same eleven Gemini voice identities exist under each Gemini model alias, so
one name maps to three catalog rows. Select by voiceId, or pass the model
alias together with the voice name.
| Voice | Description |
|---|---|
achernar | Soft |
aoede | Breezy |
autonoe | Bright |
callirrhoe | Easy-going |
despina | Smooth |
erinome | Clear |
gacrux | Mature |
kore | Firm |
puck | Upbeat |
sulafat | Warm |
zephyr | Bright |
Gemini 2.5 Pro (gpro) voices support style prompting and the following
language/locale set:
| Language | BCP-47 Code | Language | BCP-47 Code |
|---|---|---|---|
| Arabic (Egyptian) | ar-EG | German (Germany) | de-DE |
| English (US) | en-US | Spanish (US) | es-US |
| French (France) | fr-FR | Hindi (India) | hi-IN |
| Indonesian (Indonesia) | id-ID | Italian (Italy) | it-IT |
| Japanese (Japan) | ja-JP | Korean (Korea) | ko-KR |
| Portuguese (Brazil) | pt-BR | Russian (Russia) | ru-RU |
| Dutch (Netherlands) | nl-NL | Polish (Poland) | pl-PL |
| Thai (Thailand) | th-TH | Turkish (Turkey) | tr-TR |
| Vietnamese (Vietnam) | vi-VN | Romanian (Romania) | ro-RO |
| Ukrainian (Ukraine) | uk-UA | Bengali (Bangladesh) | bn-BD |
| English (India) | en-IN & hi-IN bundle | Marathi (India) | mr-IN |
| Tamil (India) | ta-IN | Telugu (India) | te-IN |
gpro31)Use gpro31 only with voices returned by /api/v1/voices as model: "gpro31".
Voices returned as gpro stay on Gemini 2.5 Pro.
Supports all 24 languages above, plus (non-exhaustive):
Afrikaans (af-ZA), Albanian (sq-AL), Amharic (am-ET), Armenian (hy-AM),
Azerbaijani (az-AZ), Basque (eu-ES), Bulgarian (bg-BG), Catalan (ca-ES),
Chinese Simplified (zh-CN), Chinese Traditional (zh-TW), Croatian (hr-HR),
Czech (cs-CZ), Danish (da-DK), Estonian (et-EE), Filipino/Tagalog (fil-PH),
Finnish (fi-FI), Galician (gl-ES), Georgian (ka-GE), Greek (el-GR),
Gujarati (gu-IN), Hebrew (he-IL), Hungarian (hu-HU), Icelandic (is-IS),
Irish (ga-IE), Javanese (jv-ID), Kannada (kn-IN), Kazakh (kk-KZ),
Latvian (lv-LV), Lithuanian (lt-LT), Macedonian (mk-MK), Malay (ms-MY),
Maltese (mt-MT), Norwegian Bokmål (nb-NO), Persian (fa-IR), Punjabi (pa-IN),
Serbian (sr-RS), Slovak (sk-SK), Slovenian (sl-SI), Swahili (sw-KE),
Swedish (sv-SE), Urdu (ur-PK), Uzbek (uz-UZ), Welsh (cy-GB), Zulu (zu-ZA).
Plus English, Spanish, French, Portuguese, and Arabic regional variants.
Full list: https://cloud.google.com/text-to-speech/docs/gemini-tts#language_availability
Gemini 3.1 also supports 200+ inline audio expression tags ([cheerfully], [whispering], [pause], etc.).
gpro38)Use gpro38 only with voices returned by /api/v1/voices as
model: "gpro38". Gemini 3.8 rows cover the eleven multilingual identities
above plus 17 Spanish role voices. Each Spanish voice description records its
role, accent, and pitch.
Castilian Spanish (es-ES):
| Voice | Role | Type | Pitch |
|---|---|---|---|
es-es-advisor-8 | Authoritative Advisor | Female | Low |
es-es-assistant-3 | Digital Assistant | Male | Low |
es-es-commercial-7 | Commercial Voiceover | Female | Medium |
es-es-concierge-3 | Concierge | Female | Medium |
es-es-csagent-6 | Call Center Agent | Female | Low |
es-es-podcaster-7 | Podcaster | Male | Low |
es-es-techagent-5 | Tech Advisor | Female | Medium |
es-es-training-12 | Training Voiceover | Female | High |
es-es-tutor-12 | Tutor | Female | Medium |
Mexican Spanish (es-MX, provider locale es-419):
| Voice | Role | Type | Pitch |
|---|---|---|---|
es-419-advisor-4 | Authoritative Advisor | Female | High |
es-419-assistant-9 | Digital Assistant | Male | Medium |
es-419-commercial-1 | Commercial Voiceover | Male | Low |
es-419-concierge-5 | Concierge | Female | High |
es-419-csagent-8 | Call Center Agent | Neutral | Medium |
es-419-podcaster-1 | Podcaster | Male | Low |
es-419-training-8 | Training Voiceover | Female | Medium |
es-419-tutor-3 | Tutor | Female | Low |
xai) expressive voicesGrok text-to-speech voices:
| Voice | Description |
|---|---|
ara | Warm and friendly |
carina | Breathy and enthusiastic |
eve | Engaging and upbeat |
leo | Authoritative and strong |
rex | Confident and clear |
sal | Versatile voice |
zagan | Powerful, dramatic, and unmistakable |
AI voice calls use the Grok call voices Ara, Carina, Eve, Leo, Rex,
and Sal.
Custom characters can use owned saved Inworld or Mistral voices.
CALL_CLONE_PROVIDER=inworld selects the provider for new call clones; set it
to mistral to create Mistral profiles. Existing profiles retain their provider.
Set INWORLD_API_KEY to the Basic credential exactly as Inworld shows it
(already Base64; do not encode it again), with clone/write access
and give the SexyCall agent access to the same Inworld workspace. Mistral
profiles require MISTRAL_API_KEY in the web app and agent. An unset
CALL_CLONE_PROVIDER selects Inworld as soon as this web deployment is released.
Deploy the agent's inworld-tts support and configure INWORLD_API_KEY in both
deployments first. To defer the switch, explicitly set CALL_CLONE_PROVIDER=mistral
in Vercel before releasing the web app; set it to inworld and redeploy once
the agent and credentials are ready.
See saved call voices and
deployment setup.
These voices support expressive inline tags like [laugh] and wrapping tags like <fast>...</fast>, plus automatic language detection and the following language/locale options:
| Language / Locale | Code | Language / Locale | Code |
|---|---|---|---|
| English | en | Japanese | ja |
| Arabic (Egypt) | ar-EG | Korean | ko |
| Arabic (Saudi Arabia) | ar-SA | Portuguese (Brazil) | pt-BR |
| Arabic (United Arab Emirates) | ar-AE | Portuguese (Portugal) | pt-PT |
| Bengali | bn | Russian | ru |
| Chinese (Simplified) | zh | Spanish (Spain) | es-ES |
| French | fr | Spanish (Mexico) | es-MX |
| German | de | Turkish | tr |
| Hindi | hi | Vietnamese | vi |
| Indonesian | id | Italian | it |
LIVEKIT_URLLIVEKIT_API_KEYLIVEKIT_API_SECRETLIVEKIT_AGENT_NAME - Optional; defaults to sexycall, and must match the deployed agent's registered nameSTRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETSTRIPE_TOPUP_STARTER_PRICE_IDSTRIPE_TOPUP_STANDARD_PRICE_IDSTRIPE_TOPUP_PRO_PRICE_IDSTRIPE_SUBSCRIPTION_STARTER_PRICE_IDSTRIPE_SUBSCRIPTION_STANDARD_PRICE_IDSTRIPE_SUBSCRIPTION_PRO_PRICE_IDSTRIPE_SUBSCRIPTION_FIRST_MONTH_COUPON_ID - Optional Stripe coupon applied automatically for eligible first-time subscribersSTRIPE_SUBSCRIPTION_FIRST_MONTH_DISCOUNT_PERCENT - Optional first-month discount percentage used to display discounted subscription pricing when the coupon is configuredNEXT_PUBLIC_PROMO_ENABLED - Enables promo banners and bonus-credit pricingNEXT_PUBLIC_ACTIVE_PROMO_BANNER - Active promo banner id from apps/web/messages/*.json and apps/web/lib/banners/registry.tsNEXT_PUBLIC_ACTIVE_ANNOUNCEMENT_BANNER - Active announcement banner id from apps/web/messages/*.json and apps/web/lib/banners/registry.tsNEXT_PUBLIC_PROMO_THEME - Banner theme (pink, orange, blue)NEXT_PUBLIC_PROMO_COUNTDOWN_END_DATE - Optional countdown end date for promo banners that support itNEXT_PUBLIC_PROMO_ID - Promo identifier still used by Stripe metadata and credit bonus flowsNEXT_PUBLIC_PROMO_BONUS_STARTERNEXT_PUBLIC_PROMO_BONUS_STANDARDNEXT_PUBLIC_PROMO_BONUS_PROTELEGRAM_WEBHOOK_URL - for daily stats notificationsCRON_SECRET - For securing the cron API routes (/api/daily-stats, /api/call-sessions/analyze/batch) - See Managing Cron JobsAXIOM_TOKEN - Your Axiom API token for structured request logging on /api/v1/speechAPI_KEY_HMAC_SECRET - Secret used to HMAC-SHA256 hash API keys before storing them in the database. Generate with openssl rand -hex 32. Without this, keys fall back to plain SHA-256 (acceptable in development, never in production).EDGE_CONFIG - Your Vercel Edge Config connection string (automatically set when you link an Edge Config to your project)NEXT_PUBLIC_E2E_TEST_MODE - Build-time; set to true to disable the browser Sentry client so CI runs don't report into production SentryFor environment variables, infrastructure configuration, and release verification, see Deployment and release checks.
Set up Supabase
cd apps/web
supabase db push
cd ../..
Start the development server
pnpm dev
Open your browser
The web app runs through Portless at https://sv.dev.
The portless.json app name only sets the route name; PORTLESS_TLD=dev
in apps/web/package.json makes the route use .dev instead of the
default .localhost.
If you previously installed the Portless startup service, it may restart the
default .localhost proxy on port 443 and block .dev. Remove the service
before starting the app:
sudo portless service uninstall
sudo portless proxy stop
pnpm dev