Spaces:
Build error
Build error
File size: 10,818 Bytes
b738528 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | # spaces_client.py - Client library for your Spaces deployment
import asyncio
import aiohttp
import requests
from typing import Optional, Union
import io
import tempfile
import logging
logger = logging.getLogger(__name__)
class SpacesPiperTTS:
"""Client for Piper TTS deployed on Hugging Face Spaces"""
def __init__(self, space_name: str, hf_token: Optional[str] = None):
"""
Initialize client for Spaces deployment
Args:
space_name: Your Space name (format: "username/space-name")
hf_token: Optional Hugging Face token for private spaces
"""
self.space_name = space_name
self.base_url = f"https://{space_name.replace('/', '-')}.hf.space"
self.api_url = f"{self.base_url}/api"
self.hf_token = hf_token
# Headers for authenticated requests
self.headers = {}
if hf_token:
self.headers["Authorization"] = f"Bearer {hf_token}"
def synthesize(self, text: str) -> bytes:
"""
Synchronous TTS synthesis
Args:
text: Text to convert to speech
Returns:
WAV audio data as bytes
"""
try:
response = requests.post(
f"{self.api_url}/tts",
json={"text": text},
headers=self.headers,
timeout=30
)
response.raise_for_status()
return response.content
except requests.exceptions.RequestException as e:
logger.error(f"TTS request failed: {e}")
raise
async def synthesize_async(self, text: str) -> bytes:
"""
Asynchronous TTS synthesis
Args:
text: Text to convert to speech
Returns:
WAV audio data as bytes
"""
async with aiohttp.ClientSession() as session:
try:
async with session.post(
f"{self.api_url}/tts",
json={"text": text},
headers=self.headers,
timeout=aiohttp.ClientTimeout(total=30)
) as response:
response.raise_for_status()
return await response.read()
except aiohttp.ClientError as e:
logger.error(f"Async TTS request failed: {e}")
raise
def synthesize_to_file(self, text: str, filename: str) -> str:
"""
Synthesize and save to file
Args:
text: Text to convert to speech
filename: Output filename
Returns:
Path to saved file
"""
audio_data = self.synthesize(text)
with open(filename, 'wb') as f:
f.write(audio_data)
return filename
async def synthesize_to_file_async(self, text: str, filename: str) -> str:
"""
Async synthesize and save to file
Args:
text: Text to convert to speech
filename: Output filename
Returns:
Path to saved file
"""
audio_data = await self.synthesize_async(text)
with open(filename, 'wb') as f:
f.write(audio_data)
return filename
def health_check(self) -> dict:
"""Check if the service is healthy"""
try:
response = requests.get(f"{self.api_url}/health", headers=self.headers)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
logger.error(f"Health check failed: {e}")
raise
async def health_check_async(self) -> dict:
"""Async health check"""
async with aiohttp.ClientSession() as session:
try:
async with session.get(f"{self.api_url}/health", headers=self.headers) as response:
response.raise_for_status()
return await response.json()
except aiohttp.ClientError as e:
logger.error(f"Async health check failed: {e}")
raise
class DigitalCompanionSpaces:
"""High-level wrapper for digital companion integration with Spaces"""
def __init__(self, space_name: str, hf_token: Optional[str] = None):
self.tts = SpacesPiperTTS(space_name, hf_token)
self.conversation_history = []
def speak(self, text: str, save_to_file: Optional[str] = None) -> Union[bytes, str]:
"""
Generate speech for the companion
Args:
text: Text to speak
save_to_file: Optional filename to save audio
Returns:
Audio bytes or filename if saved
"""
# Log conversation
self.conversation_history.append({
"role": "assistant",
"text": text,
"timestamp": asyncio.get_event_loop().time()
})
# Generate speech
if save_to_file:
return self.tts.synthesize_to_file(text, save_to_file)
else:
return self.tts.synthesize(text)
async def speak_async(self, text: str, save_to_file: Optional[str] = None) -> Union[bytes, str]:
"""Async version of speak"""
# Log conversation
self.conversation_history.append({
"role": "assistant",
"text": text,
"timestamp": asyncio.get_event_loop().time()
})
# Generate speech
if save_to_file:
return await self.tts.synthesize_to_file_async(text, save_to_file)
else:
return await self.tts.synthesize_async(text)
def get_conversation_history(self) -> list:
"""Get conversation history"""
return self.conversation_history.copy()
def clear_history(self):
"""Clear conversation history"""
self.conversation_history.clear()
# deploy_to_spaces.py - Deployment helper script
import os
import subprocess
import sys
from pathlib import Path
def deploy_to_spaces():
"""Deploy the TTS system to Hugging Face Spaces"""
print("π Deploying Piper TTS to Hugging Face Spaces")
print("=" * 50)
# Check if we're in the right directory
required_files = ["app.py", "requirements.txt"]
for file in required_files:
if not Path(file).exists():
print(f"β Missing required file: {file}")
return False
# Check if git is initialized
if not Path(".git").exists():
print("π Initializing git repository...")
subprocess.run(["git", "init"], check=True)
# Check if huggingface_hub is installed
try:
import huggingface_hub
except ImportError:
print("π¦ Installing huggingface_hub...")
subprocess.run([sys.executable, "-m", "pip", "install", "huggingface_hub[cli]"], check=True)
# Get Space details from user
space_name = input("Enter your Space name (username/space-name): ").strip()
if not space_name or "/" not in space_name:
print("β Invalid Space name format. Use: username/space-name")
return False
# Check for HF token
hf_token = os.getenv("HF_TOKEN")
if not hf_token:
hf_token = input("Enter your Hugging Face token (or set HF_TOKEN env var): ").strip()
if not hf_token:
print("β Hugging Face token is required")
return False
try:
# Login to Hugging Face
print("π Logging into Hugging Face...")
subprocess.run(["huggingface-cli", "login", "--token", hf_token], check=True)
# Create Space
print(f"ποΈ Creating Space: {space_name}")
subprocess.run([
"huggingface-cli", "repo", "create",
space_name,
"--type", "space",
"--space_sdk", "gradio"
], check=True)
# Add git remote
repo_url = f"https://huggingface.co/spaces/{space_name}"
print(f"π Adding remote: {repo_url}")
# Remove existing remote if exists
subprocess.run(["git", "remote", "remove", "origin"], check=False)
subprocess.run(["git", "remote", "add", "origin", repo_url], check=True)
# Prepare files for commit
print("π Preparing files...")
subprocess.run(["git", "add", "."], check=True)
subprocess.run(["git", "commit", "-m", "Initial commit: Piper TTS for digital companions"], check=True)
# Push to Spaces
print("β¬οΈ Pushing to Spaces...")
subprocess.run(["git", "push", "origin", "main"], check=True)
print(f"β
Successfully deployed to: {repo_url}")
print(f"π Your TTS API will be available at: https://{space_name.replace('/', '-')}.hf.space/api")
return True
except subprocess.CalledProcessError as e:
print(f"β Deployment failed: {e}")
return False
except KeyboardInterrupt:
print("\nβ οΈ Deployment cancelled by user")
return False
# example_usage.py - Usage examples
async def example_basic_usage():
"""Basic usage example"""
print("π€ Basic TTS Usage Example")
# Replace with your actual Space name
tts = SpacesPiperTTS("your-username/your-space-name")
# Check if service is healthy
try:
health = tts.health_check()
print(f"β
Service healthy: {health}")
except Exception as e:
print(f"β Service unavailable: {e}")
return
# Generate speech
text = "Hello! I'm your digital companion powered by Piper TTS on Hugging Face Spaces."
print(f"π΅ Generating speech for: '{text}'")
try:
audio_data = tts.synthesize(text)
print(f"β
Generated {len(audio_data)} bytes of audio")
# Save to file
filename = "companion_speech.wav"
tts.synthesize_to_file(text, filename)
print(f"πΎ Saved audio to: {filename}")
except Exception as e:
print(f"β TTS failed: {e}")
async def example_digital_companion():
"""Digital companion integration example"""
print("π€ Digital Companion Example")
# Initialize companion
companion = DigitalCompanionSpaces("your-username/your-space-name")
# Conversation flow
responses = [
"Hello! I'm your AI companion. How are you feeling today?",
"I understand. Let me help you with that.",
"That's a great question! Let me think about it.",
"I hope that was helpful. Is there anything else you'd like to know?"
]
for i, response in enumerate(responses, |