1use console::{style, Style};
6use std::collections::HashMap;
7
8pub struct HelpSystem {
10 pub command_help: HashMap<String, CommandHelp>,
12 general_tips: Vec<HelpTip>,
14}
15
16#[derive(Debug, Clone)]
18pub struct CommandHelp {
19 pub description: String,
21 pub detailed: String,
23 pub examples: Vec<HelpExample>,
25 pub related: Vec<String>,
27 pub troubleshooting: Vec<HelpTip>,
29}
30
31#[derive(Debug, Clone)]
33pub struct HelpExample {
34 pub command: String,
36 pub description: String,
38 pub expected: Option<String>,
40}
41
42#[derive(Debug, Clone)]
44pub struct HelpTip {
45 pub title: String,
47 pub content: String,
49 pub level: TipLevel,
51}
52
53#[derive(Debug, Clone, PartialEq)]
55pub enum TipLevel {
56 Info,
57 Warning,
58 Error,
59}
60
61impl HelpSystem {
62 pub fn new() -> Self {
64 let mut help_system = Self {
65 command_help: HashMap::new(),
66 general_tips: Vec::new(),
67 };
68
69 help_system.load_command_help();
70 help_system.load_general_tips();
71 help_system
72 }
73
74 pub fn get_command_help(&self, command: &str) -> Option<&CommandHelp> {
76 self.command_help.get(command)
77 }
78
79 pub fn display_command_help(&self, command: &str) -> String {
81 if let Some(help) = self.get_command_help(command) {
82 self.format_command_help(command, help)
83 } else {
84 self.format_unknown_command(command)
85 }
86 }
87
88 pub fn get_contextual_help(&self, context: &str) -> Vec<String> {
90 let mut suggestions = Vec::new();
91
92 match context {
93 "voice_not_found" => {
94 suggestions.push("List available voices with: voirs list-voices".to_string());
95 suggestions
96 .push("Download a voice with: voirs download-voice <voice-id>".to_string());
97 }
98 "model_not_found" => {
99 suggestions.push("List available models with: voirs list-models".to_string());
100 suggestions
101 .push("Download a model with: voirs download-model <model-id>".to_string());
102 }
103 "file_not_found" => {
104 suggestions.push("Check if the file path is correct".to_string());
105 suggestions.push("Use absolute paths for clarity".to_string());
106 }
107 "permission_denied" => {
108 suggestions.push("Check file/directory permissions".to_string());
109 suggestions.push("Try running with appropriate permissions".to_string());
110 }
111 "gpu_error" => {
112 suggestions.push("Check GPU availability with: voirs test --gpu".to_string());
113 suggestions.push("Fallback to CPU mode by removing --gpu flag".to_string());
114 }
115 _ => {
116 suggestions.push("Use 'voirs guide' for general help".to_string());
117 suggestions
118 .push("Use 'voirs guide <command>' for command-specific help".to_string());
119 }
120 }
121
122 suggestions
123 }
124
125 pub fn display_command_overview(&self) -> String {
127 let mut output = String::new();
128
129 output.push_str(&format!(
130 "{}\n\n",
131 style("VoiRS CLI Commands").bold().cyan()
132 ));
133
134 let categories = vec![
135 (
136 "Synthesis",
137 vec!["synthesize", "synthesize-file", "batch", "interactive"],
138 ),
139 (
140 "Advanced Voice Features",
141 vec!["emotion", "clone", "convert", "sing", "spatial"],
142 ),
143 (
144 "Voice Management",
145 vec!["list-voices", "voice-info", "download-voice"],
146 ),
147 (
148 "Model Management",
149 vec![
150 "list-models",
151 "download-model",
152 "benchmark-models",
153 "optimize-model",
154 ],
155 ),
156 ("System", vec!["config", "test", "server", "capabilities"]),
157 ];
158
159 for (category, commands) in categories {
160 output.push_str(&format!("{}\n", style(category).bold().yellow()));
161
162 for cmd in commands {
163 if let Some(help) = self.get_command_help(cmd) {
164 output.push_str(&format!(
165 " {} - {}\n",
166 style(cmd).green(),
167 help.description
168 ));
169 }
170 }
171 output.push('\n');
172 }
173
174 output.push_str(&format!(
175 "\n{}\n",
176 style("Use 'voirs guide <command>' for detailed information about a specific command.")
177 .dim()
178 ));
179
180 output
181 }
182
183 fn format_command_help(&self, command: &str, help: &CommandHelp) -> String {
185 let mut output = String::new();
186
187 output.push_str(&format!(
189 "{}\n",
190 style(format!("voirs {}", command)).bold().cyan()
191 ));
192 output.push_str(&format!("{}\n\n", help.description));
193
194 if !help.detailed.is_empty() {
196 output.push_str(&format!("{}\n", style("Description:").bold().yellow()));
197 output.push_str(&format!("{}\n\n", help.detailed));
198 }
199
200 if !help.examples.is_empty() {
202 output.push_str(&format!("{}\n", style("Examples:").bold().yellow()));
203 for example in &help.examples {
204 output.push_str(&format!(" {}\n", style(&example.command).green()));
205 output.push_str(&format!(" {}\n", example.description));
206
207 if let Some(expected) = &example.expected {
208 output.push_str(&format!(" Expected: {}\n", style(expected).dim()));
209 }
210 output.push('\n');
211 }
212 }
213
214 if !help.related.is_empty() {
216 output.push_str(&format!("{}\n", style("Related Commands:").bold().yellow()));
217 for related in &help.related {
218 output.push_str(&format!(" voirs {}\n", style(related).green()));
219 }
220 output.push('\n');
221 }
222
223 if !help.troubleshooting.is_empty() {
225 output.push_str(&format!("{}\n", style("Troubleshooting:").bold().yellow()));
226 for tip in &help.troubleshooting {
227 let tip_style = match tip.level {
228 TipLevel::Info => Style::new().blue(),
229 TipLevel::Warning => Style::new().yellow(),
230 TipLevel::Error => Style::new().red(),
231 };
232
233 output.push_str(&format!(
234 " {} {}\n",
235 tip_style.apply_to("•"),
236 style(&tip.title).bold()
237 ));
238 output.push_str(&format!(" {}\n", tip.content));
239 }
240 }
241
242 output
243 }
244
245 fn format_unknown_command(&self, command: &str) -> String {
247 let mut output = String::new();
248
249 output.push_str(&format!(
250 "{}\n\n",
251 style(format!("Unknown command: '{}'", command))
252 .red()
253 .bold()
254 ));
255
256 let similar = self.find_similar_commands(command);
258 if !similar.is_empty() {
259 output.push_str(&format!("{}\n", style("Did you mean:").yellow()));
260 for suggestion in similar {
261 output.push_str(&format!(" voirs {}\n", style(suggestion).green()));
262 }
263 output.push('\n');
264 }
265
266 output.push_str(&format!(
267 "{}\n",
268 style("Use 'voirs guide' to see all available commands.").dim()
269 ));
270
271 output
272 }
273
274 fn find_similar_commands(&self, input: &str) -> Vec<String> {
276 let mut similar = Vec::new();
277
278 for command in self.command_help.keys() {
279 if command.contains(input) || input.contains(command) {
280 similar.push(command.clone());
281 }
282 }
283
284 similar.truncate(3);
286 similar
287 }
288
289 fn load_command_help(&mut self) {
291 self.add_synthesize_help();
293 self.add_synthesize_file_help();
294 self.add_batch_help();
295 self.add_interactive_help();
296
297 self.add_emotion_help();
299 self.add_clone_help();
300 self.add_convert_help();
301 self.add_sing_help();
302 self.add_spatial_help();
303
304 self.add_list_voices_help();
306 self.add_voice_info_help();
307 self.add_download_voice_help();
308
309 self.add_list_models_help();
311 self.add_download_model_help();
312 self.add_benchmark_models_help();
313 self.add_optimize_model_help();
314
315 self.add_config_help();
317 self.add_test_help();
318 self.add_server_help();
319 self.add_guide_help();
320 self.add_capabilities_help();
321 }
322
323 fn load_general_tips(&mut self) {
325 self.general_tips.extend(vec![
326 HelpTip {
327 title: "Getting Started".to_string(),
328 content: "Run 'voirs test' to verify your installation and download a basic voice.".to_string(),
329 level: TipLevel::Info,
330 },
331 HelpTip {
332 title: "Configuration".to_string(),
333 content: "Use 'voirs config --init' to create a configuration file with your preferences.".to_string(),
334 level: TipLevel::Info,
335 },
336 HelpTip {
337 title: "Performance".to_string(),
338 content: "Enable GPU acceleration with --gpu flag for faster synthesis on supported hardware.".to_string(),
339 level: TipLevel::Info,
340 },
341 ]);
342 }
343
344 fn add_synthesize_help(&mut self) {
346 self.command_help.insert("synthesize".to_string(), CommandHelp {
347 description: "Convert text to speech using neural synthesis".to_string(),
348 detailed: "The synthesize command processes input text and generates high-quality speech audio. \
349 It supports various audio formats, speaking rates, pitch adjustments, and quality levels.".to_string(),
350 examples: vec![
351 HelpExample {
352 command: "voirs synthesize \"Hello, world!\"".to_string(),
353 description: "Basic synthesis with default settings".to_string(),
354 expected: Some("Creates audio file with generated filename".to_string()),
355 },
356 HelpExample {
357 command: "voirs synthesize \"Hello, world!\" --output hello.wav".to_string(),
358 description: "Synthesize to specific output file".to_string(),
359 expected: Some("Creates hello.wav".to_string()),
360 },
361 HelpExample {
362 command: "voirs synthesize \"Fast speech\" --rate 1.5 --quality ultra".to_string(),
363 description: "Faster speech with highest quality".to_string(),
364 expected: None,
365 },
366 ],
367 related: vec!["synthesize-file".to_string(), "batch".to_string(), "interactive".to_string()],
368 troubleshooting: vec![
369 HelpTip {
370 title: "Slow synthesis".to_string(),
371 content: "Try using --gpu flag for hardware acceleration or lower quality settings".to_string(),
372 level: TipLevel::Info,
373 },
374 HelpTip {
375 title: "Quality issues".to_string(),
376 content: "Use --quality ultra for best results, or check voice compatibility".to_string(),
377 level: TipLevel::Warning,
378 },
379 ],
380 });
381 }
382
383 fn add_synthesize_file_help(&mut self) {
384 self.command_help.insert("synthesize-file".to_string(), CommandHelp {
385 description: "Synthesize text from input file".to_string(),
386 detailed: "Process a text file and generate speech audio. The input file is read line by line, \
387 with each line treated as a separate synthesis request.".to_string(),
388 examples: vec![
389 HelpExample {
390 command: "voirs synthesize-file input.txt".to_string(),
391 description: "Synthesize all lines from input.txt".to_string(),
392 expected: Some("Creates multiple audio files".to_string()),
393 },
394 HelpExample {
395 command: "voirs synthesize-file input.txt --output-dir ./audio/".to_string(),
396 description: "Output to specific directory".to_string(),
397 expected: None,
398 },
399 ],
400 related: vec!["synthesize".to_string(), "batch".to_string()],
401 troubleshooting: vec![],
402 });
403 }
404
405 fn add_batch_help(&mut self) {
406 self.command_help.insert("batch".to_string(), CommandHelp {
407 description: "Process multiple texts with parallel synthesis".to_string(),
408 detailed: "Batch processing supports various input formats (TXT, CSV, JSON, JSONL) and \
409 provides efficient parallel processing with progress tracking and resume capability.".to_string(),
410 examples: vec![
411 HelpExample {
412 command: "voirs batch texts.csv --workers 4".to_string(),
413 description: "Process CSV file with 4 parallel workers".to_string(),
414 expected: None,
415 },
416 HelpExample {
417 command: "voirs batch data.jsonl --resume".to_string(),
418 description: "Resume interrupted batch processing".to_string(),
419 expected: None,
420 },
421 ],
422 related: vec!["synthesize".to_string(), "synthesize-file".to_string()],
423 troubleshooting: vec![
424 HelpTip {
425 title: "Memory usage".to_string(),
426 content: "Reduce --workers count if experiencing high memory usage".to_string(),
427 level: TipLevel::Warning,
428 },
429 ],
430 });
431 }
432
433 fn add_interactive_help(&mut self) {
434 self.command_help.insert(
435 "interactive".to_string(),
436 CommandHelp {
437 description: "Real-time interactive synthesis shell".to_string(),
438 detailed:
439 "Interactive mode provides a shell-like interface for real-time text-to-speech \
440 synthesis with session management and live audio playback."
441 .to_string(),
442 examples: vec![
443 HelpExample {
444 command: "voirs interactive".to_string(),
445 description: "Start interactive mode with default voice".to_string(),
446 expected: Some("Opens interactive shell".to_string()),
447 },
448 HelpExample {
449 command: "voirs interactive --voice en-us-female".to_string(),
450 description: "Start with specific voice".to_string(),
451 expected: None,
452 },
453 ],
454 related: vec!["synthesize".to_string()],
455 troubleshooting: vec![HelpTip {
456 title: "Audio playback issues".to_string(),
457 content:
458 "Use --no-audio flag to disable playback if experiencing audio problems"
459 .to_string(),
460 level: TipLevel::Warning,
461 }],
462 },
463 );
464 }
465
466 fn add_list_voices_help(&mut self) {
467 self.command_help.insert(
468 "list-voices".to_string(),
469 CommandHelp {
470 description: "Display available voices".to_string(),
471 detailed: "List all installed and available voices with their characteristics, \
472 languages, and installation status."
473 .to_string(),
474 examples: vec![
475 HelpExample {
476 command: "voirs list-voices".to_string(),
477 description: "Show all available voices".to_string(),
478 expected: None,
479 },
480 HelpExample {
481 command: "voirs list-voices --language en".to_string(),
482 description: "Filter by English voices only".to_string(),
483 expected: None,
484 },
485 ],
486 related: vec!["voice-info".to_string(), "download-voice".to_string()],
487 troubleshooting: vec![],
488 },
489 );
490 }
491
492 fn add_voice_info_help(&mut self) {
493 self.command_help.insert(
494 "voice-info".to_string(),
495 CommandHelp {
496 description: "Get detailed information about a specific voice".to_string(),
497 detailed: "Display comprehensive information about a voice including metadata, \
498 quality metrics, and usage examples."
499 .to_string(),
500 examples: vec![HelpExample {
501 command: "voirs voice-info en-us-female".to_string(),
502 description: "Show details for English US female voice".to_string(),
503 expected: None,
504 }],
505 related: vec!["list-voices".to_string(), "download-voice".to_string()],
506 troubleshooting: vec![],
507 },
508 );
509 }
510
511 fn add_download_voice_help(&mut self) {
512 self.command_help.insert(
513 "download-voice".to_string(),
514 CommandHelp {
515 description: "Download and install a voice model".to_string(),
516 detailed: "Download voice models from the repository with progress tracking \
517 and checksum verification."
518 .to_string(),
519 examples: vec![HelpExample {
520 command: "voirs download-voice en-us-female".to_string(),
521 description: "Download English US female voice".to_string(),
522 expected: Some("Downloads and installs voice model".to_string()),
523 }],
524 related: vec!["list-voices".to_string(), "voice-info".to_string()],
525 troubleshooting: vec![HelpTip {
526 title: "Download fails".to_string(),
527 content: "Check internet connection and available disk space".to_string(),
528 level: TipLevel::Error,
529 }],
530 },
531 );
532 }
533
534 fn add_list_models_help(&mut self) {
535 self.command_help.insert(
536 "list-models".to_string(),
537 CommandHelp {
538 description: "Display available synthesis models".to_string(),
539 detailed: "List acoustic models, vocoders, and other synthesis components \
540 with compatibility and performance information."
541 .to_string(),
542 examples: vec![HelpExample {
543 command: "voirs list-models".to_string(),
544 description: "Show all available models".to_string(),
545 expected: None,
546 }],
547 related: vec!["download-model".to_string(), "benchmark-models".to_string()],
548 troubleshooting: vec![],
549 },
550 );
551 }
552
553 fn add_download_model_help(&mut self) {
554 self.command_help.insert(
555 "download-model".to_string(),
556 CommandHelp {
557 description: "Download and install synthesis models".to_string(),
558 detailed: "Download acoustic models, vocoders, and other synthesis components \
559 required for text-to-speech synthesis."
560 .to_string(),
561 examples: vec![HelpExample {
562 command: "voirs download-model tacotron2-en".to_string(),
563 description: "Download Tacotron2 English model".to_string(),
564 expected: None,
565 }],
566 related: vec!["list-models".to_string(), "optimize-model".to_string()],
567 troubleshooting: vec![],
568 },
569 );
570 }
571
572 fn add_benchmark_models_help(&mut self) {
573 self.command_help.insert(
574 "benchmark-models".to_string(),
575 CommandHelp {
576 description: "Benchmark model performance".to_string(),
577 detailed: "Run performance tests on synthesis models to measure speed, \
578 quality, and resource usage."
579 .to_string(),
580 examples: vec![HelpExample {
581 command: "voirs benchmark-models tacotron2-en hifigan-en".to_string(),
582 description: "Benchmark multiple models".to_string(),
583 expected: None,
584 }],
585 related: vec!["list-models".to_string(), "optimize-model".to_string()],
586 troubleshooting: vec![],
587 },
588 );
589 }
590
591 fn add_optimize_model_help(&mut self) {
592 self.command_help.insert(
593 "optimize-model".to_string(),
594 CommandHelp {
595 description: "Optimize models for current hardware".to_string(),
596 detailed: "Apply hardware-specific optimizations to improve synthesis \
597 performance and reduce memory usage."
598 .to_string(),
599 examples: vec![HelpExample {
600 command: "voirs optimize-model tacotron2-en".to_string(),
601 description: "Optimize model for current hardware".to_string(),
602 expected: None,
603 }],
604 related: vec!["benchmark-models".to_string(), "list-models".to_string()],
605 troubleshooting: vec![],
606 },
607 );
608 }
609
610 fn add_config_help(&mut self) {
611 self.command_help.insert(
612 "config".to_string(),
613 CommandHelp {
614 description: "Manage configuration settings".to_string(),
615 detailed: "View, modify, and manage VoiRS configuration including \
616 default voices, quality settings, and preferences."
617 .to_string(),
618 examples: vec![
619 HelpExample {
620 command: "voirs config --show".to_string(),
621 description: "Display current configuration".to_string(),
622 expected: None,
623 },
624 HelpExample {
625 command: "voirs config --init".to_string(),
626 description: "Create default configuration file".to_string(),
627 expected: Some("Creates config.toml".to_string()),
628 },
629 ],
630 related: vec![],
631 troubleshooting: vec![],
632 },
633 );
634 }
635
636 fn add_test_help(&mut self) {
637 self.command_help.insert(
638 "test".to_string(),
639 CommandHelp {
640 description: "Test synthesis pipeline and installation".to_string(),
641 detailed: "Verify that VoiRS is properly installed and configured \
642 by running a test synthesis."
643 .to_string(),
644 examples: vec![
645 HelpExample {
646 command: "voirs test".to_string(),
647 description: "Run basic synthesis test".to_string(),
648 expected: Some("Creates test audio file".to_string()),
649 },
650 HelpExample {
651 command: "voirs test --play".to_string(),
652 description: "Test with audio playback".to_string(),
653 expected: Some("Plays synthesized audio".to_string()),
654 },
655 ],
656 related: vec!["config".to_string()],
657 troubleshooting: vec![HelpTip {
658 title: "Test fails".to_string(),
659 content: "Check that voices and models are installed with 'voirs list-voices'"
660 .to_string(),
661 level: TipLevel::Error,
662 }],
663 },
664 );
665 }
666
667 fn add_server_help(&mut self) {
668 self.command_help.insert(
669 "server".to_string(),
670 CommandHelp {
671 description: "Run VoiRS as HTTP API server".to_string(),
672 detailed: "Start a production-ready HTTP server providing REST API \
673 endpoints for synthesis, voice management, and system status."
674 .to_string(),
675 examples: vec![
676 HelpExample {
677 command: "voirs server".to_string(),
678 description: "Start server on default port 8080".to_string(),
679 expected: Some("Server runs at http://127.0.0.1:8080".to_string()),
680 },
681 HelpExample {
682 command: "voirs server --port 3000 --host 0.0.0.0".to_string(),
683 description: "Start server on custom address".to_string(),
684 expected: None,
685 },
686 ],
687 related: vec![],
688 troubleshooting: vec![HelpTip {
689 title: "Port already in use".to_string(),
690 content: "Use --port flag to specify a different port number".to_string(),
691 level: TipLevel::Error,
692 }],
693 },
694 );
695 }
696
697 fn add_guide_help(&mut self) {
698 self.command_help.insert("guide".to_string(), CommandHelp {
699 description: "Show detailed help and guides".to_string(),
700 detailed: "Display comprehensive help information, getting started guides, \
701 and examples for VoiRS commands. Use this to learn about specific \
702 commands or get an overview of available functionality.".to_string(),
703 examples: vec![
704 HelpExample {
705 command: "voirs guide".to_string(),
706 description: "Show overview of all commands".to_string(),
707 expected: Some("Lists all command categories".to_string()),
708 },
709 HelpExample {
710 command: "voirs guide synthesize".to_string(),
711 description: "Get detailed help for synthesize command".to_string(),
712 expected: Some("Shows usage, examples, and troubleshooting".to_string()),
713 },
714 HelpExample {
715 command: "voirs guide --getting-started".to_string(),
716 description: "Show getting started guide".to_string(),
717 expected: Some("Step-by-step setup instructions".to_string()),
718 },
719 HelpExample {
720 command: "voirs guide --examples".to_string(),
721 description: "Show examples for all commands".to_string(),
722 expected: Some("Command examples with descriptions".to_string()),
723 },
724 ],
725 related: vec!["test".to_string(), "config".to_string()],
726 troubleshooting: vec![
727 HelpTip {
728 title: "Need more help".to_string(),
729 content: "Visit the documentation or check the project repository for additional resources".to_string(),
730 level: TipLevel::Info,
731 },
732 ],
733 });
734 }
735
736 fn add_emotion_help(&mut self) {
738 self.command_help.insert("emotion".to_string(), CommandHelp {
739 description: "Control emotional expression in synthesized speech".to_string(),
740 detailed: "The emotion command allows you to modify the emotional tone and expression \
741 of synthesized speech. You can use predefined emotion presets, blend multiple \
742 emotions, or create custom emotion configurations.".to_string(),
743 examples: vec![
744 HelpExample {
745 command: "voirs emotion list".to_string(),
746 description: "List all available emotion presets".to_string(),
747 expected: Some("Shows emotions like happy, sad, angry, calm, etc.".to_string()),
748 },
749 HelpExample {
750 command: "voirs emotion synth --emotion happy --intensity 0.7 \"Hello world!\" output.wav".to_string(),
751 description: "Synthesize with happy emotion at 70% intensity".to_string(),
752 expected: Some("Creates emotionally expressive audio".to_string()),
753 },
754 HelpExample {
755 command: "voirs emotion blend --emotions happy,calm --weights 0.6,0.4 \"Text\" output.wav".to_string(),
756 description: "Blend multiple emotions with specified weights".to_string(),
757 expected: None,
758 },
759 HelpExample {
760 command: "voirs emotion create-preset --name custom --config emotion.json".to_string(),
761 description: "Create a custom emotion preset".to_string(),
762 expected: Some("Saves custom emotion configuration".to_string()),
763 },
764 ],
765 related: vec!["synthesize".to_string(), "convert".to_string()],
766 troubleshooting: vec![
767 HelpTip {
768 title: "Emotion not working".to_string(),
769 content: "Check if emotion models are downloaded and the voice supports emotional expression".to_string(),
770 level: TipLevel::Warning,
771 },
772 HelpTip {
773 title: "Intensity too high".to_string(),
774 content: "Reduce intensity value (0.0-1.0) if emotion sounds unnatural".to_string(),
775 level: TipLevel::Info,
776 },
777 ],
778 });
779 }
780
781 fn add_clone_help(&mut self) {
782 self.command_help.insert("clone".to_string(), CommandHelp {
783 description: "Clone voices from reference audio samples".to_string(),
784 detailed: "Voice cloning allows you to create new voices from reference audio samples. \
785 You can use multiple reference files for better quality, and the system \
786 supports both quick cloning and detailed speaker adaptation.".to_string(),
787 examples: vec![
788 HelpExample {
789 command: "voirs clone clone --reference-files voice_samples/*.wav --text \"Hello world\" output.wav".to_string(),
790 description: "Clone voice from multiple reference files".to_string(),
791 expected: Some("Creates audio with cloned voice".to_string()),
792 },
793 HelpExample {
794 command: "voirs clone quick --reference-files sample.wav --text \"Hello world\" output.wav".to_string(),
795 description: "Quick cloning from single reference file".to_string(),
796 expected: Some("Faster but potentially lower quality cloning".to_string()),
797 },
798 HelpExample {
799 command: "voirs clone list-profiles".to_string(),
800 description: "List cached speaker profiles".to_string(),
801 expected: Some("Shows previously cloned speaker profiles".to_string()),
802 },
803 HelpExample {
804 command: "voirs clone validate --reference-files samples/*.wav".to_string(),
805 description: "Validate reference audio quality for cloning".to_string(),
806 expected: Some("Reports audio quality and suitability".to_string()),
807 },
808 ],
809 related: vec!["convert".to_string(), "synthesize".to_string()],
810 troubleshooting: vec![
811 HelpTip {
812 title: "Poor cloning quality".to_string(),
813 content: "Use high-quality reference audio (16kHz+) with clear speech and minimal background noise".to_string(),
814 level: TipLevel::Warning,
815 },
816 HelpTip {
817 title: "Cloning fails".to_string(),
818 content: "Ensure reference files are at least 30 seconds of clear speech from the target speaker".to_string(),
819 level: TipLevel::Error,
820 },
821 ],
822 });
823 }
824
825 fn add_convert_help(&mut self) {
826 self.command_help.insert("convert".to_string(), CommandHelp {
827 description: "Convert and transform voice characteristics".to_string(),
828 detailed: "Voice conversion allows you to transform existing audio by changing \
829 speaker characteristics, age, gender, or other vocal properties. \
830 Supports both file-based and real-time conversion.".to_string(),
831 examples: vec![
832 HelpExample {
833 command: "voirs convert speaker --input source.wav --target-speaker target_voice --output converted.wav".to_string(),
834 description: "Convert to a different speaker".to_string(),
835 expected: Some("Creates audio with target speaker's voice".to_string()),
836 },
837 HelpExample {
838 command: "voirs convert age --input voice.wav --target-age 25 --output aged.wav".to_string(),
839 description: "Change apparent age of the speaker".to_string(),
840 expected: Some("Creates audio with modified age characteristics".to_string()),
841 },
842 HelpExample {
843 command: "voirs convert gender --input voice.wav --target male --output converted.wav".to_string(),
844 description: "Convert gender characteristics".to_string(),
845 expected: Some("Creates audio with modified gender characteristics".to_string()),
846 },
847 HelpExample {
848 command: "voirs convert morph --voice1 voice1.model --voice2 voice2.model --ratio 0.5".to_string(),
849 description: "Morph between two voice models".to_string(),
850 expected: Some("Creates blended voice characteristics".to_string()),
851 },
852 ],
853 related: vec!["clone".to_string(), "emotion".to_string()],
854 troubleshooting: vec![
855 HelpTip {
856 title: "Conversion artifacts".to_string(),
857 content: "Reduce conversion intensity or use higher quality settings".to_string(),
858 level: TipLevel::Warning,
859 },
860 HelpTip {
861 title: "Real-time conversion slow".to_string(),
862 content: "Use GPU acceleration or reduce audio quality for real-time processing".to_string(),
863 level: TipLevel::Info,
864 },
865 ],
866 });
867 }
868
869 fn add_sing_help(&mut self) {
870 self.command_help.insert("sing".to_string(), CommandHelp {
871 description: "Synthesize singing voice from musical scores".to_string(),
872 detailed: "Singing voice synthesis converts musical scores and lyrics into \
873 realistic singing. Supports various input formats including MusicXML, \
874 MIDI, and custom score formats with advanced vocal technique controls.".to_string(),
875 examples: vec![
876 HelpExample {
877 command: "voirs sing score --score score.musicxml --voice singer.model --output song.wav".to_string(),
878 description: "Synthesize from MusicXML score".to_string(),
879 expected: Some("Creates singing audio from musical score".to_string()),
880 },
881 HelpExample {
882 command: "voirs sing midi --midi input.mid --lyrics lyrics.txt --voice singer.model --output song.wav".to_string(),
883 description: "Synthesize from MIDI file with lyrics".to_string(),
884 expected: Some("Creates singing audio from MIDI and lyrics".to_string()),
885 },
886 HelpExample {
887 command: "voirs sing create-voice --samples singing_samples/ --output singer.model".to_string(),
888 description: "Create singing voice model from samples".to_string(),
889 expected: Some("Trains custom singing voice model".to_string()),
890 },
891 HelpExample {
892 command: "voirs sing effects --input song.wav --vibrato 1.2 --expression happy --output processed.wav".to_string(),
893 description: "Apply singing effects and expression".to_string(),
894 expected: Some("Adds vocal effects to singing audio".to_string()),
895 },
896 ],
897 related: vec!["emotion".to_string(), "synthesize".to_string()],
898 troubleshooting: vec![
899 HelpTip {
900 title: "Pitch issues".to_string(),
901 content: "Check score format and ensure correct pitch notation".to_string(),
902 level: TipLevel::Warning,
903 },
904 HelpTip {
905 title: "Timing problems".to_string(),
906 content: "Verify tempo and rhythm marks in the musical score".to_string(),
907 level: TipLevel::Warning,
908 },
909 ],
910 });
911 }
912
913 fn add_spatial_help(&mut self) {
914 self.command_help.insert("spatial".to_string(), CommandHelp {
915 description: "Create 3D spatial audio with positioning effects".to_string(),
916 detailed: "Spatial audio synthesis creates immersive 3D soundscapes by applying \
917 Head-Related Transfer Functions (HRTF) and room acoustics. Supports \
918 binaural rendering for headphones and multi-channel output for speakers.".to_string(),
919 examples: vec![
920 HelpExample {
921 command: "voirs spatial synth --text \"hello\" --position 1,0,0 --output 3d_audio.wav".to_string(),
922 description: "Synthesize with 3D positioning".to_string(),
923 expected: Some("Creates 3D positioned audio".to_string()),
924 },
925 HelpExample {
926 command: "voirs spatial hrtf --input mono.wav --position x,y,z --output binaural.wav".to_string(),
927 description: "Apply HRTF processing to existing audio".to_string(),
928 expected: Some("Creates binaural audio for headphones".to_string()),
929 },
930 HelpExample {
931 command: "voirs spatial room --input voice.wav --room-config room.json --output spatial.wav".to_string(),
932 description: "Apply room acoustics simulation".to_string(),
933 expected: Some("Creates audio with room acoustics".to_string()),
934 },
935 HelpExample {
936 command: "voirs spatial movement --input voice.wav --path movement.json --output dynamic.wav".to_string(),
937 description: "Apply dynamic movement path".to_string(),
938 expected: Some("Creates audio with moving sound source".to_string()),
939 },
940 ],
941 related: vec!["synthesize".to_string()],
942 troubleshooting: vec![
943 HelpTip {
944 title: "HRTF not working".to_string(),
945 content: "Check if HRTF dataset is installed and compatible with your setup".to_string(),
946 level: TipLevel::Warning,
947 },
948 HelpTip {
949 title: "Poor spatial effect".to_string(),
950 content: "Use high-quality headphones and ensure proper audio driver configuration".to_string(),
951 level: TipLevel::Info,
952 },
953 ],
954 });
955 }
956
957 fn add_capabilities_help(&mut self) {
958 self.command_help.insert("capabilities".to_string(), CommandHelp {
959 description: "Show system capabilities and feature availability".to_string(),
960 detailed: "The capabilities command provides comprehensive information about \
961 available features, system requirements, configuration status, and \
962 hardware capabilities. Use this to troubleshoot issues and verify \
963 your VoiRS installation.".to_string(),
964 examples: vec![
965 HelpExample {
966 command: "voirs capabilities list".to_string(),
967 description: "Show all available features and their status".to_string(),
968 expected: Some("Lists features with availability status".to_string()),
969 },
970 HelpExample {
971 command: "voirs capabilities check emotion".to_string(),
972 description: "Check if emotion control feature is available".to_string(),
973 expected: Some("Shows emotion feature status and requirements".to_string()),
974 },
975 HelpExample {
976 command: "voirs capabilities requirements".to_string(),
977 description: "Show system requirements for all features".to_string(),
978 expected: Some("Lists hardware and software requirements".to_string()),
979 },
980 HelpExample {
981 command: "voirs capabilities test cloning".to_string(),
982 description: "Test voice cloning functionality".to_string(),
983 expected: Some("Runs functional tests for voice cloning".to_string()),
984 },
985 ],
986 related: vec!["test".to_string(), "config".to_string()],
987 troubleshooting: vec![
988 HelpTip {
989 title: "Feature unavailable".to_string(),
990 content: "Check if required models are installed and feature is enabled in configuration".to_string(),
991 level: TipLevel::Warning,
992 },
993 HelpTip {
994 title: "System requirements".to_string(),
995 content: "Use 'voirs capabilities requirements' to check specific hardware needs".to_string(),
996 level: TipLevel::Info,
997 },
998 ],
999 });
1000 }
1001}
1002
1003impl Default for HelpSystem {
1004 fn default() -> Self {
1005 Self::new()
1006 }
1007}
1008
1009pub fn display_getting_started() -> String {
1011 let mut output = String::new();
1012
1013 output.push_str(&format!(
1014 "{}\n\n",
1015 style("Getting Started with VoiRS").bold().cyan()
1016 ));
1017
1018 let steps = vec![
1019 (
1020 "1. Test Installation",
1021 "voirs test",
1022 "Verify VoiRS is working correctly",
1023 ),
1024 (
1025 "2. List Voices",
1026 "voirs list-voices",
1027 "See available voices",
1028 ),
1029 (
1030 "3. Download a Voice",
1031 "voirs download-voice en-us-female",
1032 "Get a voice for synthesis",
1033 ),
1034 (
1035 "4. Synthesize Text",
1036 "voirs synthesize \"Hello, world!\"",
1037 "Create your first audio",
1038 ),
1039 (
1040 "5. Interactive Mode",
1041 "voirs interactive",
1042 "Try real-time synthesis",
1043 ),
1044 ];
1045
1046 for (step, command, description) in steps {
1047 output.push_str(&format!("{}\n", style(step).bold().yellow()));
1048 output.push_str(&format!(" {}\n", style(command).green()));
1049 output.push_str(&format!(" {}\n\n", description));
1050 }
1051
1052 output.push_str(&format!(
1053 "{}\n",
1054 style("Use 'voirs help <command>' for detailed information about specific commands.").dim()
1055 ));
1056
1057 output
1058}