feat: initial Flask REST API implementation for TTS + Voice Conversion
This commit is contained in:
4
app/models/__init__.py
Normal file
4
app/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""Models package."""
|
||||
from app.models.voice import Voice
|
||||
|
||||
__all__ = ['Voice']
|
||||
73
app/models/voice.py
Normal file
73
app/models/voice.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""Voice model for reference voice metadata."""
|
||||
import os
|
||||
import json
|
||||
from datetime import datetime
|
||||
from typing import List, Optional, Dict, Any
|
||||
|
||||
|
||||
class Voice:
|
||||
"""Represents a reference voice."""
|
||||
|
||||
def __init__(self, voice_id: str, name: str, filename: str, created_at: str = None):
|
||||
self.id = voice_id
|
||||
self.name = name
|
||||
self.filename = filename
|
||||
self.created_at = created_at or datetime.now().isoformat()
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert to dictionary."""
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'filename': self.filename,
|
||||
'created_at': self.created_at
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_file(cls, voice_id: str, voices_dir: str) -> Optional['Voice']:
|
||||
"""Load voice metadata from JSON file."""
|
||||
meta_path = os.path.join(voices_dir, f"{voice_id}.json")
|
||||
if not os.path.exists(meta_path):
|
||||
return None
|
||||
|
||||
with open(meta_path, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
return cls(
|
||||
voice_id=data['id'],
|
||||
name=data['name'],
|
||||
filename=data['filename'],
|
||||
created_at=data.get('created_at')
|
||||
)
|
||||
|
||||
def save(self, voices_dir: str):
|
||||
"""Save voice metadata to JSON file."""
|
||||
meta_path = os.path.join(voices_dir, f"{self.id}.json")
|
||||
with open(meta_path, 'w') as f:
|
||||
json.dump(self.to_dict(), f, indent=2)
|
||||
|
||||
def get_audio_path(self, voices_dir: str) -> str:
|
||||
"""Get full path to audio file."""
|
||||
return os.path.join(voices_dir, self.filename)
|
||||
|
||||
def exists(self, voices_dir: str) -> bool:
|
||||
"""Check if voice files exist."""
|
||||
audio_path = self.get_audio_path(voices_dir)
|
||||
meta_path = os.path.join(voices_dir, f"{self.id}.json")
|
||||
return os.path.exists(audio_path) and os.path.exists(meta_path)
|
||||
|
||||
@classmethod
|
||||
def list_all(cls, voices_dir: str) -> List['Voice']:
|
||||
"""List all voices in directory."""
|
||||
voices = []
|
||||
if not os.path.exists(voices_dir):
|
||||
return voices
|
||||
|
||||
for filename in os.listdir(voices_dir):
|
||||
if filename.endswith('.json'):
|
||||
voice_id = filename[:-5] # Remove .json
|
||||
voice = cls.from_file(voice_id, voices_dir)
|
||||
if voice and voice.exists(voices_dir):
|
||||
voices.append(voice)
|
||||
|
||||
return sorted(voices, key=lambda v: v.created_at, reverse=True)
|
||||
Reference in New Issue
Block a user