diff --git a/.env.example b/.env.example index 42394da..5e40661 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,9 @@ ### Enable debug mode (optional): # ENABLE_DEBUG="1" +### Enable colored debug mode (optional): +# ENABLE_COLORED_DEBUG="1" + ### List audio devices (optional): # if enabled normal startup is disabled # LIST_DEVICES="1" diff --git a/README.md b/README.md index 857caf7..c35521e 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ usage: __main__.py [-h] [--name NAME] [--audio-input-device AUDIO_INPUT_DEVICE] | `--peripheral-volume-step` | Volume change per button press, 0.0–1.0 | %(default)s | | `--disable-peripheral-api` | Disable the peripheral WebSocket API entirely | False | | `--debug` | Print DEBUG messages to console | False | +| `--colored-debug` | Print colored DEBUG messages to console | False | | `--output-only` | Enable output only mode | False | 💡 **Note:** There is a detailed explanation on the gain, noise suppression, and wake word sensitivity flags in the [audio options](docs/audio_options.md) file. diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index b24531c..db7d816 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -9,6 +9,10 @@ if [ "$ENABLE_DEBUG" = "1" ]; then EXTRA_ARGS+=( "--debug" ) fi +if [ "$ENABLE_COLORED_DEBUG" = "1" ]; then + EXTRA_ARGS+=( "--colored-debug" ) +fi + if [ -n "${CLIENT_NAME}" ]; then EXTRA_ARGS+=( "--name" "$CLIENT_NAME" ) fi diff --git a/docs/install_application.md b/docs/install_application.md index 9cce2c6..1e374a1 100644 --- a/docs/install_application.md +++ b/docs/install_application.md @@ -260,6 +260,9 @@ The following variables can be configured in the `.env` or in the service file: | `LVA_PULSE_SERVER` | `/run/user/${LVA_USER_ID}/pulse/native` | Path to the PulseAudio/PipeWire socket (In some cases a `:unix`infront of the path is needed) | | `LVA_XDG_RUNTIME_DIR` | `/run/user/${LVA_USER_ID}` | XDG runtime directory | | `LVA_PULSE_COOKIE` | `/app/configuration/tmp_pulse_cookie` | Cookie file for PulseAudio if you use encryption. By default disabled. We use a tmp file to avoid errors if the file is not found | +| `ENABLE_DEBUG` | (optional) | Set to "1" to enable debug mode | +| `ENABLE_COLORED_DEBUG` | (optional) | Set to "1" to enable colored debug mode | +| `LIST_DEVICES` | (optional) | Set to "1" to list audio devices instead of starting | | `PREFERENCES_FILE` | (optional) | Path to a custom preferences JSON file | | `NETWORK_INTERFACE` | Autodetected | network card for server | | `HOST` | Autodetected | API server IP-Address, can be 0.0.0.0 for all interfaces, but only one network card works for MAC-ADDRESS and ESP protocol | diff --git a/linux_voice_assistant/__main__.py b/linux_voice_assistant/__main__.py index fd9b818..39ce8ca 100644 --- a/linux_voice_assistant/__main__.py +++ b/linux_voice_assistant/__main__.py @@ -234,6 +234,11 @@ async def main() -> None: action="store_true", help="Add this to enable debug logging", ) + parser.add_argument( + "--colored-debug", + action="store_true", + help="Add this to enable colored debug logging", + ) parser.add_argument( "--output-only", action="store_true", @@ -241,6 +246,15 @@ async def main() -> None: ) args = parser.parse_args() + if args.colored_debug: + args.debug = True + _setup_logging(args) + elif args.debug: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + + _LOGGER.debug(args) if args.list_input_devices: print("Audio Input devices:") print("=" * 13) @@ -259,9 +273,6 @@ async def main() -> None: print(speaker["name"] + ":", speaker["description"]) return - logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO) - _LOGGER.debug(args) - # Resolve network interface for mac-address detection if not args.network_interface: print("No network interface specified, try to detect default interface") @@ -575,6 +586,38 @@ async def main() -> None: _LOGGER.debug("Server stopped") +# ----------------------------------------------------------------------------- +def _setup_logging(args: argparse.Namespace) -> None: + COLORS = { + logging.DEBUG: "\033[36m", + logging.INFO: "\033[32m", + logging.WARNING: "\033[33m", + logging.ERROR: "\033[31m", + logging.CRITICAL: "\033[35m", + } + RESET = "\033[0m" + + original_format = logging.Formatter.format + + def colored_format(self, record: logging.LogRecord) -> str: + color = COLORS.get(record.levelno, RESET) + return f"{color}{original_format(self, record)}{RESET}" + + logging.Formatter.format = colored_format # type: ignore + + handler = logging.StreamHandler() + handler.setFormatter( + logging.Formatter( + fmt="%(asctime)s %(levelname)s %(name)s: %(message)s", + datefmt="%H:%M:%S", + ) + ) + logging.basicConfig( + level=logging.DEBUG if args.debug else logging.INFO, + handlers=[handler], + ) + + # ----------------------------------------------------------------------------- diff --git a/linux_voice_assistant/satellite.py b/linux_voice_assistant/satellite.py index b57c3a5..ffffe5e 100644 --- a/linux_voice_assistant/satellite.py +++ b/linux_voice_assistant/satellite.py @@ -507,7 +507,7 @@ class VoiceSatelliteProtocol(APIServer): # ------------------------------------------------------------------ def handle_voice_event(self, event_type: VoiceAssistantEventType, data: Dict[str, str]) -> None: - _LOGGER.debug("Voice event: type=%s, data=%s", event_type.name, data) + _LOGGER.info("Voice event: type=%s, data=%s", event_type.name, data) if event_type == VoiceAssistantEventType.VOICE_ASSISTANT_RUN_START: self._tts_url = data.get("url")