Interactive configuration setup.
(args: Namespace, config_data: dict)
| 104 | |
| 105 | |
| 106 | def _interactive_init(args: Namespace, config_data: dict) -> int: |
| 107 | """Interactive configuration setup.""" |
| 108 | ensure_config_dir() |
| 109 | |
| 110 | if CONFIG_FILE.exists() and not getattr(args, "force", False): |
| 111 | output.warn(f"Config file already exists: {CONFIG_FILE}") |
| 112 | output.hint("Use 'videocaptioner config init --force' to overwrite it.") |
| 113 | output.hint("Use 'videocaptioner config edit' to modify the existing file.") |
| 114 | return EXIT.USAGE_ERROR |
| 115 | |
| 116 | def _prompt(msg: str, default: str = "") -> str: |
| 117 | try: |
| 118 | raw = input(msg).strip() |
| 119 | return raw or default |
| 120 | except (EOFError, KeyboardInterrupt): |
| 121 | print() |
| 122 | output.hint("Non-interactive mode detected. Use 'videocaptioner config init --non-interactive'.") |
| 123 | raise |
| 124 | |
| 125 | print("VideoCaptioner Onboarding") |
| 126 | print("=" * 40) |
| 127 | print() |
| 128 | print("Press Enter to keep the shown default. API keys can be skipped and added later.") |
| 129 | print() |
| 130 | |
| 131 | try: |
| 132 | _set_nested(config_data, "transcribe.asr", _prompt("ASR engine [bijian]: ", "bijian")) |
| 133 | _set_nested(config_data, "subtitle.optimize", _yes_no("Enable AI subtitle polish? It fixes obvious ASR errors and punctuation. [Y/n]: ", True)) |
| 134 | _set_nested(config_data, "subtitle.split", _yes_no("Enable subtitle re-segmentation? [Y/n]: ", True)) |
| 135 | translator = _prompt("Translator [bing] (bing/google/llm): ", "bing") |
| 136 | _set_nested(config_data, "translate.service", translator) |
| 137 | print() |
| 138 | print("LLM config is used for AI subtitle polish, LLM translation, and --adapt-length.") |
| 139 | _set_nested(config_data, "llm.api_key", _prompt("LLM API key [skip]: ")) |
| 140 | _set_nested(config_data, "llm.api_base", _prompt(f"LLM API base [{DEFAULTS['llm']['api_base']}]: ", DEFAULTS["llm"]["api_base"])) |
| 141 | _set_nested(config_data, "llm.model", _prompt(f"LLM model [{DEFAULTS['llm']['model']}]: ", DEFAULTS["llm"]["model"])) |
| 142 | print() |
| 143 | print("Dubbing config is used by 'dub' and 'process --dub-only'.") |
| 144 | _set_nested(config_data, "dubbing.preset", _prompt("Dubbing preset [siliconflow-cn-female]: ", "siliconflow-cn-female")) |
| 145 | _set_nested(config_data, "dubbing.api_key", _prompt("TTS API key [skip]: ")) |
| 146 | _set_nested(config_data, "dubbing.voice", _prompt("Default voice [anna]: ", "anna")) |
| 147 | _set_nested(config_data, "dubbing.timing", _prompt("Timing [balanced] (balanced/strict/natural/none): ", "balanced")) |
| 148 | _set_nested(config_data, "dubbing.audio_mode", _prompt("Audio mode [replace] (replace/mix/duck): ", "replace")) |
| 149 | except (EOFError, KeyboardInterrupt): |
| 150 | return EXIT.USAGE_ERROR |
| 151 | |
| 152 | template = _render_onboarding_template(config_data) |
| 153 | return _write_onboarding_config(template, force=True) |
| 154 | |
| 155 | |
| 156 | def _yes_no(prompt: str, default: bool) -> bool: |
no test coverage detected