Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Fruit_Jam/Fruit_Jam_Spell_Jam/aws_polly.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def text_to_speech_polly_http(
text,
access_key,
secret_key,
output_file="/saves/awspollyoutput.mp3",
output_file="/saves/tts_output.mp3",
voice_id="Joanna",
region="us-east-1",
output_format="mp3",
Expand Down
62 changes: 17 additions & 45 deletions Fruit_Jam/Fruit_Jam_Spell_Jam/code.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
# SPDX-License-Identifier: MIT
import os

import sys
import time

import supervisor

from adafruit_fruitjam import FruitJam
from adafruit_fruitjam.peripherals import request_display_config
import adafruit_connection_manager
import adafruit_requests
from displayio import OnDiskBitmap, TileGrid, Group
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text.bitmap_label import Label

from aws_polly import text_to_speech_polly_http

from launcher_config import LauncherConfig

# comment out one of these imports depending on which TTS engine you want to use
from tts_aws import WordFetcherTTS
# from tts_local import WordFetcherTTS

# read the user settings
launcher_config = LauncherConfig()

# constants
Expand Down Expand Up @@ -60,55 +61,26 @@

fj.neopixels.brightness = 0.1

# AWS auth requires us to have accurate date/time
now = fj.sync_time()

# setup adafruit_requests session
# pylint: disable=protected-access
pool = adafruit_connection_manager.get_radio_socketpool(fj.network._wifi.esp)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(fj.network._wifi.esp)
requests = adafruit_requests.Session(pool, ssl_context)

# read AWS keys from settings.toml
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY")
AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY")


def fetch_word(word, voice="Joanna"):
"""
Fetch an MP3 saying a word from AWS Polly
:param word: The word to speak
:param voice: The AWS Polly voide ID to use
:return: Boolean, whether the request was successful.
"""

if AWS_ACCESS_KEY is None or AWS_SECRET_KEY is None:
return False

fj.neopixels.fill(0xFFFF00)
success = text_to_speech_polly_http(
requests,
text=word,
access_key=AWS_ACCESS_KEY,
secret_key=AWS_SECRET_KEY,
voice_id=voice,
)
fj.neopixels.fill(0x00FF00)
return success

word_fetcher = WordFetcherTTS(fj, launcher_config)

def say_and_spell_lastword():
"""
Say the last word, then spell it out one letter at a time, finally say it once more.
"""
if sayword:
fj.play_mp3_file("/saves/awspollyoutput.mp3")
if word_fetcher.output_path[-4:] == ".mp3":
fj.play_mp3_file(word_fetcher.output_path)
elif word_fetcher.output_path[-4:] == ".wav":
fj.play_file(word_fetcher.output_path)
time.sleep(0.2)
for letter in lastword:
fj.play_mp3_file(f"spell_jam_assets/letter_mp3s/{letter.upper()}.mp3")
time.sleep(0.2)
if sayword:
fj.play_mp3_file("/saves/awspollyoutput.mp3")
if word_fetcher.output_path[-4:] == ".mp3":
fj.play_mp3_file(word_fetcher.output_path)
elif word_fetcher.output_path[-4:] == ".wav":
fj.play_file(word_fetcher.output_path)
fj.neopixels.fill(0x000000)


Expand All @@ -133,7 +105,7 @@ def say_and_spell_lastword():
elif c == "\n":
if curword:
lastword = curword
sayword = fetch_word(lastword)
sayword = word_fetcher.fetch_word(lastword)
say_and_spell_lastword()
curword = ""
else:
Expand Down
48 changes: 48 additions & 0 deletions Fruit_Jam/Fruit_Jam_Spell_Jam/tts_aws.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
# SPDX-License-Identifier: MIT

# tts_aws.py
import os
import adafruit_connection_manager
import adafruit_requests
from aws_polly import text_to_speech_polly_http

class WordFetcherTTS():
def __init__(self, fj=None, launcher_config=None, output_path="/saves/tts_output.mp3"):

self.output_path = output_path
self.fj = fj
self.launcher_config = launcher_config

# AWS auth requires us to have accurate date/time
fj.sync_time()

# setup adafruit_requests session
pool = adafruit_connection_manager.get_radio_socketpool(fj.network._wifi.esp)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(fj.network._wifi.esp)
self.requests = adafruit_requests.Session(pool, ssl_context)
self.AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY")
self.AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY")

def fetch_word(self, word: str, voice: str = "Joanna") -> bool:
if not self.AWS_ACCESS_KEY or not self.AWS_SECRET_KEY:
print("Missing AWS credentials.")
return False

if self.fj:
self.fj.neopixels.fill(0xFFFF00)

success = text_to_speech_polly_http(
self.requests,
text=word,
access_key=self.AWS_ACCESS_KEY,
secret_key=self.AWS_SECRET_KEY,
output_file=self.output_path,
voice_id=voice,
region="us-east-1",
output_format="mp3",
)

if self.fj:
self.fj.neopixels.fill(0x00FF00)
return success