Merge pull request #3105 from FoamyGuy/add_pi_kittentts

Add pi kittentts demo project
This commit is contained in:
foamyguy 2025-08-12 11:08:29 -05:00 committed by GitHub
commit 1daa2d72aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 196 additions and 0 deletions

View file

@ -0,0 +1,126 @@
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import json
import time
import glob
import os
import tomllib
from datetime import datetime
import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Debouncer
from kittentts import KittenTTS
import soundfile as sf
print("initializing...")
with open("weather_narrator.toml", "rb") as f:
config = tomllib.load(f)
voice = config.get("voice", None)
sound_device = config.get("sound_device", None)
day_of_month_words = [
"1st",
"2nd",
"3rd",
"4th",
"5th",
"6th",
"7th",
"8th",
"9th",
"10th",
"11th",
"12th",
"13th",
"14th",
"15th",
"16th",
"17th",
"18th",
"19th",
"20th",
"21st",
"22nd",
"23rd",
"24th",
"25th",
"26th",
"27th",
"28th",
"29th",
"30th",
"31st",
]
button = DigitalInOut(board.D17)
button.direction = Direction.INPUT
button.pull = Pull.UP
debounced_btn = Debouncer(button)
with open("forecast.json", "r") as f:
forecast = json.load(f)
m = KittenTTS("KittenML/kitten-tts-nano-0.1")
def generate_date_time_audio(date_obj):
replacements = {
"00": "oh clock",
"01": "oh 1",
"02": "oh 2",
"03": "oh 3",
"04": "oh 4",
"05": "oh 5",
"06": "oh 6",
"07": "oh 7",
"08": "oh 8",
"09": "oh 9",
}
now_date_obj = datetime.now()
try:
os.remove("date.wav")
except FileNotFoundError:
pass
month = date_obj.strftime("%B")
day_word = day_of_month_words[date_obj.day - 1]
date_script = f"{month} {day_word}, {date_obj.year}."
time_script = now_date_obj.strftime("%-I %M %p")
for key, val in replacements.items():
time_script = time_script.replace(key, val)
date_script += f" The time is: {time_script}."
audio = m.generate(date_script, voice=voice)
sf.write("date.wav", audio, 24000)
print("Press button to hear time and weather...")
while True:
debounced_btn.update()
if debounced_btn.fell:
print("just pressed")
dt_format = "%Y-%m-%dT%H:%M:%S%z"
forecast_date_obj = datetime.strptime(
forecast["properties"]["periods"][0]["startTime"], dt_format
)
generate_date_time_audio(forecast_date_obj)
files_to_read = glob.glob("sound_files/*.wav")
sorted_files_asc = sorted(files_to_read, key=os.path.getmtime)
sorted_files_asc.insert(0, "date.wav")
for file in sorted_files_asc:
if sound_device is None:
os.system(f"aplay {file}")
else:
os.system(f"aplay -D {sound_device} {file}")
time.sleep(0.01)

View file

@ -0,0 +1,54 @@
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import json
import os
import tomllib
import shutil
import requests
from kittentts import KittenTTS
import soundfile as sf
with open("weather_narrator.toml", "rb") as f:
config = tomllib.load(f)
m = KittenTTS("KittenML/kitten-tts-nano-0.1")
replacements = {"mph": "miles per hour"}
# latlng_lookup_url = "https://api.weather.gov/points/{lat},{lon}"
voice = config.get("voice", None)
location_points = config.get("location_points", "36,33")
weather_data = requests.get(
f"https://api.weather.gov/gridpoints/TOP/{location_points}/forecast", timeout=20
).json()
print("Got weather. Building script...")
with open("forecast.json", "w") as f:
json.dump(weather_data, f)
forecast_length = config.get("forecast_length", None)
shutil.rmtree("sound_files", ignore_errors=True)
os.mkdir("sound_files")
for i, period in enumerate(weather_data["properties"]["periods"]):
if forecast_length is None or i < forecast_length:
filename = period["name"].replace(" ", "_")
outstr = ""
if i == 0:
outstr += f'Current Temperature is {period["temperature"]} degrees. '
outstr += f'{period["name"]} {period["detailedForecast"]}'
for key, replacement in replacements.items():
outstr = outstr.replace(key, replacement)
print(f"script: {outstr}")
print("Generating audio...")
audio = m.generate(outstr, voice=voice)
output_file = f"sound_files/{filename}.wav"
print(f"Writing {output_file}")
sf.write(output_file, audio, 24000)
print("Audio generation complete")

View file

@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
voice = "expr-voice-3-f"
location_points = "36,33"
forecast_length = 3
#sound_device = "plughw:3,0"
available_voices = [
'expr-voice-2-m',
'expr-voice-2-f',
'expr-voice-3-m',
'expr-voice-3-f',
'expr-voice-4-m',
'expr-voice-4-f',
'expr-voice-5-m',
'expr-voice-5-f' ]