This commit is contained in:
Morten Olsen
2025-09-12 10:59:19 +02:00
commit 25939b0141
13 changed files with 889 additions and 0 deletions

18
.dockerignore Normal file
View File

@@ -0,0 +1,18 @@
# Git files
.git/
.gitignore
.gitattributes
.github/
# Documentation
README.md
# Docker files
docker-compose.yml
Dockerfile
# Development files
*.log
*.tmp
.DS_Store

35
.gitattributes vendored Normal file
View File

@@ -0,0 +1,35 @@
*.7z filter=lfs diff=lfs merge=lfs -text
*.arrow filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.ckpt filter=lfs diff=lfs merge=lfs -text
*.ftz filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.h5 filter=lfs diff=lfs merge=lfs -text
*.joblib filter=lfs diff=lfs merge=lfs -text
*.lfs.* filter=lfs diff=lfs merge=lfs -text
*.mlmodel filter=lfs diff=lfs merge=lfs -text
*.model filter=lfs diff=lfs merge=lfs -text
*.msgpack filter=lfs diff=lfs merge=lfs -text
*.npy filter=lfs diff=lfs merge=lfs -text
*.npz filter=lfs diff=lfs merge=lfs -text
*.onnx filter=lfs diff=lfs merge=lfs -text
*.ot filter=lfs diff=lfs merge=lfs -text
*.parquet filter=lfs diff=lfs merge=lfs -text
*.pb filter=lfs diff=lfs merge=lfs -text
*.pickle filter=lfs diff=lfs merge=lfs -text
*.pkl filter=lfs diff=lfs merge=lfs -text
*.pt filter=lfs diff=lfs merge=lfs -text
*.pth filter=lfs diff=lfs merge=lfs -text
*.rar filter=lfs diff=lfs merge=lfs -text
*.safetensors filter=lfs diff=lfs merge=lfs -text
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
*.tar.* filter=lfs diff=lfs merge=lfs -text
*.tar filter=lfs diff=lfs merge=lfs -text
*.tflite filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.wasm filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text
*tfevents* filter=lfs diff=lfs merge=lfs -text

48
.github/release-drafter-config.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name-template: '$RESOLVED_VERSION 🌈'
tag-template: '$RESOLVED_VERSION'
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
label: 'chore'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: patch
autolabeler:
- label: 'chore'
files:
- '*.md'
branch:
- '/docs{0,1}\/.+/'
- label: 'bug'
branch:
- '/fix\/.+/'
title:
- '/fix/i'
- label: 'enhancement'
branch:
- '/feature\/.+/'
- '/feat\/.+/'
title:
- '/feat:.+/'
template: |
## Changes
$CHANGES

21
.github/workflows/auto-labeler.yaml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Auto Labeler
on:
pull_request:
types: [opened, reopened, synchronize]
permissions:
contents: read
jobs:
auto-labeler:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter-config.yml
disable-releaser: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,18 @@
name: Draft release
on:
workflow_call:
jobs:
draft-release:
name: Update release drafter
permissions:
contents: write
pull-requests: write
environment: release
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter-config.yml
publish: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

75
.github/workflows/pipeline-default.yaml vendored Normal file
View File

@@ -0,0 +1,75 @@
name: Build and release
on:
push:
branches:
- main
pull_request:
types:
- opened
- synchronize
env:
environment: test
release_channel: latest
DO_NOT_TRACK: "1"
DOCKER_REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
permissions:
contents: write
packages: read
pull-requests: write
id-token: write
actions: read
security-events: write
jobs:
update-release-draft:
if: github.ref == 'refs/heads/main'
uses: ./.github/workflows/job-draft-release.yaml
release:
permissions:
contents: read
packages: write
attestations: write
id-token: write
pages: write
name: Release
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: update-release-draft
environment: release
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# - name: Generate artifact attestation
# uses: actions/attest-build-provenance@v2
# with:
# subject-name: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME}}
# subject-digest: ${{ steps.push.outputs.digest }}
# push-to-registry: true

4
.u8.json Normal file
View File

@@ -0,0 +1,4 @@
{
"values": {},
"entries": []
}

15
Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
FROM rhasspy/wyoming-piper
# Copy custom GLaDOS model directly to the data directory root
# Wyoming Piper looks for voices in the root of the data directory
COPY model/en_US_glados_medium.onnx /usr/share/piper-voices/en_US-glados-medium.onnx
COPY model/en_US_glados_medium.json /usr/share/piper-voices/en_US-glados-medium.onnx.json
# Set proper permissions
RUN chmod -R 755 /usr/share/piper-voices/
# Expose the Wyoming protocol port
EXPOSE 10200
# Use the default CMD from the base image
# The base image should handle running the Wyoming Piper server

97
README.md Normal file
View File

@@ -0,0 +1,97 @@
# Piper GLaDOS Medium Voice for Home Assistant
This container provides a custom GLaDOS voice model for Home Assistant's Wyoming Piper TTS integration.
## Model Information
- **Voice**: GLaDOS (from Portal video game series)
- **Language**: English (US)
- **Quality**: Medium
- **Sample Rate**: 22.05 kHz
- **Source**: https://huggingface.co/Stoned-Code/piper-en_US-glados-medium/tree/main
## Quick Start
### Build and Run with Docker Compose
```bash
# Build and start the container
docker-compose up -d
# Check logs
docker-compose logs -f piper-glados
```
### Manual Docker Build
```bash
# Build the image
docker build -t piper-glados-medium .
# Run the container
docker run -d \
--name piper-glados-medium \
-p 10200:10200 \
--restart unless-stopped \
piper-glados-medium
```
## Home Assistant Integration
1. **Add to your Home Assistant configuration.yaml**:
```yaml
tts:
- platform: wyoming
host: <container-ip-or-hostname>
port: 10200
name: "Piper GLaDOS"
```
2. **Or use Home Assistant UI**:
- Go to Settings → Devices & Services
- Click "Add Integration"
- Search for "Wyoming Protocol"
- Enter the container's IP address and port 10200
3. **Test the voice**:
- Go to Developer Tools → Services
- Select `tts.speak`
- Choose entity: `tts.piper_glados`
- Enter test message and target media player
## Available Voice
Once integrated, you'll have access to:
- Voice ID: `en_US-glados-medium`
- Language: English (United States)
- Speaker: GLaDOS
## Container Details
- **Base Image**: `rhasspy/wyoming-piper`
- **Protocol**: Wyoming (compatible with Home Assistant 2023.5+)
- **Port**: 10200 (Wyoming protocol)
- **Model Path**: `/usr/share/piper-voices/en_US/glados/medium/`
## Troubleshooting
### Check if the service is running:
```bash
curl http://localhost:10200/api/voices
```
### View container logs:
```bash
docker logs piper-glados-medium
```
### Test TTS directly:
```bash
echo "Hello, subject. The tests are now complete." | docker exec -i piper-glados-medium piper --model /usr/share/piper-voices/en_US/glados/medium/en_US-glados-medium.onnx --output-file - | aplay
```
## Model Files
- `model/en_US_glados_medium.onnx` - Neural network model
- `model/en_US_glados_medium.json` - Model configuration and phoneme mappings

27
build.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/bin/bash
# Build script for Piper GLaDOS container
set -e
IMAGE_NAME="piper-glados-medium"
CONTAINER_NAME="piper-glados-medium"
echo "🏗️ Building Piper GLaDOS container..."
docker build -t "$IMAGE_NAME" .
echo "🧪 Testing if model files are correctly placed..."
docker run --rm "$IMAGE_NAME" ls -la /usr/share/piper-voices/en_US/glados/medium/
echo "🔍 Verifying Piper can load the model..."
docker run --rm "$IMAGE_NAME" piper --model /usr/share/piper-voices/en_US/glados/medium/en_US-glados-medium.onnx --help
echo "✅ Build completed successfully!"
echo ""
echo "To run the container:"
echo " docker run -d --name $CONTAINER_NAME -p 10200:10200 $IMAGE_NAME"
echo ""
echo "Or use docker-compose:"
echo " docker-compose up -d"
echo ""
echo "Test the voice API at: http://localhost:10200/api/voices"

26
docker-compose.yml Normal file
View File

@@ -0,0 +1,26 @@
version: "3.8"
services:
piper-glados:
build: .
container_name: piper-glados-medium
ports:
- "10200:5000"
environment:
# Wyoming Piper will automatically discover models in /usr/share/piper-voices/
- PIPER_DEBUG=1
command:
[
"--piper",
"/usr/share/piper/piper",
"--voice",
"en_US-glados-medium",
"--data-dir",
"/usr/share/piper-voices",
]
restart: no
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:10200/api/voices || exit 1"]
interval: 30s
timeout: 10s
retries: 3

View File

@@ -0,0 +1,502 @@
{
"audio": {
"sample_rate": 22050,
"quality": "medium"
},
"espeak": {
"voice": "en-us"
},
"inference": {
"noise_scale": 0.667,
"length_scale": 1,
"noise_w": 0.8
},
"phoneme_type": "espeak",
"phoneme_map": {},
"phoneme_id_map": {
" ": [
3
],
"!": [
4
],
"\"": [
150
],
"#": [
149
],
"$": [
2
],
"'": [
5
],
"(": [
6
],
")": [
7
],
",": [
8
],
"-": [
9
],
".": [
10
],
"0": [
130
],
"1": [
131
],
"2": [
132
],
"3": [
133
],
"4": [
134
],
"5": [
135
],
"6": [
136
],
"7": [
137
],
"8": [
138
],
"9": [
139
],
":": [
11
],
";": [
12
],
"?": [
13
],
"X": [
156
],
"^": [
1
],
"_": [
0
],
"a": [
14
],
"b": [
15
],
"c": [
16
],
"d": [
17
],
"e": [
18
],
"f": [
19
],
"g": [
154
],
"h": [
20
],
"i": [
21
],
"j": [
22
],
"k": [
23
],
"l": [
24
],
"m": [
25
],
"n": [
26
],
"o": [
27
],
"p": [
28
],
"q": [
29
],
"r": [
30
],
"s": [
31
],
"t": [
32
],
"u": [
33
],
"v": [
34
],
"w": [
35
],
"x": [
36
],
"y": [
37
],
"z": [
38
],
"æ": [
39
],
"ç": [
40
],
"ð": [
41
],
"ø": [
42
],
"ħ": [
43
],
"ŋ": [
44
],
"œ": [
45
],
"ǀ": [
46
],
"ǁ": [
47
],
"ǂ": [
48
],
"ǃ": [
49
],
"ɐ": [
50
],
"ɑ": [
51
],
"ɒ": [
52
],
"ɓ": [
53
],
"ɔ": [
54
],
"ɕ": [
55
],
"ɖ": [
56
],
"ɗ": [
57
],
"ɘ": [
58
],
"ə": [
59
],
"ɚ": [
60
],
"ɛ": [
61
],
"ɜ": [
62
],
"ɞ": [
63
],
"ɟ": [
64
],
"ɠ": [
65
],
"ɡ": [
66
],
"ɢ": [
67
],
"ɣ": [
68
],
"ɤ": [
69
],
"ɥ": [
70
],
"ɦ": [
71
],
"ɧ": [
72
],
"ɨ": [
73
],
"ɪ": [
74
],
"ɫ": [
75
],
"ɬ": [
76
],
"ɭ": [
77
],
"ɮ": [
78
],
"ɯ": [
79
],
"ɰ": [
80
],
"ɱ": [
81
],
"ɲ": [
82
],
"ɳ": [
83
],
"ɴ": [
84
],
"ɵ": [
85
],
"ɶ": [
86
],
"ɸ": [
87
],
"ɹ": [
88
],
"ɺ": [
89
],
"ɻ": [
90
],
"ɽ": [
91
],
"ɾ": [
92
],
"ʀ": [
93
],
"ʁ": [
94
],
"ʂ": [
95
],
"ʃ": [
96
],
"ʄ": [
97
],
"ʈ": [
98
],
"ʉ": [
99
],
"ʊ": [
100
],
"ʋ": [
101
],
"ʌ": [
102
],
"ʍ": [
103
],
"ʎ": [
104
],
"ʏ": [
105
],
"ʐ": [
106
],
"ʑ": [
107
],
"ʒ": [
108
],
"ʔ": [
109
],
"ʕ": [
110
],
"ʘ": [
111
],
"ʙ": [
112
],
"ʛ": [
113
],
"ʜ": [
114
],
"ʝ": [
115
],
"ʟ": [
116
],
"ʡ": [
117
],
"ʢ": [
118
],
"ʦ": [
155
],
"ʰ": [
145
],
"ʲ": [
119
],
"ˈ": [
120
],
"ˌ": [
121
],
"ː": [
122
],
"ˑ": [
123
],
"˞": [
124
],
"ˤ": [
146
],
"̃": [
141
],
"̧": [
140
],
"̩": [
144
],
"̪": [
142
],
"̯": [
143
],
"̺": [
152
],
"̻": [
153
],
"β": [
125
],
"ε": [
147
],
"θ": [
126
],
"χ": [
127
],
"ᵻ": [
128
],
"↑": [
151
],
"↓": [
148
],
"ⱱ": [
129
]
},
"num_symbols": 256,
"num_speakers": 1,
"speaker_id_map": {},
"piper_version": "1.0.0",
"language": {
"code": "en_US",
"family": "en",
"region": "US",
"name_native": "English",
"name_english": "English",
"country_english": "United States"
},
"dataset": "GLaDOS"
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dd1d155f8871452a54fc7db399390691d0252e53a2c84042cd40d33e867890be
size 63516050