snips-sam
Version:
The Snips Assistant Manager
195 lines (138 loc) • 7.22 kB
Markdown
---
layout: article
title: "Buidling a Sonos system with custom Spotify playlists"
subtitle: A step-by-step guide to building a voice-powered Sonos music system.
permalink: /tutorials/sonos/
toc: Prerequisites|Preparing your device|Creating the assistant|Deploying to the Pi|Adding the skill|Further customisation|Demo
---
<div class="notification light-notification">
If you are new to Snips, we recommended you to go through the <a href="{{ site.baseurl }}/getting-started/introduction/">Getting Started Guide</a>.
</div>
# Prerequisites
For this tutorial, we assume you have the following:
- A Raspberry Pi Model 3
- A Sonos speaker
- A microphone (see for instance our recommendations in the [Microphone Array Benchmark]({{ site.baseurl }}/articles/micarrays))
- A Snips account for access to the [Snips Console](https://console.snips.ai)
- A Spotify Premium account
# Preparing your device
This tutorial is using the Snips Assistant Manager (`sam`) for setting up and deploying the assistant to your Pi. Make sure it is installed on your computer. If not, check out the <a href="{{ site.baseurl }}/getting-started/introduction/">Getting Started Guide</a>. Once installed, connect to your Pi:
```sh
$ sam connect
```
<div class="notification light-notification">
Your Pi must be on the same network as your computer. For help on setting up a Pi on a Wi-Fi network, see our <a href="{{ site.baseurl }}/getting-started/introduction/">Raspberry Pi Network Connection</a> guide.
</div>
If you haven't done so already, install the Snips toolbelt on the Pi:
```sh
$ sam init
```
This will take a little moment, which you may use to start the next step, and create an assistant in the Console.
# Creating the assistant
Head over to the Snips Console:
<a class="button is-primary" href="https://console.snips.ai" target="_blank">
<span>Open Snips Console</span>
<span class="icon">
<i class="fa fa-arrow-circle-right"></i>
</span>
</a>
Create an account if you don't have one yet, and create a new assistant with your name of choice.
<img src="{{ site.baseurl }}/images/console-create-assistant.png" srcset="{{ site.baseurl }}/images/console-create-assistant@2x.png 2x"/>
TBC
# Deploying to the Pi
Once the assistant has been created in the Console, you can load it onto your Pi using `sam`. First, create a new project locally on your computer:
```sh
$ sam create
```
This will generate a [Snipsfile]({{ site.baseurl }}/articles/snipsfile) in the current working directory.
Next, note the ID of your assistant created in the console. It can be found in the URL:
<img src="{{ site.baseurl }}/images/console-assistant-id.png" srcset="{{ site.baseurl }}/images/console-assistant-id@2x.png 2x"/>
Open the Snipsfile on your computer, find the line starting with `assistant_url`, and replace it with `assistant_id: YOUR_ASSISTANT_ID`, where `YOUR_ASSISTANT_ID` is the ID of your assistant. Your Snipsfile should look similar to this:
```yaml
assistant_id: YOUR_ASSISTANT_ID
skills:
- url: https://github.com/snipsco/snips-skill-fakeweather
package_name: snipsfakeweather
requires_tts: True
```
Don't mind the skill part, you will change this in the next step.
Deploy the assistant to your Raspberry Pi:
```sh
$ sam deploy
```
After a short time, your assistant should be deployed and ready to take your voice commands. Start by opening the intents watcher:
```sh
$ sam watch
```
Try to say a music query:
> Hey Snips, play me a song by the Beatles
In the console, you should see the `PlayMusic` intent being correctly detected:
```sh
$ sam watch
↯ Hotword detected
Query: Play me a song by the beatles
Intent: PlayMusic
artistName string beatles
```
Try a few other queries, ensuring that the intended use cases are covered, and if necessary, go back to the console to improve the assistant. Every time you update your assistant in the Console, simply run `sam deploy` to try out the changes on your device.
# Adding the skill
Once the assistant is ready, you are now set to add a skill which will be able to trigger the Sonos system upon receiving an intent from your assistant. The skill is written in Python, based on the [SoCo](http://python-soco.com/) library. It can be found here: [snips-skills-sonos](https://github.com/snipsco/snips-skill-sonos).
First, you need to obtain a Spotify token, which will give your skill access to your playlists.
<a class="button is-primary" href="https://snips-spotify-login.herokuapp.com" target="_blank">
<span>Open Spotify Connect</span>
<span class="icon">
<i class="fa fa-arrow-circle-right"></i>
</span>
</a>
<div class="notification light-notification">
Note that you will need a Spotify Premium account for this to work.
</div>
Copy the token. Now, update your Snipsfile, replacing the sample skill with the Sonos skill:
```yaml
assistant_id: YOUR_ASSISTANT_ID
skills:
- url: https://github.com/snipsco/snips-skill-sonos
package_name: snipssonos
class_name: SnipsSonos
params:
spotify_token: YOUR_SPOTIFY_TOKEN
```
replacing `YOUR_SPOTIFY_TOKEN` with the token you just obtained.
```sh
$ sam deploy
```
Make sure your Sonos system is on. Once the deployment has completed, you can again speak to your device:
> Hey Snips, play me a song by the Beatles
and it should start playing on your Sonos!
# Further customisation
Currently, the Sonos skill features the following methods:
```yaml
play_playlist(playlistName, shuffle)
play_artist(artistName)
play_next_item_in_queue()
play_previous_item_in_queue()
stop_sonos()
volume_up(level)
volume_down(level)
```
The way these methods are bound to intents is specified in the skill's [Snipsspec file](https://github.com/snipsco/snips-skill-sonos/blob/master/snipssonos/Snipsspec). This can be overwritten in your local Snipsfile, by adding an `intents` section to the skill. For instance, if you have a custom intent, say one called `SkipNTracks` with a slot named `numTracksToSkip`, you can bind it in your Snipsfile as follows:
```yaml
assistant_id: YOUR_ASSISTANT_ID
skills:
- url: https://github.com/snipsco/snips-skill-sonos
package_name: snipssonos
class_name: SnipsSonos
params:
spotify_token: YOUR_SPOTIFY_TOKEN
intents:
- intent: SkipNTracks
action: |
{% raw %}{%{% endraw %}
for _ in range(intent.numTracksToSkip):
skill.play_next_item_in_queue()
{% raw %}%}{% endraw %}
```
Here, `intent` and `skill` are reserved names that give you access to the parsed intent, respectively the current skill. You can also override existing intents from the Snipsspec file: the ones in the Snipsfile take precedence to the ones in the Snipsspec file. For a more detailed explanation on the workings of the Snipsfile, see the [Snipsfile article]({{ site.baseurl }}/articles/snipsfile).
# Demo
Here is a short demo of the skill in action, in French:
<iframe id="introIframe" src="https://player.vimeo.com/video/237742054?color=00d1b2" width="100%" height="500" frameborder="0" webkitallowfullscreen="true" mozallowfullscreen="true" allowfullscreen="true" data-vimeo-tracked="true" data-ready="true"></iframe>