{"id":15048858,"url":"https://github.com/mryndzionek/kws_cli","last_synced_at":"2026-02-27T19:07:13.169Z","repository":{"id":250647798,"uuid":"834968448","full_name":"mryndzionek/kws_cli","owner":"mryndzionek","description":"Small footprint, standalone, zero dependency, offline keyword spotting (KWS) CLI tool.","archived":false,"fork":false,"pushed_at":"2024-08-04T11:46:18.000Z","size":991,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-12T17:53:14.436Z","etag":null,"topics":["c-language","cli","edgeml","hotword-detection","hotword-detector","keyword-spotting","kws","lightweight","machine-learning","machinelearning","onnx","pytorch","speech-commands","speech-recognition","tinyml","voice-commands","wake-word","wake-word-detection","word-spotting"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mryndzionek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-28T21:14:43.000Z","updated_at":"2024-11-19T03:23:04.000Z","dependencies_parsed_at":"2024-08-04T12:55:02.192Z","dependency_job_id":null,"html_url":"https://github.com/mryndzionek/kws_cli","commit_stats":null,"previous_names":["mryndzionek/kws_cli"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mryndzionek/kws_cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mryndzionek%2Fkws_cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mryndzionek%2Fkws_cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mryndzionek%2Fkws_cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mryndzionek%2Fkws_cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mryndzionek","download_url":"https://codeload.github.com/mryndzionek/kws_cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mryndzionek%2Fkws_cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29909293,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T17:28:36.873Z","status":"ssl_error","status_checked_at":"2026-02-27T17:28:20.970Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-language","cli","edgeml","hotword-detection","hotword-detector","keyword-spotting","kws","lightweight","machine-learning","machinelearning","onnx","pytorch","speech-commands","speech-recognition","tinyml","voice-commands","wake-word","wake-word-detection","word-spotting"],"created_at":"2024-09-24T21:16:54.000Z","updated_at":"2026-02-27T19:07:13.152Z","avatar_url":"https://github.com/mryndzionek.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kws_cli\n\n[![build](https://github.com/mryndzionek/kws_cli/actions/workflows/build.yml/badge.svg)](https://github.com/mryndzionek/kws_cli/actions/workflows/build.yml)\n\n## About\n\nSpeech recognition in ~300kB of code.\n\nSmall footprint, standalone, zero dependency, offline\nkeyword spotting (KWS) CLI tool. Might be useful in\nsome automation task. Accepts audio on stdin a and recognizes\nfollowing words: `up`, `down`, `left`, `right`, `stop`.\n\nHere is an example invocation:\n\n```\nrec -q -t raw -c1 -e signed -b 16 -r16k - | ./kws_cli\n```\n\nMake sure you have decent microphone and the system audio\nis on a decent level.\n\nIndividual WAV files can piped (e.g. for testing) using:\n\n```\nsox -S ../untitled.wav -t raw -c1 -e signed -b 16 -r16k - | ./kws_cli\n```\n## Demo\n\nIn the demo subdirectory there is a Python script showing how to\nuse `kws_cli` for simple automation.\n\nhttps://github.com/user-attachments/assets/2a9eaa90-a0b9-4423-91c8-fd4df6bbc459\n\n## More details\n\nSpeech recognition is based on [this](https://github.com/microsoft/EdgeML/blob/master/docs/publications/Sha-RNN.pdf)\nmodel and examples from the same repository.\nThis simple model with three layers: 2x LSTM + 1x fully connected.\nThe model is trained in PyTorch and exported to ONNX.\nThen [onnx2c](https://github.com/kraiskil/onnx2c)\nis used to convert the model to a bunch of C code.\nThe LSTM layers had become mainstream in recent years and are well\nsupported in different frameworks. ~~The model is small, so it might\nbe possible to run it on Cortex-M4/M7, or ESP32 (future work).~~\nSee below.\n\n## Building\n\nThe usual CMake routine:\n\n```\nmkdir build\ncd build\ncmake -DCMAKE_BUILD_TYPE=Release\nmake\n```\n\n## Running in embedded systems context (TinyML/EdgeML)\n\nThis model was run on RP2040 and ESP32-S3.\n\nThe model runs on a 1s window of sound samples, so feature extraction\nand inference must take less than that in order to run continuously.\nPreferably there should also be an overlap between successive windows.\nOn RP2040 the inference alone takes ~2.4s with 240MHz clock, so\nit's not possible to run real-time. The feature extraction also\ntakes significant time. A smaller (\"narrower\") model was also\ntested and still the inference took ~1.2s. This is still impressive\ntaking into account that RP2040 is a Cortex-M0+ without FPU.\n\nOn ESP32-S3 running at 240MHz inference with feature extraction\ntakes ~0.5s, so running real-time is possible (e.g. every 750ms\nwith 250ms overlap gives good results).\nA demo can be found [here](https://github.com/mryndzionek/esp32s3_eye_kws_demo).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmryndzionek%2Fkws_cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmryndzionek%2Fkws_cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmryndzionek%2Fkws_cli/lists"}