feat: modernize UI with gradient design, glass morphism, and enhanced visual appeal
- Add purple/indigo gradient background throughout app - Implement glass morphism effects on all cards - Add gradient buttons with smooth hover animations - Integrate emoji icons for better visual communication - Enhance typography with improved font stack - Add loading spinners and smooth transitions - Improve color scheme with modern purple/indigo palette - Add glowing shadows and depth effects - Maintain responsive design and touch-friendly interactions
This commit is contained in:
@@ -4,10 +4,11 @@
|
||||
|
||||
The Text to Audiobook system is a full-stack application that converts long-form text into multi-voice audiobooks using Kokoro TTS. The architecture follows a client-server model with a React TypeScript frontend and a Python FastAPI backend running in Docker. The system automatically detects speaker roles in text, allows voice assignment per role, and generates high-quality audio using the Kokoro-82M model.
|
||||
|
||||
The application workflow consists of three main phases:
|
||||
The application workflow consists of four main phases:
|
||||
1. **Text Input & Role Detection**: User provides text, system identifies distinct speakers
|
||||
2. **Voice Assignment**: User maps each detected role to a specific Kokoro voice
|
||||
3. **Audio Generation & Playback**: System synthesizes multi-voice audio and provides playback/download
|
||||
3. **Script Review & Editing**: User reviews and edits AI-generated speaker assignments for each text segment
|
||||
4. **Audio Generation & Playback**: System synthesizes multi-voice audio and provides playback/download
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -93,10 +94,12 @@ Main application container managing the overall workflow state.
|
||||
- `text: string` - User input text
|
||||
- `roles: Role[]` - Detected roles from backend
|
||||
- `voiceAssignments: Map<string, string>` - Role ID to Voice ID mapping
|
||||
- `scriptSegments: ScriptSegment[]` - AI-generated script segments
|
||||
- `selectedLanguage: string` - Language code (default: 'a')
|
||||
- `speed: number` - Playback speed (default: 1.0)
|
||||
- `audioUrl: string | null` - Generated audio blob URL
|
||||
- `isDetectingRoles: boolean` - Loading state for role detection
|
||||
- `isGeneratingScript: boolean` - Loading state for script generation
|
||||
- `isGenerating: boolean` - Loading state for audio generation
|
||||
- `error: string | null` - Error message if any
|
||||
|
||||
@@ -104,7 +107,10 @@ Main application container managing the overall workflow state.
|
||||
- `handleTextChange(text: string)` - Updates text state
|
||||
- `handleDetectRoles()` - Calls API to detect roles
|
||||
- `handleVoiceAssignment(roleId: string, voiceId: string)` - Updates voice mapping
|
||||
- `handleGenerate()` - Calls API to generate audiobook
|
||||
- `handleGenerateScript()` - Calls API to generate script preview
|
||||
- `handleSkipReview()` - Skips script review and proceeds to generation
|
||||
- `handleSegmentChange(segmentId: string, newSpeaker: string)` - Updates speaker for a segment
|
||||
- `handleGenerate()` - Calls API to generate audiobook with edited script
|
||||
- `handleDownload()` - Triggers download of generated audio
|
||||
|
||||
#### 2. TextInputSection Component
|
||||
@@ -132,14 +138,25 @@ Displays role-to-voice mapping interface with language and speed controls.
|
||||
- `isGenerating: boolean`
|
||||
- `allRolesAssigned: boolean`
|
||||
|
||||
#### 4. AudioPlayerSection Component
|
||||
#### 4. ScriptReviewSection Component
|
||||
Displays AI-generated script with editable speaker assignments.
|
||||
|
||||
**Props:**
|
||||
- `segments: ScriptSegment[]`
|
||||
- `roles: Role[]`
|
||||
- `onSegmentChange: (segmentId: string, newSpeaker: string) => void`
|
||||
- `onGenerate: () => void`
|
||||
- `onSkipReview: () => void`
|
||||
- `isGenerating: boolean`
|
||||
|
||||
#### 5. AudioPlayerSection Component
|
||||
Displays audio player and download button after generation.
|
||||
|
||||
**Props:**
|
||||
- `audioUrl: string`
|
||||
- `onDownload: () => void`
|
||||
|
||||
#### 5. API Client (`src/api/tts.ts`)
|
||||
#### 6. API Client (`src/api/tts.ts`)
|
||||
|
||||
**Interfaces:**
|
||||
```typescript
|
||||
@@ -156,8 +173,24 @@ export interface RolesResponse {
|
||||
roles: Role[];
|
||||
}
|
||||
|
||||
export interface GenerateRequest {
|
||||
export interface ScriptSegment {
|
||||
id: string;
|
||||
speaker: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface ScriptRequest {
|
||||
text: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
export interface ScriptResponse {
|
||||
segments: ScriptSegment[];
|
||||
}
|
||||
|
||||
export interface GenerateRequest {
|
||||
segments?: ScriptSegment[];
|
||||
text?: string;
|
||||
lang: string;
|
||||
roles: { id: string; voice: string }[];
|
||||
speed?: number;
|
||||
@@ -167,6 +200,7 @@ export interface GenerateRequest {
|
||||
**Functions:**
|
||||
```typescript
|
||||
export async function detectRoles(text: string): Promise<RolesResponse>
|
||||
export async function generateScript(request: ScriptRequest): Promise<ScriptResponse>
|
||||
export async function generateAudiobook(payload: GenerateRequest): Promise<Blob>
|
||||
export async function checkHealth(): Promise<{ status: string }>
|
||||
```
|
||||
@@ -188,6 +222,11 @@ async def detect_roles(request: RoleDetectionRequest) -> RolesResponse:
|
||||
"""Analyzes text and returns detected roles"""
|
||||
pass
|
||||
|
||||
@app.post("/api/tts/script")
|
||||
async def generate_script(request: ScriptRequest) -> ScriptResponse:
|
||||
"""Generates script preview with AI-segmented text and speaker assignments"""
|
||||
pass
|
||||
|
||||
@app.post("/api/tts")
|
||||
async def generate_audiobook(request: TTSRequest) -> StreamingResponse:
|
||||
"""Generates multi-voice audiobook and streams audio"""
|
||||
@@ -206,12 +245,25 @@ class RoleInfo(BaseModel):
|
||||
class RolesResponse(BaseModel):
|
||||
roles: List[RoleInfo]
|
||||
|
||||
class ScriptRequest(BaseModel):
|
||||
text: str
|
||||
roles: List[str] # List of detected role IDs
|
||||
|
||||
class ScriptSegment(BaseModel):
|
||||
id: str # Unique segment identifier
|
||||
speaker: str # Assigned speaker/role
|
||||
text: str # Text content for this segment
|
||||
|
||||
class ScriptResponse(BaseModel):
|
||||
segments: List[ScriptSegment]
|
||||
|
||||
class RoleVoiceMapping(BaseModel):
|
||||
id: str
|
||||
voice: str
|
||||
|
||||
class TTSRequest(BaseModel):
|
||||
text: str
|
||||
segments: Optional[List[ScriptSegment]] = None # If provided, use edited script
|
||||
text: Optional[str] = None # Fallback if no script provided
|
||||
lang: str
|
||||
roles: List[RoleVoiceMapping]
|
||||
speed: Optional[float] = 1.0
|
||||
@@ -384,10 +436,11 @@ interface LanguageOption {
|
||||
**Application State:**
|
||||
```typescript
|
||||
interface AppState {
|
||||
phase: 'input' | 'assignment' | 'generated';
|
||||
phase: 'input' | 'assignment' | 'review' | 'generated';
|
||||
text: string;
|
||||
roles: Role[];
|
||||
voiceAssignments: Map<string, string>;
|
||||
scriptSegments: ScriptSegment[];
|
||||
language: string;
|
||||
speed: number;
|
||||
audioUrl: string | null;
|
||||
@@ -578,6 +631,22 @@ ROLE_PATTERNS = {
|
||||
*For any* text where both AI detection and pattern detection find roles, the backend should merge results and return each unique role exactly once.
|
||||
**Validates: Requirements 14.5**
|
||||
|
||||
### Property 32: Script generation completeness
|
||||
*For any* text and list of roles, the script generation should return segments that cover the entire input text without gaps or overlaps.
|
||||
**Validates: Requirements 15.2**
|
||||
|
||||
### Property 33: Script segment structure
|
||||
*For any* generated script, each segment should contain an id, speaker, and text field.
|
||||
**Validates: Requirements 15.4**
|
||||
|
||||
### Property 34: Script segment editability
|
||||
*For any* script segment, the user should be able to change the speaker assignment to any detected role.
|
||||
**Validates: Requirements 15.5**
|
||||
|
||||
### Property 35: Edited script persistence
|
||||
*For any* edited script segment, the changes should be preserved when generating the audiobook.
|
||||
**Validates: Requirements 15.7**
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Frontend Error Handling
|
||||
|
||||
Reference in New Issue
Block a user