Author SHA1 Message Date
Michael Hansen 13bb024931 Merge pull request #308 from AnkushMalaker/master
Update pyproject.toml to fix broken build
2025-04-25 13:52:50 -05:00
Ankush Malaker 04fe5e6827 Update pyproject.toml 2025-04-25 21:22:21 +05:30
Michael Hansen 0efb7fb8f2 Merge pull request #225 from mrdarrengriffin/ohf-logo
Add OHF logo to README
2025-04-22 10:07:48 -05:00
Michael Hansen ac0b4c7d14 Bump version 2025-02-10 11:57:13 -06:00
Michael Hansen c237a4887d Send Played event to server 2025-02-10 11:56:21 -06:00
Michael Hansen f86d236432 Update changelog 2025-01-24 09:43:28 -06:00
Michael Hansen b2409a4a40 Move other requirements to pyproject.toml 2025-01-24 09:42:20 -06:00
Michael Hansen 2c72ad0e01 Migrate to pyproject.toml 2025-01-24 09:28:51 -06:00
Michael Hansen 3576c0fc5f Lint 2025-01-24 09:28:38 -06:00
Michael Hansen 1915d3fce3 Send audio-start to wake service after detect 2025-01-24 09:17:54 -06:00
Darren Griffin 632b392154 Add OHF logo to README 2024-09-30 17:09:19 +01:00
21 changed files with 108 additions and 110 deletions
+1 -3
View File
@@ -1,7 +1,5 @@
* *
!requirements.txt !pyproject.toml
!MANIFEST.in
!setup.py
!script/setup !script/setup
!script/run !script/run
!wyoming_satellite/*.py !wyoming_satellite/*.py
+12
View File
@@ -1,5 +1,17 @@
# Changelog # Changelog
## 1.4.1
- Send `played` event to server
## 1.4.0
- Migrate to pyproject.toml
## 1.3.1
- Send audio-start to wake service after detect
## 1.3.0 ## 1.3.0
- Bump to wyoming 1.5.4 (timers) - Bump to wyoming 1.5.4 (timers)
+1 -1
View File
@@ -10,7 +10,7 @@ WORKDIR /app
COPY sounds/ ./sounds/ COPY sounds/ ./sounds/
COPY script/setup ./script/ COPY script/setup ./script/
COPY setup.py requirements.txt MANIFEST.in ./ COPY pyproject.toml ./
COPY wyoming_satellite/ ./wyoming_satellite/ COPY wyoming_satellite/ ./wyoming_satellite/
RUN script/setup RUN script/setup
-2
View File
@@ -1,2 +0,0 @@
include requirements.txt
include VERSION
+1
View File
@@ -13,6 +13,7 @@ Video tutorials:
* [Wyoming Voice Satellite with ChatGPT](https://www.youtube.com/watch?v=eTKgc0YDCwE) * [Wyoming Voice Satellite with ChatGPT](https://www.youtube.com/watch?v=eTKgc0YDCwE)
* [Local ChatGPT Voice Assistant](https://www.youtube.com/watch?v=pAKqKTkx5X4) * [Local ChatGPT Voice Assistant](https://www.youtube.com/watch?v=pAKqKTkx5X4)
[![An open standard from the Open Home Foundation](https://www.openhomefoundation.org/badges/ohf-open-standard.png)](https://www.openhomefoundation.org/)
--- ---
Requires: Requires:
+1 -3
View File
@@ -55,9 +55,7 @@ python3 -m venv .venv
.venv/bin/pip3 install --upgrade wheel setuptools .venv/bin/pip3 install --upgrade wheel setuptools
.venv/bin/pip3 install \ .venv/bin/pip3 install \
-f 'https://synesthesiam.github.io/prebuilt-apps/' \ -f 'https://synesthesiam.github.io/prebuilt-apps/' \
-r requirements.txt \ -e '.[all]'
-r requirements_audio_enhancement.txt \
-r requirements_vad.txt
``` ```
If the installation was successful, you should be able to run: If the installation was successful, you should be able to run:
+6 -5
View File
@@ -6,6 +6,7 @@ import logging
import time import time
from functools import partial from functools import partial
from pixel_ring import pixel_ring
from wyoming.event import Event from wyoming.event import Event
from wyoming.satellite import ( from wyoming.satellite import (
SatelliteConnected, SatelliteConnected,
@@ -13,15 +14,14 @@ from wyoming.satellite import (
StreamingStarted, StreamingStarted,
StreamingStopped, StreamingStopped,
) )
from wyoming.snd import Played
from wyoming.server import AsyncEventHandler, AsyncServer from wyoming.server import AsyncEventHandler, AsyncServer
from wyoming.snd import Played
from wyoming.vad import VoiceStarted, VoiceStopped from wyoming.vad import VoiceStarted, VoiceStopped
from wyoming.wake import Detection from wyoming.wake import Detection
from pixel_ring import pixel_ring
_LOGGER = logging.getLogger() _LOGGER = logging.getLogger()
async def main() -> None: async def main() -> None:
"""Main entry point.""" """Main entry point."""
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@@ -35,7 +35,7 @@ async def main() -> None:
_LOGGER.info("Ready") _LOGGER.info("Ready")
# Turn on power to LEDs # Turn on power to LEDs
pixel_ring.set_color_palette(0x0080ff, 0x007a37) pixel_ring.set_color_palette(0x0080FF, 0x007A37)
pixel_ring.think() pixel_ring.think()
await asyncio.sleep(3) await asyncio.sleep(3)
pixel_ring.off() pixel_ring.off()
@@ -92,10 +92,11 @@ class LEDsEventHandler(AsyncEventHandler):
pixel_ring.off() pixel_ring.off()
elif SatelliteDisconnected.is_type(event.type): elif SatelliteDisconnected.is_type(event.type):
_LOGGER.debug("SatelliteDisconnected") _LOGGER.debug("SatelliteDisconnected")
pixel_ring.mono(0xff0000) pixel_ring.mono(0xFF0000)
return True return True
if __name__ == "__main__": if __name__ == "__main__":
try: try:
asyncio.run(main()) asyncio.run(main())
+3 -7
View File
@@ -123,7 +123,7 @@ def apply_settings(settings: Settings) -> None:
): ):
result = run_with_gauge( result = run_with_gauge(
"Installing vad...", "Installing vad...",
[pip_install("-r", str(PROGRAM_DIR / "requirements_vad.txt"))], [pip_install("-e", f"{PROGRAM_DIR}[silerovad]")],
) )
if not result: if not result:
error("installing vad") error("installing vad")
@@ -135,11 +135,7 @@ def apply_settings(settings: Settings) -> None:
): ):
result = run_with_gauge( result = run_with_gauge(
"Installing audio enhancements...", "Installing audio enhancements...",
[ [pip_install("-e", f"{PROGRAM_DIR}[webrtc]")],
pip_install(
"-r", str(PROGRAM_DIR / "requirements_audio_enhancement.txt")
)
],
) )
if not result: if not result:
error("installing audio enhancements") error("installing audio enhancements")
@@ -154,7 +150,7 @@ def apply_settings(settings: Settings) -> None:
) and (not can_import("gpiozero", "spidev")): ) and (not can_import("gpiozero", "spidev")):
result = run_with_gauge( result = run_with_gauge(
"Installing event requirements...", "Installing event requirements...",
[pip_install("-r", str(PROGRAM_DIR / "requirements_respeaker.txt"))], [pip_install("-e", f"{PROGRAM_DIR}[respeaker]")],
) )
if not result: if not result:
error("installing event requirements") error("installing event requirements")
+61
View File
@@ -0,0 +1,61 @@
[build-system]
requires = ["setuptools>=62.3"]
build-backend = "setuptools.build_meta"
[project]
name = "wyoming_satellite"
version = "1.4.1"
license = {text = "MIT"}
description = "Wyoming server for remote voice satellite"
readme = "README.md"
authors = [
{name = "Michael Hansen", email = "mike@rhasspy.org"}
]
keywords = ["rhasspy", "wyoming", "satellite"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
requires-python = ">=3.9.0"
dependencies = [
"wyoming==1.5.4",
"zeroconf==0.88.0",
"pyring-buffer>=1,<2",
]
[project.optional-dependencies]
all = ["pysilero-vad==1.0.0", "webrtc-noise-gain==1.2.3"]
silerovad = ["pysilero-vad==1.0.0"]
webrtc = ["webrtc-noise-gain==1.2.3"]
respeaker = ["gpiozero", "spidev"]
dev = [
"black==22.12.0",
"flake8==6.0.0",
"isort==5.11.3",
"mypy==0.991",
"pylint==2.15.9",
"pytest==7.4.3",
"pytest-asyncio==0.23.3",
"build==1.2.2"
]
[project.scripts]
wyoming-satellite = "wyoming_satellite:__main__.run"
[project.urls]
"Source Code" = "http://github.com/rhasspy/wyoming-satellite"
[tool.setuptools]
platforms = ["any"]
zip-safe = true
include-package-data = true
[tool.setuptools.packages.find]
include = ["wyoming_satellite*"]
exclude = ["tests", "tests.*"]
-3
View File
@@ -1,3 +0,0 @@
wyoming==1.5.4
zeroconf==0.88.0
pyring-buffer==1.0.0
-1
View File
@@ -1 +0,0 @@
webrtc-noise-gain==1.2.3
-7
View File
@@ -1,7 +0,0 @@
black==22.12.0
flake8==6.0.0
isort==5.11.3
mypy==0.991
pylint==2.15.9
pytest==7.4.3
pytest-asyncio==0.23.3
-2
View File
@@ -1,2 +0,0 @@
gpiozero
spidev
-1
View File
@@ -1 +0,0 @@
pysilero-vad==1.0.0
+1 -1
View File
@@ -8,4 +8,4 @@ _PROGRAM_DIR = _DIR.parent
_VENV_DIR = _PROGRAM_DIR / ".venv" _VENV_DIR = _PROGRAM_DIR / ".venv"
context = venv.EnvBuilder().ensure_directories(_VENV_DIR) context = venv.EnvBuilder().ensure_directories(_VENV_DIR)
subprocess.check_call([context.env_exe, _PROGRAM_DIR / "setup.py", "bdist_wheel"]) subprocess.check_call([context.env_exe, "-m", "build", "--wheel", "--sdist"])
+3 -4
View File
@@ -20,7 +20,6 @@ builder.create(_VENV_DIR)
# Upgrade dependencies # Upgrade dependencies
pip = [context.env_exe, "-m", "pip"] pip = [context.env_exe, "-m", "pip"]
subprocess.check_call(pip + ["install", "--upgrade", "pip"]) subprocess.check_call(pip + ["install", "--upgrade", "pip"])
subprocess.check_call(pip + ["install", "--upgrade", "setuptools", "wheel"])
# Install requirements # Install requirements
subprocess.check_call( subprocess.check_call(
@@ -31,13 +30,13 @@ subprocess.check_call(
"https://www.piwheels.org/simple", "https://www.piwheels.org/simple",
"-f", "-f",
"https://synesthesiam.github.io/prebuilt-apps/", "https://synesthesiam.github.io/prebuilt-apps/",
"-r", "-e",
str(_PROGRAM_DIR / "requirements.txt"), str(_PROGRAM_DIR),
] ]
) )
if args.dev: if args.dev:
# Install dev requirements # Install dev requirements
subprocess.check_call( subprocess.check_call(
pip + ["install", "-r", str(_PROGRAM_DIR / "requirements_dev.txt")] pip + ["install", "-e", f"{_PROGRAM_DIR}[dev]"]
) )
-64
View File
@@ -1,64 +0,0 @@
#!/usr/bin/env python3
from pathlib import Path
from typing import List
import setuptools
from setuptools import setup
this_dir = Path(__file__).parent
module_dir = this_dir / "wyoming_satellite"
version_path = module_dir / "VERSION"
version = version_path.read_text(encoding="utf-8").strip()
def get_requirements(req_path: Path) -> List[str]:
if not req_path.is_file():
return []
requirements: List[str] = []
with open(req_path, "r", encoding="utf-8") as req_file:
for line in req_file:
line = line.strip()
if not line:
continue
requirements.append(line)
return requirements
install_requires = get_requirements(this_dir / "requirements.txt")
extras_require = {
"silerovad": get_requirements(this_dir / "requirements_vad.txt"),
"webrtc": get_requirements(this_dir / "requirements_audio_enhancement.txt"),
}
# -----------------------------------------------------------------------------
setup(
name="wyoming_satellite",
version="1.1.0",
description="Wyoming server for remote voice satellite",
url="http://github.com/rhasspy/wyoming-satellite",
author="Michael Hansen",
author_email="mike@rhasspy.org",
packages=setuptools.find_packages(),
package_data={
"wyoming_satellite": [str(p.relative_to(module_dir)) for p in (version_path,)]
},
install_requires=install_requires,
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
keywords="rhasspy wyoming satellite",
extras_require=extras_require,
entry_points={
"console_scripts": ["wyoming-satellite = wyoming_satellite:__main__.run"]
},
)
+1 -1
View File
@@ -1,6 +1,6 @@
[tox] [tox]
env_list = env_list =
py{39,310,311} py{39,310,311,312,313}
minversion = 4.12.1 minversion = 4.12.1
[testenv] [testenv]
-1
View File
@@ -1 +0,0 @@
1.3.0
+3 -1
View File
@@ -1,4 +1,6 @@
"""Voice satellite using the Wyoming protocol.""" """Voice satellite using the Wyoming protocol."""
import importlib.metadata
from pathlib import Path from pathlib import Path
from .satellite import ( from .satellite import (
@@ -17,7 +19,7 @@ from .settings import (
) )
_DIR = Path(__file__).parent _DIR = Path(__file__).parent
__version__ = (_DIR / "VERSION").read_text(encoding="utf-8").strip() __version__ = importlib.metadata.version("wyoming-satellite")
__all__ = [ __all__ = [
"__version__", "__version__",
+13 -2
View File
@@ -1,4 +1,5 @@
"""Satellite code.""" """Satellite code."""
import array import array
import asyncio import asyncio
import logging import logging
@@ -514,9 +515,11 @@ class SatelliteBase:
event = AudioChunk( event = AudioChunk(
rate=chunk.rate, rate=chunk.rate,
width=chunk.width, width=chunk.width,
channels=chunk.channels channels=(
chunk.channels
if (self.settings.mic.channel_index is None) if (self.settings.mic.channel_index is None)
else 1, else 1
),
audio=audio_bytes, audio=audio_bytes,
).event() ).event()
else: else:
@@ -617,6 +620,7 @@ class SatelliteBase:
): ):
await _disconnect() await _disconnect()
if snd_event.is_tts: if snd_event.is_tts:
await self.event_to_server(Played().event())
await self.trigger_played() await self.trigger_played()
snd_client = None # reconnect on next event snd_client = None # reconnect on next event
except asyncio.CancelledError: except asyncio.CancelledError:
@@ -805,6 +809,13 @@ class SatelliteBase:
wake_names = [w.name for w in self.settings.wake.names] wake_names = [w.name for w in self.settings.wake.names]
await self.event_to_wake(Detect(names=wake_names).event()) await self.event_to_wake(Detect(names=wake_names).event())
await self.event_to_wake(
AudioStart(
rate=self.settings.mic.rate,
width=self.settings.mic.width,
channels=self.settings.mic.channels,
).event()
)
await self.trigger_detect() await self.trigger_detect()
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------