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:
2025-12-09 12:29:40 +00:00
parent 63bdf57593
commit 706ada866c
17 changed files with 731 additions and 93 deletions

View File

@@ -0,0 +1,154 @@
# Script Review Feature - Enhancement Specification
## Overview
This document describes the new **Script Review & Editing** feature that addresses the issue where AI-generated speaker assignments may not always be accurate. This feature gives users visibility and control over how the text is segmented and which character speaks each line.
## Problem Statement
When using AI to detect speakers in unmarked text, the system may:
- Incorrectly assign dialogue to the wrong character
- Miss some character dialogue
- Assign narrative text to a character instead of the narrator
Users currently have no way to see or correct these mistakes before generating the audiobook.
## Solution
Add a new **Script Review** phase between voice assignment and audio generation where users can:
1. See the complete script breakdown showing which character speaks each line
2. Edit speaker assignments for any segment
3. Skip the review if they trust the AI's assignments
## User Workflow
### Updated Flow
```
1. Text Input
↓
2. Role Detection (AI detects: Lily, Benny, Sammy, Narrator)
↓
3. Voice Assignment (User assigns voices to each role)
↓
4. **Script Review** (NEW - User reviews and edits speaker assignments)
↓
5. Audio Generation (Uses edited script)
↓
6. Playback & Download
```
### Script Review Interface
The review screen will show:
```
┌─────────────────────────────────────────────────────────────┐
│ Review Script │
├─────────────────────────────────────────────────────────────┤
│ │
│ Segment 1: [Narrator ▼] │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Once upon a time, in a tiny village surrounded by │ │
│ │ lush green forests, there lived three best friends... │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Segment 2: [Lily ▼] │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ "Have you guys heard about the new stream that just │ │
│ │ appeared in the woods?" │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Segment 3: [Benny ▼] │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ "Ooh, I love streams! Do we get to go see it now?" │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ... (more segments) │
│ │
│ [Skip Review] [Generate Audiobook] │
└─────────────────────────────────────────────────────────────┘
```
## Technical Implementation
### New API Endpoint
**POST /api/tts/script**
- Request: `{ text: string, roles: string[] }`
- Response: `{ segments: [{ id: string, speaker: string, text: string }] }`
- Uses Ollama AI to segment text and assign speakers
- Returns editable script for frontend
### Updated Generation Endpoint
**POST /api/tts** (modified)
- Now accepts optional `segments` array
- If segments provided, uses them directly (respecting user edits)
- If no segments, falls back to original text-based segmentation
- Maintains backward compatibility
### Frontend Components
**New: ScriptReviewSection**
- Displays all segments with editable speaker dropdowns
- Allows users to change speaker for any segment
- Provides "Skip Review" option for quick generation
- Mobile-responsive design
**Updated: VoiceAssignmentSection**
- Button changes from "Generate Audiobook" to "Next: Review Script"
- Adds "Skip Review & Generate" option
**Updated: App Component**
- Adds 'review' phase to workflow
- Manages script segments state
- Handles segment editing
## Benefits
1. **Transparency**: Users can see exactly how the AI interpreted their text
2. **Control**: Users can correct any mistakes before generation
3. **Flexibility**: Users can skip review if they trust the AI
4. **Better Results**: Ensures the final audiobook matches user expectations
## Requirements Added
- **Requirement 15**: Complete specification for script review feature
- 8 acceptance criteria covering all aspects
- API endpoints, UI components, and user interactions
## Design Updates
- Added ScriptReviewSection component
- Added /api/tts/script endpoint
- Updated data models (ScriptSegment, ScriptRequest, ScriptResponse)
- Added 5 new correctness properties (Properties 32-35)
- Updated application workflow to include review phase
## Implementation Tasks
Added 8 new tasks (18-25) covering:
- Backend script generation endpoint
- Updated TTS generation to accept edited scripts
- Frontend API client updates
- ScriptReviewSection component
- App component workflow updates
- VoiceAssignmentSection updates
- Documentation
- Integration testing
## Testing Strategy
- Property tests for script completeness and structure
- Unit tests for all new components and endpoints
- Integration tests for complete workflow
- Manual testing with various text samples
## Future Enhancements
Potential improvements for later:
- Inline editing of segment text
- Merge/split segments
- Bulk speaker assignment
- Save/load script templates
- Export script as text file

View File

@@ -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

View File

@@ -15,6 +15,7 @@ The Text to Audiobook system is a production-ready React TypeScript single-page
- **KPipeline**: The Kokoro library's pipeline object for text-to-speech synthesis
- **Segment**: A portion of text assigned to a specific role for synthesis
- **Role Marker**: Text patterns that identify speakers (e.g., "Alice:", "[Narrator]")
- **Script**: The complete breakdown of text into segments with speaker assignments, displayed for user review and editing
## Requirements
@@ -192,3 +193,18 @@ The Text to Audiobook system is a production-ready React TypeScript single-page
4. WHEN Ollama is unavailable or fails THEN the Backend SHALL fall back to pattern-based role detection
5. WHEN both AI detection and pattern detection find roles THEN the Backend SHALL merge and deduplicate the results
6. THE Backend SHALL configure Ollama connection using environment variable OLLAMA_BASE_URL with default http://localhost:11434
### Requirement 15
**User Story:** As a user, I want to review and edit the AI-generated script showing which character speaks each line, so that I can correct any mistakes before generating the audiobook.
#### Acceptance Criteria
1. WHEN the user completes voice assignment THEN the Frontend SHALL request a script preview from the Backend before generation
2. WHEN the Backend receives a script preview request THEN the Backend SHALL use AI to segment the text and return a list of segments with speaker assignments
3. WHEN the script preview is received THEN the Frontend SHALL display a new "Review Script" phase showing each segment with its assigned speaker
4. WHEN displaying script segments THEN the Frontend SHALL show each segment in a text box with a dropdown to select the speaker
5. WHEN the user changes a speaker assignment for a segment THEN the Frontend SHALL update the segment mapping
6. WHEN the user is satisfied with the script THEN the Frontend SHALL enable a "Generate Audiobook" button
7. WHEN the user clicks "Generate Audiobook" THEN the Frontend SHALL send the edited script segments to the Backend for synthesis
8. THE Frontend SHALL allow users to skip the review step with a "Skip Review" option that proceeds directly to generation

View File

@@ -443,7 +443,7 @@
- Test skip review bypasses review phase
- _Requirements: 15.1, 15.8_
- [ ] 23. Update VoiceAssignmentSection to trigger script generation
- [x] 23. Update VoiceAssignmentSection to trigger script generation
- Change "Generate Audiobook" button to "Next: Review Script"
- Add "Skip Review & Generate" button as alternative
- Update button handlers to call appropriate methods