# Moonshine Voice Control on Raspberry Pi

## Overview

https://www.youtube.com/watch?v=Ima379siKVw

[Moonshine](https://moonshine.ai) Voice is an open source project for real-time voice transcription. It's primarily suited for streaming and live audio capture for voice based interfaces. This project will demonstrate how to use Moonshine to set up basic voice control for NeoPixels on a Raspberry Pi.

All testing was performed on a Raspberry Pi 5 with 8gb of RAM.

## Parts
Featured
### Raspberry Pi 5 - 8 GB RAM

[Raspberry Pi 5 - 8 GB RAM](https://www.adafruit.com/product/5813)
The Raspberry Pi 5&nbsp;is the newest Raspberry Pi computer, and the Pi Foundation knows you can always make a good thing&nbsp;_better_! And what could make the Pi 5 better than the 4? How about a&nbsp;_faster_&nbsp;processor, USB 3.0 ports, and an updated Gigabit Ethernet chip...

In Stock
[Buy Now](https://www.adafruit.com/product/5813)
[Related Guides to the Product](https://learn.adafruit.com/products/5813/guides)
![Angled shot of green Raspberry Pi microcontroller.](https://cdn-shop.adafruit.com/640x480/5813-01.jpg)

Featured
### Official Raspberry Pi 27W PD Power Supply 5.1V 5A with USB C

[Official Raspberry Pi 27W PD Power Supply 5.1V 5A with USB C](https://www.adafruit.com/product/5814)
The official Raspberry Pi PD USB-C power supply is here! Superfast with just the right amount of cable length to get your Pi 5 projects up and running! With true Power Delivery support, this supply can easily supply 5 A of current!

Comes in gothy Adafruit Black! Great for use with Pi 4...

In Stock
[Buy Now](https://www.adafruit.com/product/5814)
[Related Guides to the Product](https://learn.adafruit.com/products/5814/guides)
![Angled shot of black, square-shaped power supply block with a coiled black cable.](https://cdn-shop.adafruit.com/640x480/5814-02.jpg)

Featured
### Adafruit NeoPixel LED Strip with 3-pin JST PH 2mm Connector

[Adafruit NeoPixel LED Strip with 3-pin JST PH 2mm Connector](https://www.adafruit.com/product/3919)
Plug in and glow, this **Adafruit NeoPixel LED Strip with JST PH Connector** has **30 total LEDs** in a **"60 LED per meter" spacing** , and is 0.5 meters long, in classy Adafruit Black. Its not too long, but has lots of glowing action.<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/3919)
[Related Guides to the Product](https://learn.adafruit.com/products/3919/guides)
![Adafruit NeoPixel LED Strip with 3-pin JST PH Connector lit up rainbow](https://cdn-shop.adafruit.com/640x480/3919-01.jpg)

### USB Microphone

Any standard USB Microphone that works on the Raspberry Pi should work with Moonshine. This mini microphone in the shop is one option:

Featured
### Mini USB Microphone

[Mini USB Microphone](https://www.adafruit.com/product/3367)
Hey, listen up! It's the world's smallest USB microphone! OK maybe it's not in the Guinness Record Book, but it is _pretty darn small_! This plug-and-play **Mini USB Microphone** needs no driver, and its USB interface means you can use it with any computer,...

In Stock
[Buy Now](https://www.adafruit.com/product/3367)
[Related Guides to the Product](https://learn.adafruit.com/products/3367/guides)
![Mini USB Microphone dongle](https://cdn-shop.adafruit.com/640x480/3367-00.jpg)

### Optional

The Pi Cobbler and breadboard are optional, they make it more convenient to connect the NeoPixels to the correct pins on the Raspberry Pi:

Featured
### Assembled Pi Cobbler Plus - Breakout Cable

[Assembled Pi Cobbler Plus - Breakout Cable](https://www.adafruit.com/product/2029)
The Raspberry Pi B+ / Pi 2 / Pi 3 / Pi 4 / Pi 5 has landed on the Maker World like a 40-GPIO pinned, quad-USB ported, credit card sized bomb of DIY joy. And while you can use most of our great Model B accessories by hooking up our [downgrade...](https://www.adafruit.com/product/1986)

In Stock
[Buy Now](https://www.adafruit.com/product/2029)
[Related Guides to the Product](https://learn.adafruit.com/products/2029/guides)
![Angled shot of blue, rectangular, GPIO breakout board.](https://cdn-shop.adafruit.com/640x480/2029-04.jpg)

Featured
### GPIO Ribbon Cable for Raspberry Pi Model A+/B+/Pi 2/Pi 3/Pi 4/5

[GPIO Ribbon Cable for Raspberry Pi Model A+/B+/Pi 2/Pi 3/Pi 4/5](https://www.adafruit.com/product/1988)
That new Raspberry Pi® Model B+ computer you just got has a row of 2x20 pin headers soldered on - those are the GPIO (general purpose input/output) pins, and for those of us who like to hack electronics, they are where the real fun is. By programming the Pi, you can twiddle those pins high...

Out of Stock
[Buy Now](https://www.adafruit.com/product/1988)
[Related Guides to the Product](https://learn.adafruit.com/products/1988/guides)
![Angled shot of a GPIO Ribbon Cable for Raspberry Pi Model.](https://cdn-shop.adafruit.com/640x480/1988-00.jpg)

Featured
### Half-Size Breadboard with Mounting Holes

[Half-Size Breadboard with Mounting Holes](https://www.adafruit.com/product/4539)
This cute 3.2″ × 2.1″ (82 × 53mm) solderless half-size breadboard has four bus lines&nbsp;and 30 rows of pins, our favorite size of solderless breadboard for projects. You get a whoppin' **400 tie points**! [Plug in...](http://adafruit.com/feather)

Out of Stock
[Buy Now](https://www.adafruit.com/product/4539)
[Related Guides to the Product](https://learn.adafruit.com/products/4539/guides)
![Angled shot of Half-Size Breadboard with Mounting Holes.](https://cdn-shop.adafruit.com/640x480/4539-03.jpg)

# Moonshine Voice Control on Raspberry Pi

## Wiring

Plug in a standard USB microphone into one of the available Raspberry Pi USB ports.

Connect a strip of NeoPixels to the Raspberry Pi using one of the following methods.

## Pi Cobbler Wiring

A&nbsp;[Pi Cobbler](https://www.adafruit.com/product/2029) makes the wiring easy with clearly labeled pins. A 2x20 ribbon cable connects the Pi GPIO pins to the Cobbler breakout.

To connect a NeoPixel LED strand, make the following wiring connections while the Pi is powered off and unplugged from its power adapter:

- Pi **5V** to NeoPixel **5V** power (red wire)
- Pi **GND** to NeoPixel **GND** (black wire)
- Pi **26** to NeoPixel **DIN** (green wire)

![Fritzing wiring diagram showing NeoPixel strip connected to 5V, GND, and GPIO 26](https://cdn-learn.adafruit.com/assets/assets/000/142/513/medium640/raspberry_pi_cobbler_wiring.png?1771615882)

![A Raspberry Pi 5 with a USB microphone connected, and a ribbon cable connecting to a Pi Cobbler breakout on a breadboard with a NeoPixel strip connected and lit up pink.](https://cdn-learn.adafruit.com/assets/assets/000/142/529/medium640/raspberry_pi_moonshine_rpi_guide_image.png?1771862696)

## Direct Wiring

You can also wire the NeoPixels directly to the Raspberry Pi

To connect a NeoPixel LED strand, make the following wiring connections while the Pi is powered off and unplugged from its power adapter:

- Pi **5V** to NeoPixel **5V** power (red wire)
- Pi **GND** to NeoPixel **GND** (black wire)
- Pi **26** to NeoPixel **DIN** (green wire)

![Fritzing wiring diagram showing a NeoPixel strip connected directly to a Raspberry Pi's 5V, GND, and GPIO 26 pins.](https://cdn-learn.adafruit.com/assets/assets/000/142/514/medium640/raspberry_pi_direct_wiring.png?1771616106)

# Moonshine Voice Control on Raspberry Pi

## Software Setup

## OS Image & Blinka

Use the&nbsp;[Raspberry Pi Imager](https://www.raspberrypi.com/software/) to load a fresh image of Raspberry Pi OS (64-bit) onto a micro SD card. Once the SD card is ready, insert it into the Pi 5 and boot up.

Run these commands to update all of the pre-loaded software.

```terminal
sudo apt update
sudo apt upgrade
```

Next install [Adafruit Blinka](https://circuitpython.org/blinka) on the Raspberry Pi by following the&nbsp;[instructions in the Blinka Learn Guide](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi).

## Moonshine

Be sure that you activate the same Python virtual environment that Blinka was installed in when you install Moonshine. The code for this project needs to utilize both Blinka and Moonshine together, so both must be installed in the same environment.

If it's not already active, then activate the environment with a command like this one adapted for the path and name of your virtual environment if they are different.

```terminal
source env/bin/activate
```

Install `moonshine-voice` using pip with this command.

```terminal
pip install moonshine-voice
```

The first time that you use the `moonshine-voice` library, it will download the required model files. To download them now, and ensure that the install is working properly, use this command to launch the basic transcription example.

```terminal
python -m moonshine_voice.mic_transcriber --language en
```

It will take a moment to initialize and then begin listening to the microphone and transcribing the words that it hears.

Press **Ctrl+C** when you want to exit the transcription example.

# Moonshine Voice Control on Raspberry Pi

## Code

The Moonshine project contains [many great examples](https://github.com/moonshine-ai/moonshine/tree/main/examples). These examples make a great starting point to be adapted into other projects like the one in this guide.

Download or copy the code below to your Raspberry Pi. This example uses the NeoPixel LED strip.

After downloading the code launch it with Python inside of the same virtual environment set up previously.

```terminal
python voice_control_lights.py
```

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Raspberry_Pi/Raspberry_Pi5_Moonshine_VoiceControl_NeoPixels/voice_control_lights.py

# Moonshine Voice Control on Raspberry Pi

## Code Explanation

## NeoPixel Initialization

The first thing the code does after imports is initialize the strand of 30 NeoPixels connected to GPIO pin **D26**. They are set to `0.1` brightness to go easy on the retinas but feel free to adjust if you have something to diffuse or obstruct direct vision of the LEDs.

## Command Line Arguments

The script supports a number of command line arguments to control its behavior.

- `--model-arch`: Controls which version of the Moonshine model is used. Smaller model versions can transcribe faster but are less likely to be accurate.
  - `5` - Medium streaming (default)
  - `4` - Small streaming
  - `2` - Tiny streaming

- `--embedding-model`: The name of the embedding model to use for intent recognition. The default is `embeddinggemma-300m` which uses Google's [EmbeddingGemma model](https://huggingface.co/google/embeddinggemma-300m).
- `--threshold`: The similarity threshold for matching the trigger phrases as a decimal. The default is `0.6`. This refers to the confidence level output of the intent recognition model, higher value means more confidence that the intent of the input text matches the specified value.&nbsp;

## Transcriber & Intent Recognition Models Setup

A `TranscriptPrinter` class is defined that extends Moonshine's `TranscriptEventListener`. The functions implemented within it simply print to the terminal as the transcription is happening. The most recently printed line is updated over time as the model works. This is not strictly necessary for voice control, but it is helpful for troubleshooting to be able to see what the model thinks it is hearing.

The models used for transcription and embedding are determined based on the CLI arguments documented above. The embedding model is used to initialize an instance of&nbsp;`IntentRecognizer`. The transcription model is used to create a `MicTranscriber`. The `MicTranscriber` has listeners added for both the `transcript_printer` and the `intent_recognizer` causing it to print as it works, and scan for the specified intent trigger phrases.

## Voice Command Callbacks

Setting up voice commands is a two part process:

1. Define a callback function that will get called and take the appropriate action when the voice command is heard.
2. Call `intent_recognizer.register_intent()` passing in the command string and the callback function.&nbsp;

Here is the relevant code for the disco party command. Inside the callback function it prints a message and sets the global variable `run_disco_animation` to `True`. This variable gets checked in the main loop to control whether the disco animation will run on the NeoPixels.

```python
# Disco Party animation setup
disco_party = ColorCycle(pixels, speed=0.35, colors=[_[1] for _ in colors[:8]])
run_disco_animation = False

# ...

def on_disco_party(trigger: str, utterance: str, similarity: float):
    """
    Intent trigger listener callback function for Disco Party command.
    Enables the disco party animation boolean.
    """
    print("###########################")
    print(f"# {trigger} - {utterance} - {similarity}")
    print("# Disco Party!")
    print("###########################")
    global run_disco_animation
    run_disco_animation = True


# Register intents with their trigger phrases and handlers
intents = {
    "disco party": on_disco_party,
}

# ... 

for intent, handler in intents.items():
    intent_recognizer.register_intent(intent, handler)
```

In the code for this project, the commands are first gathered into a dictionary variable `intents`. Then a `for` loop is used to iterate over them registering each with the `intent_recognizer`.

The disco party command is the only one that is hard-coded directly.

### Dynamic Light Color Callbacks

All of the light color callbacks are created dynamically in order to reduce copy/pasted boilerplate code.

The color words and RGB values are first defined in a list of tuples.

```python
colors = [
    ("red", (255, 0, 0)),
    ("blue", (0, 0, 255)),
    ("green", (0, 255, 0)),
    ("yellow", (255, 255, 0)),
    ("orange", (255, 95, 0)),
    ("pink", (255, 0, 255)),
    ("purple", (90, 0, 255)),
    ("turquoise", (0, 255, 255)),
    ("off", (0, 0, 0)),
    ("black", (0, 0, 0)),
]
```

The word `"off"` is registered as the color black `(0, 0, 0)` meaning it will turn the LEDs off.

The&nbsp;[higher order function](https://en.wikipedia.org/wiki/Higher-order_function) `build_lights_color_callback_function()` is defined to build the callback functions for each of the colors. In Python, functions can be treated as normal variables. This function defines a new function into a variable and then returns it. It takes a tuple argument containing color word and RGB value from list of `colors` and creates an appropriate callback function for the color specified.

```python
def build_lights_color_callback_function(input_data):
    """
    Given a tuple with color name, and RGB values like:
    ("red", (255, 0, 0))
    Create and return an intent trigger callback function
    that turns the NeoPixels the specified color.
    """

    def lights_color_callback(trigger: str, utterance: str, similarity: float):
        print("###########################")
        print(f"# {trigger} - {utterance} - {similarity}")
        print(f"# Turning lights {input_data[0]}")
        print("###########################")
        global run_disco_animation
        run_disco_animation = False
        pixels.fill(input_data[1])
        pixels.show()

    return lights_color_callback
```

A `for` loop is used to create entries in the `intents` dictionary for each of the colors. For each color, two entries are created: "lights [color\_word]" and "[color\_word] lights". During testing I found that some colors work better when they're said before "lights" and others work better the other way around. Defining commands for both allows for flexibility when speaking and increases the chances that intent recognizer will find a match on any phrases that have a similar meaning.

```python
for color in colors:
    intents[f"lights {color[0]}"] = build_lights_color_callback_function(color)
    intents[f"{color[0]} lights"] = build_lights_color_callback_function(color)
```

The same `for` loop mentioned in the disco party command section also registers all of the light color commands since they're all in the same&nbsp;`intents` dictionary.

```python
for intent, handler in intents.items():
    intent_recognizer.register_intent(intent, handler)
```


## Guide Products

### Raspberry Pi 5 - 8 GB RAM

[Raspberry Pi 5 - 8 GB RAM](https://www.adafruit.com/product/5813)
The Raspberry Pi 5&nbsp;is the newest Raspberry Pi computer, and the Pi Foundation knows you can always make a good thing&nbsp;_better_! And what could make the Pi 5 better than the 4? How about a&nbsp;_faster_&nbsp;processor, USB 3.0 ports, and an updated Gigabit Ethernet chip...

In Stock
[Buy Now](https://www.adafruit.com/product/5813)
[Related Guides to the Product](https://learn.adafruit.com/products/5813/guides)
### Official Raspberry Pi 27W PD Power Supply 5.1V 5A with USB C

[Official Raspberry Pi 27W PD Power Supply 5.1V 5A with USB C](https://www.adafruit.com/product/5814)
The official Raspberry Pi PD USB-C power supply is here! Superfast with just the right amount of cable length to get your Pi 5 projects up and running! With true Power Delivery support, this supply can easily supply 5 A of current!

Comes in gothy Adafruit Black! Great for use with Pi 4...

In Stock
[Buy Now](https://www.adafruit.com/product/5814)
[Related Guides to the Product](https://learn.adafruit.com/products/5814/guides)
### Adafruit NeoPixel LED Strip with 3-pin JST PH 2mm Connector

[Adafruit NeoPixel LED Strip with 3-pin JST PH 2mm Connector](https://www.adafruit.com/product/3919)
Plug in and glow, this **Adafruit NeoPixel LED Strip with JST PH Connector** has **30 total LEDs** in a **"60 LED per meter" spacing** , and is 0.5 meters long, in classy Adafruit Black. Its not too long, but has lots of glowing action.<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/3919)
[Related Guides to the Product](https://learn.adafruit.com/products/3919/guides)
### Mini USB Microphone

[Mini USB Microphone](https://www.adafruit.com/product/3367)
Hey, listen up! It's the world's smallest USB microphone! OK maybe it's not in the Guinness Record Book, but it is _pretty darn small_! This plug-and-play **Mini USB Microphone** needs no driver, and its USB interface means you can use it with any computer,...

In Stock
[Buy Now](https://www.adafruit.com/product/3367)
[Related Guides to the Product](https://learn.adafruit.com/products/3367/guides)
### Assembled Pi Cobbler Plus - Breakout Cable

[Assembled Pi Cobbler Plus - Breakout Cable](https://www.adafruit.com/product/2029)
The Raspberry Pi B+ / Pi 2 / Pi 3 / Pi 4 / Pi 5 has landed on the Maker World like a 40-GPIO pinned, quad-USB ported, credit card sized bomb of DIY joy. And while you can use most of our great Model B accessories by hooking up our [downgrade...](https://www.adafruit.com/product/1986)

In Stock
[Buy Now](https://www.adafruit.com/product/2029)
[Related Guides to the Product](https://learn.adafruit.com/products/2029/guides)
### GPIO Ribbon Cable for Raspberry Pi Model A+/B+/Pi 2/Pi 3/Pi 4/5

[GPIO Ribbon Cable for Raspberry Pi Model A+/B+/Pi 2/Pi 3/Pi 4/5](https://www.adafruit.com/product/1988)
That new Raspberry Pi® Model B+ computer you just got has a row of 2x20 pin headers soldered on - those are the GPIO (general purpose input/output) pins, and for those of us who like to hack electronics, they are where the real fun is. By programming the Pi, you can twiddle those pins high...

Out of Stock
[Buy Now](https://www.adafruit.com/product/1988)
[Related Guides to the Product](https://learn.adafruit.com/products/1988/guides)
### Half-Size Breadboard with Mounting Holes

[Half-Size Breadboard with Mounting Holes](https://www.adafruit.com/product/4539)
This cute 3.2″ × 2.1″ (82 × 53mm) solderless half-size breadboard has four bus lines&nbsp;and 30 rows of pins, our favorite size of solderless breadboard for projects. You get a whoppin' **400 tie points**! [Plug in...](http://adafruit.com/feather)

Out of Stock
[Buy Now](https://www.adafruit.com/product/4539)
[Related Guides to the Product](https://learn.adafruit.com/products/4539/guides)

## Related Guides

- [CYBERDECK Bonnet and HAT for Raspberry Pi 400](https://learn.adafruit.com/cyberdeck-bonnet-and-hat.md)
- [LED Matrix Wall Arcade for Pico-8](https://learn.adafruit.com/led-matrix-wall-arcade.md)
- [Yoga Pose Chime](https://learn.adafruit.com/yoga-pose-chime.md)
- [Milk Jug Glow Skull](https://learn.adafruit.com/milk-jug-glow-skull.md)
- [Magic Storybook with ChatGPT](https://learn.adafruit.com/magic-storybook-with-chatgpt.md)
- [Ultimate Youtube Live Camera](https://learn.adafruit.com/ultimate-youtube-live-camera.md)
- [PyPortal NeoPixel Color Picker](https://learn.adafruit.com/pyportal-neopixel-color-picker.md)
- [HalloWing M4 Tombstone](https://learn.adafruit.com/hallowing-tombstone.md)
- [Control an LED With Your Voice using Watson and Raspberry Pi](https://learn.adafruit.com/tjbot-control-an-led-with-your-voice-watson-on-raspberry-pi.md)
- [HalloWing Lightsabers](https://learn.adafruit.com/hallowing-lightsaber.md)
- [Set up Home Assistant with a Raspberry Pi](https://learn.adafruit.com/set-up-home-assistant-with-a-raspberry-pi.md)
- [Holiday Tree with Feather RP2040 Scorpio](https://learn.adafruit.com/holiday-tree-with-scorpio.md)
- [Local LLMs on Raspberry Pi](https://learn.adafruit.com/local-llms-on-raspberry-pi.md)
- [Robotic AI Bear using ChatGPT](https://learn.adafruit.com/robotic-ai-bear-using-chatgpt.md)
- [Articulated Pi Display V2 Mount](https://learn.adafruit.com/pi-wall-mount.md)
