High-level TTS with voice rotation and mood selection for content creators
Project description
Voice Forge 🎙️
High-level TTS with voice rotation and mood selection for content creators
Voice Forge makes text-to-speech dead simple. Built on top of Edge TTS (free, high-quality Microsoft voices), it adds voice rotation, mood-based selection, and word-level timestamps - everything content creators need.
✨ Features
- 🆓 Free - Uses Microsoft Edge TTS (no API key needed)
- 🎭 20+ voices - Male, female, US, UK, Australian accents
- 🎯 Mood-based selection - Pick voices that match your content
- 🔄 Voice rotation - Automatic variety across multiple generations
- ⏱️ Word timestamps - Perfect for synchronized subtitles
- 🚀 Async-first - Built for modern Python
📦 Installation
pip install voice-forge
For ElevenLabs support (premium voices):
pip install voice-forge[elevenlabs]
🚀 Quick Start
Simple One-Liner
from voice_forge import speak
await speak("Hello world!", "output.mp3")
Choose a Voice
from voice_forge import EdgeTTS
# Use a specific voice
tts = EdgeTTS(voice="aria") # Expressive, dramatic female
result = await tts.generate("The tension was unbearable...", "drama.mp3")
print(f"Generated {result.duration:.1f}s of audio")
Mood-Based Selection
from voice_forge import VoiceRotator
rotator = VoiceRotator()
# Get a voice that matches the mood
tts = rotator.get_tts_for_mood("dramatic")
await tts.generate("And then... everything changed.", "scene.mp3")
# Available moods: dramatic, suspense, scary, happy, sad, news, tutorial, podcast, aita, revenge, heartwarming, shocking
Voice Rotation for Variety
from voice_forge import VoiceRotator
rotator = VoiceRotator()
stories = ["Story one...", "Story two...", "Story three..."]
for i, story in enumerate(stories):
# Each story gets a different voice
tts = rotator.get_next_tts()
await tts.generate(story, f"story_{i}.mp3")
Word-Level Timestamps (for subtitles)
from voice_forge import EdgeTTS
tts = EdgeTTS(voice="guy")
result, timestamps = await tts.generate_with_timestamps(
"This is perfect for creating synchronized subtitles.",
"output.mp3"
)
for word in timestamps:
print(f"{word['start']:.2f}s - {word['end']:.2f}s: {word['text']}")
🎭 Available Voices
| Name | Gender | Accent | Best For |
|---|---|---|---|
guy |
Male | US | Storytelling, warm narratives |
jenny |
Female | US | Friendly, versatile content |
aria |
Female | US | Dramatic, emotional content |
davis |
Male | US | Professional, authoritative |
ryan |
Male | UK | British, formal content |
sonia |
Female | UK | British, warm professional |
thomas |
Male | UK | Deep, serious, dramatic |
🎯 Mood Categories
Perfect for content creators who need the right voice for their content:
| Mood | Best Voices | Use Case |
|---|---|---|
dramatic |
aria, guy, ryan | Reddit stories, drama |
suspense |
aria, thomas, davis | Thriller content |
happy |
jenny, sara, tony | Upbeat content |
news |
davis, nancy, ryan | News, reports |
aita |
guy, aria, jenny | "Am I The A-hole" stories |
tutorial |
jenny, guy, sara | How-to videos |
🎚️ Adjust Speed and Pitch
from voice_forge import EdgeTTS
tts = EdgeTTS(voice="guy")
# Faster for short-form content
await tts.generate("Quick update!", "fast.mp3", rate="+20%")
# Slower for dramatic effect
await tts.generate("And then...", "slow.mp3", rate="-30%")
# Higher pitch
await tts.generate("Exciting news!", "high.mp3", pitch="+10Hz")
💎 ElevenLabs (Premium)
For the most natural-sounding voices:
from voice_forge import ElevenLabsTTS
tts = ElevenLabsTTS(
api_key="your-api-key",
voice_id="your-voice-id"
)
result = await tts.generate("Premium quality voice.", "premium.mp3")
📋 Requirements
- Python 3.10+
ffprobe(optional, for accurate duration detection)
# Ubuntu/Debian
sudo apt install ffmpeg
# macOS
brew install ffmpeg
# Windows
# Download from https://ffmpeg.org/download.html
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT License - feel free to use in your projects!
Made with ❤️ for content creators
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file easy_edge_tts-0.1.0.tar.gz.
File metadata
- Download URL: easy_edge_tts-0.1.0.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7810fa53664c4e52e4c54213d077f68d6b7281b8b837dc63e1f812171880da4b
|
|
| MD5 |
232065b2d6af81a7e5625fb40a75c6e0
|
|
| BLAKE2b-256 |
c6e4fdb26182882becc925fbbb98324e85fa398dd88b9a7a98e5443b05a06ac0
|
File details
Details for the file easy_edge_tts-0.1.0-py3-none-any.whl.
File metadata
- Download URL: easy_edge_tts-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbbaa822a55ebc1d9ff77c4fde2fe2e2ee06af2526acb4a8e505d44d80258cd8
|
|
| MD5 |
fa6a69a25cff5021231d0220108f4819
|
|
| BLAKE2b-256 |
7b8b8f1e7fe3062a226a1209b38b76f3e15e058004cf48a99a55da5b8f8a524f
|