UNPKG

aiabm

Version:

AI Audiobook Maker - Convert PDFs and text files to audiobooks using OpenAI TTS or Thorsten-Voice (native German)

365 lines (327 loc) 12.2 kB
/** * UI Helper utilities for better user experience * Provides enhanced prompts, progress bars, and visual feedback */ const chalk = require('chalk'); const ora = require('ora'); class UIHelpers { /** * Creates an enhanced welcome banner with system info */ static showWelcomeBanner(version = '5.1.1') { console.clear(); console.log( chalk.cyan(` ╔══════════════════════════════════════════════════════════════════════╗ ║ ║ ║ 🎧 AI AUDIOBOOK MAKER v${version} 🎧 ║ ║ ║ ║ Transform PDFs & Text into Audiobooks ║ ║ OpenAI TTS & Thorsten-Voice TTS ║ ║ ║ ║ ✨ Enhanced Security • 🧪 Comprehensive Testing • 🚀 Fast & Reliable ║ ║ ║ ╚══════════════════════════════════════════════════════════════════════╝ `) ); // Show helpful tips console.log(chalk.gray('💡 Tips:')); console.log(chalk.gray(' • Use arrow keys to navigate menus')); console.log(chalk.gray(' • Drag & drop files into the terminal')); console.log(chalk.gray(' • Press Ctrl+C anytime to exit safely')); console.log(''); } /** * Creates enhanced main menu with better descriptions */ static getMainMenuChoices() { return [ { name: '📖 Convert file to audiobook', value: 'convert', description: 'Transform your PDF or text file into high-quality audio' }, { name: '🎤 Preview voices', value: 'preview', description: 'Listen to different voices before choosing' }, { name: '⚙️ Manage configuration', value: 'config', description: 'Set up API keys, preferences, and settings' }, { name: '📊 View session history', value: 'history', description: 'Resume previous conversions or check past projects' }, { name: '🧹 Clear cache & data', value: 'clear_cache', description: 'Free up disk space by removing temporary files' }, { name: '❓ Help & troubleshooting', value: 'help', description: 'Get help with common issues and usage tips' }, { name: '❌ Exit application', value: 'exit', description: 'Close AI Audiobook Maker' }, ]; } /** * Creates enhanced progress bar with context */ static createProgressBar(message, options = {}) { const defaultOptions = { text: message, spinner: 'dots', color: 'cyan', prefixText: '🎧', }; return ora({ ...defaultOptions, ...options }); } /** * Shows processing stages with visual feedback */ static showProcessingStages(currentStage, totalStages, stageName) { const progress = Math.round((currentStage / totalStages) * 100); const progressBar = '█'.repeat(Math.floor(progress / 5)) + '▒'.repeat(20 - Math.floor(progress / 5)); console.log(chalk.cyan('\n📋 Processing Stages:')); console.log(chalk.gray(` Stage ${currentStage}/${totalStages}: ${stageName}`)); console.log(chalk.cyan(` [${progressBar}] ${progress}%\n`)); } /** * Enhanced file selection prompt with file info */ static async promptFileSelection(files, context = '') { if (files.length === 0) { console.log(chalk.yellow('📂 No recent files found. Let\'s browse for a file instead.\n')); return null; } console.log(chalk.cyan(`\n📁 Recent ${context} Files:`)); console.log(chalk.gray(' Select a file from your recent conversions\n')); const choices = files.map(file => ({ name: `${file.name} ${chalk.gray(`(${file.size || 'Unknown size'})`)}`, value: file.path, short: file.name })); choices.push( { name: chalk.gray('─'.repeat(50)), disabled: true }, { name: '📂 Browse for different file', value: 'browse' }, { name: '🔙 Back to main menu', value: 'back' } ); return choices; } /** * Enhanced confirmation prompt with details */ static async confirmAction(action, details = {}) { console.log(chalk.yellow(`\n⚠️ Confirm ${action}:`)); if (details.cost) { console.log(chalk.gray(` 💰 Estimated cost: ${details.cost}`)); } if (details.time) { console.log(chalk.gray(` ⏱️ Estimated time: ${details.time}`)); } if (details.size) { console.log(chalk.gray(` 📊 File size: ${details.size}`)); } if (details.chunks) { console.log(chalk.gray(` 🔧 Processing chunks: ${details.chunks}`)); } return { type: 'confirm', name: 'confirmed', message: `Proceed with ${action}?`, default: true }; } /** * Success message with next steps */ static showSuccess(message, nextSteps = []) { console.log(chalk.green(`\n✅ ${message}\n`)); if (nextSteps.length > 0) { console.log(chalk.cyan('🚀 What\'s next:')); nextSteps.forEach((step, index) => { console.log(chalk.gray(` ${index + 1}. ${step}`)); }); console.log(''); } } /** * Error message with helpful suggestions */ static showError(error, suggestions = []) { console.log(chalk.red(`\n❌ Error: ${error}\n`)); if (suggestions.length > 0) { console.log(chalk.yellow('💡 Try these solutions:')); suggestions.forEach((suggestion, index) => { console.log(chalk.gray(` ${index + 1}. ${suggestion}`)); }); console.log(''); } } /** * Provider selection with detailed info */ static getProviderChoices() { return [ { name: '☁️ OpenAI TTS (Premium Cloud)', value: 'openai', description: 'High-quality voices • 6 voice options • Requires API key • ~$0.015/1K chars' }, { name: '🇩🇪 Thorsten-Voice (German Local)', value: 'thorsten', description: 'Native German pronunciation • Completely FREE • Runs locally • Auto-install' }, { name: '❓ Help me choose', value: 'help', description: 'Get recommendations based on your needs' }, { name: '🔙 Back to main menu', value: 'back', description: 'Return to previous menu' } ]; } /** * Voice selection with preview info */ static getVoiceChoices(provider) { const baseChoices = { openai: [ { name: '🎵 Alloy (Neutral, versatile)', value: 'alloy', description: 'Great for most content types' }, { name: '🎭 Echo (Expressive, dynamic)', value: 'echo', description: 'Perfect for dramatic content' }, { name: '📖 Fable (Warm, storytelling)', value: 'fable', description: 'Ideal for books and narratives' }, { name: '🎯 Onyx (Deep, authoritative)', value: 'onyx', description: 'Professional and commanding' }, { name: '✨ Nova (Bright, engaging)', value: 'nova', description: 'Energetic and clear' }, { name: '🌟 Shimmer (Gentle, soothing)', value: 'shimmer', description: 'Calm and pleasant' }, ], thorsten: [ { name: '🇩🇪 Thorsten (Standard German)', value: 'thorsten', description: 'Clear, standard German pronunciation' }, { name: '🎭 Thorsten Emotional (Expressive)', value: 'thorsten_emotional', description: 'More expressive German voice' }, ] }; return baseChoices[provider] || []; } /** * Shows detailed processing information */ static showProcessingInfo(fileData, options) { console.log(chalk.cyan('\n📋 Processing Summary:')); console.log(chalk.gray(' File: ') + chalk.white(fileData.fileName || 'Unknown')); console.log(chalk.gray(' Characters: ') + chalk.white(fileData.characterCount?.toLocaleString() || '0')); console.log(chalk.gray(' Words: ') + chalk.white(fileData.wordCount?.toLocaleString() || '0')); if (fileData.pageCount) { console.log(chalk.gray(' Pages: ') + chalk.white(fileData.pageCount)); } console.log(chalk.gray(' Provider: ') + chalk.white(options.provider || 'Unknown')); console.log(chalk.gray(' Voice: ') + chalk.white(options.voice || 'Unknown')); if (options.estimatedCost) { console.log(chalk.gray(' Estimated cost: ') + chalk.green(`$${options.estimatedCost}`)); } if (options.estimatedTime) { console.log(chalk.gray(' Estimated time: ') + chalk.yellow(options.estimatedTime)); } console.log(''); } /** * Animated loading with rotating messages */ static createRotatingLoader(messages, interval = 3000) { let currentIndex = 0; const spinner = this.createProgressBar(messages[0]); const rotateMessages = setInterval(() => { currentIndex = (currentIndex + 1) % messages.length; spinner.text = messages[currentIndex]; }, interval); // Return spinner with cleanup function spinner._cleanup = () => clearInterval(rotateMessages); return spinner; } /** * Shows help content for different topics */ static showHelpContent(topic = 'general') { const helpContent = { general: { title: '🆘 AI Audiobook Maker Help', sections: [ { title: '🚀 Getting Started', items: [ 'Choose "Convert file to audiobook" to start', 'Select your TTS provider (OpenAI or Thorsten)', 'Pick a voice and adjust settings', 'Let the magic happen!' ] }, { title: '💰 Cost Information', items: [ 'OpenAI TTS: ~$0.015 per 1,000 characters', 'Thorsten-Voice: Completely FREE', 'Check file size before processing' ] }, { title: '🔧 Troubleshooting', items: [ 'Ensure you have a stable internet connection', 'Check file size limits (50MB PDF, 1M chars text)', 'Verify API key is valid and has credit', 'Try clearing cache if issues persist' ] } ] }, providers: { title: '🎙️ TTS Provider Guide', sections: [ { title: '☁️ OpenAI TTS', items: [ 'Premium cloud-based text-to-speech', 'Requires OpenAI API key with billing setup', '6 high-quality voice options', 'Fast processing, excellent quality', 'Supports multiple languages' ] }, { title: '🇩🇪 Thorsten-Voice', items: [ 'Native German TTS (completely free)', 'Runs entirely on your computer', 'Authentic German pronunciation', 'No internet required after setup', 'Automatic installation of dependencies' ] } ] } }; const content = helpContent[topic] || helpContent.general; console.log(chalk.cyan(`\n${content.title}`)); console.log(chalk.gray('─'.repeat(60))); content.sections.forEach(section => { console.log(chalk.yellow(`\n${section.title}:`)); section.items.forEach(item => { console.log(chalk.gray(` • ${item}`)); }); }); console.log(chalk.gray('\n─'.repeat(60))); console.log(chalk.cyan('💡 Need more help? Visit: https://github.com/iamthamanic/AI-Audiobook-Maker\n')); } } module.exports = UIHelpers;