Add docker
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
*
|
||||||
|
!requirements.txt
|
||||||
|
!MANIFEST.in
|
||||||
|
!setup.py
|
||||||
|
!script/setup
|
||||||
|
!script/run
|
||||||
|
!wyoming_satellite/*.py
|
||||||
|
!docker/run
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
FROM python:3.11-slim-bookworm
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install --yes --no-install-recommends avahi-utils
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY script/setup ./script/
|
||||||
|
COPY setup.py requirements.txt MANIFEST.in ./
|
||||||
|
COPY wyoming_satellite/ ./wyoming_satellite/
|
||||||
|
|
||||||
|
RUN script/setup
|
||||||
|
|
||||||
|
COPY script/run ./script/
|
||||||
|
COPY docker/run ./
|
||||||
|
|
||||||
|
EXPOSE 10700
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/run"]
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
microphone:
|
||||||
|
image: "rhasspy/wyoming-mic-external"
|
||||||
|
ports:
|
||||||
|
- "10600:10600"
|
||||||
|
devices:
|
||||||
|
- /dev/snd:/dev/snd
|
||||||
|
group_add:
|
||||||
|
- audio
|
||||||
|
command:
|
||||||
|
- "--device"
|
||||||
|
- "sysdefault"
|
||||||
|
- "--debug"
|
||||||
|
playback:
|
||||||
|
image: "rhasspy/wyoming-snd-external"
|
||||||
|
ports:
|
||||||
|
- "10601:10601"
|
||||||
|
devices:
|
||||||
|
- /dev/snd:/dev/snd
|
||||||
|
group_add:
|
||||||
|
- audio
|
||||||
|
command:
|
||||||
|
- "--device"
|
||||||
|
- "sysdefault"
|
||||||
|
- "--debug"
|
||||||
|
satellite:
|
||||||
|
image: "rhasspy/wyoming-satellite"
|
||||||
|
ports:
|
||||||
|
- "10700:10700"
|
||||||
|
command:
|
||||||
|
- "--name"
|
||||||
|
- "my satellite"
|
||||||
|
- "--mic-uri"
|
||||||
|
- "tcp://microphone:10600"
|
||||||
|
- "--snd-uri"
|
||||||
|
- "tcp://playback:10601"
|
||||||
|
- "--debug"
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
/app/script/run \
|
||||||
|
--uri tcp://0.0.0.0:10700 "$@"
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
docker buildx build . \
|
||||||
|
-t 'rhasspy/wyoming-satellite' "$@"
|
||||||
Executable
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
docker run \
|
||||||
|
-it \
|
||||||
|
-p 10700:10700 \
|
||||||
|
--device /dev/snd \
|
||||||
|
'rhasspy/wyoming-satellite' "$@"
|
||||||
@@ -5,7 +5,6 @@ import setuptools
|
|||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
this_dir = Path(__file__).parent
|
this_dir = Path(__file__).parent
|
||||||
module_dir = this_dir / "wyoming_handle_external"
|
|
||||||
|
|
||||||
requirements = []
|
requirements = []
|
||||||
requirements_path = this_dir / "requirements.txt"
|
requirements_path = this_dir / "requirements.txt"
|
||||||
@@ -19,8 +18,8 @@ if requirements_path.is_file():
|
|||||||
setup(
|
setup(
|
||||||
name="wyoming_handle_external",
|
name="wyoming_handle_external",
|
||||||
version="1.0.0",
|
version="1.0.0",
|
||||||
description="Wyoming server for external intent handling",
|
description="Wyoming server for remote voice satellite",
|
||||||
url="http://github.com/rhasspy/wyoming-handle-external",
|
url="http://github.com/rhasspy/wyoming-satellite",
|
||||||
author="Michael Hansen",
|
author="Michael Hansen",
|
||||||
author_email="mike@rhasspy.org",
|
author_email="mike@rhasspy.org",
|
||||||
packages=setuptools.find_packages(),
|
packages=setuptools.find_packages(),
|
||||||
@@ -35,5 +34,5 @@ setup(
|
|||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
],
|
],
|
||||||
keywords="rhasspy wyoming intent handle",
|
keywords="rhasspy wyoming satellite",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import argparse
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
import uuid
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from wyoming.asr import Transcript
|
from wyoming.asr import Transcript, Transcribe
|
||||||
from wyoming.audio import AudioChunk, AudioStart, AudioStop
|
from wyoming.audio import AudioChunk, AudioStart, AudioStop
|
||||||
from wyoming.client import AsyncClient
|
from wyoming.client import AsyncClient
|
||||||
from wyoming.event import Event
|
from wyoming.event import Event
|
||||||
@@ -59,7 +60,7 @@ async def main() -> None:
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--zeroconf-name",
|
"--zeroconf-name",
|
||||||
help="Name used for zeroconf discovery (default: satellite name)",
|
help="Name used for zeroconf discovery (default: MAC from uuid.getnode)",
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
parser.add_argument("--debug", action="store_true", help="Log DEBUG messages")
|
parser.add_argument("--debug", action="store_true", help="Log DEBUG messages")
|
||||||
@@ -86,13 +87,16 @@ async def main() -> None:
|
|||||||
if (not args.no_zeroconf) and isinstance(server, AsyncTcpServer):
|
if (not args.no_zeroconf) and isinstance(server, AsyncTcpServer):
|
||||||
from wyoming.zeroconf import register_server
|
from wyoming.zeroconf import register_server
|
||||||
|
|
||||||
|
if not args.zeroconf_name:
|
||||||
|
args.zeroconf_name = get_mac_address()
|
||||||
|
|
||||||
tcp_server: AsyncTcpServer = server
|
tcp_server: AsyncTcpServer = server
|
||||||
await register_server(
|
await register_server(
|
||||||
name=args.zeroconf_name or args.name,
|
name=args.zeroconf_name,
|
||||||
port=tcp_server.port,
|
port=tcp_server.port,
|
||||||
host=tcp_server.host,
|
host=tcp_server.host,
|
||||||
)
|
)
|
||||||
_LOGGER.debug("Zeroconf discovery enabled")
|
_LOGGER.debug("Zeroconf discovery enabled (name=%s)", args.zeroconf_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await server.run(partial(SatelliteEventHandler, wyoming_info, args))
|
await server.run(partial(SatelliteEventHandler, wyoming_info, args))
|
||||||
@@ -195,6 +199,7 @@ class SatelliteEventHandler(AsyncEventHandler):
|
|||||||
elif (
|
elif (
|
||||||
Detect.is_type(event.type)
|
Detect.is_type(event.type)
|
||||||
or Detection.is_type(event.type)
|
or Detection.is_type(event.type)
|
||||||
|
or Transcribe.is_type(event.type)
|
||||||
or VoiceStarted.is_type(event.type)
|
or VoiceStarted.is_type(event.type)
|
||||||
or VoiceStopped.is_type(event.type)
|
or VoiceStopped.is_type(event.type)
|
||||||
or Synthesize.is_type(event.type)
|
or Synthesize.is_type(event.type)
|
||||||
@@ -202,6 +207,7 @@ class SatelliteEventHandler(AsyncEventHandler):
|
|||||||
# Other client events:
|
# Other client events:
|
||||||
# - Detect for start of wake word detection
|
# - Detect for start of wake word detection
|
||||||
# - Detection for when wake word is detected
|
# - Detection for when wake word is detected
|
||||||
|
# - Transcribe for when STT starts
|
||||||
# - VoiceStarted/VoiceStopped for when user starts/stops speaking
|
# - VoiceStarted/VoiceStopped for when user starts/stops speaking
|
||||||
# - Synthesize for TTS text
|
# - Synthesize for TTS text
|
||||||
await self.forward_event(event)
|
await self.forward_event(event)
|
||||||
@@ -322,6 +328,18 @@ class SatelliteEventHandler(AsyncEventHandler):
|
|||||||
self.is_running = False
|
self.is_running = False
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def get_mac_address() -> str:
|
||||||
|
"""Return MAC address formatted as hex with no colons."""
|
||||||
|
return "".join(
|
||||||
|
["{:02x}".format((uuid.getnode() >> ele) & 0xFF) for ele in range(0, 8 * 6, 8)][
|
||||||
|
::-1
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user