PIPER and Custom Voices

Trying to get a custom voice to show up in my Home Assistant and Pipper running as Docker container. Every things works, except the custom voice does not show or can not be used.

docker-compose.yaml"


 piper:  
    image: slackr31337/wyoming-piper-gpu:latest
    container_name: piper  

    ports:  
      - 10200:10200  
    environment:  
      - TZ=America/Chicago  
      - PIPER_VOICE=en_US-myvoice-high
      - PIPER_LENGTH=1.25
      - PIPER_NOISE=0.667
      - PIPER_NOISEW=0.333
      - PIPER_SPEAKER=0
      - PIPER_SILENCE=0.8     
            
    volumes:  
      - /opt/voiceAssistant/piper-data:/data
      - /opt/voiceAssistant/piper-data/share:/share
      - /opt/voiceAssistant/piper-data/share/piper/voices.json:/app/lib/python3.10/site-packages/wyoming_piper/voices.json:ro
    restart: unless-stopped
    runtime: nvidia
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities:
                - gpu
                - utility
                - compute

/opt/voiceAssistant/piper-data/share/piper/voices.json file:

....
	"aliases": [
		"en-us-ryan-medium"
	]
},
"en_US-myvoice-high": {
	"key": "en_US-myvoice-high",
	"name": "MyVoice",
	"language": {
		"code": "en_US",
		"family": "en",
		"region": "US",
		"name_native": "MyVoice",
		"name_english": "Finnish",
		"country_english": "United States"
	},
	"quality": "high",
	"num_speakers": 1,
	"speaker_id_map": {},
	"files": {
		"en_US-myvoice-high.onnx": {
			"size_bytes": 113800453,
			"md5_digest": "0a1effbae39a77dbe59095924cb8c30c"
		},
		"en_US-myvoice-high.onnx.json": {
			"size_bytes": 7093,
			"md5_digest": "8f8bbee3600f6d8a82270c3e185002d5"
		},
		"MODEL_CARD": {
			"size_bytes": 340,
			"md5_digest": "f09a07e7ccd62e273e8cd18eabd2d654"
		}
	},
	"aliases": [
			"en_US-myvoice-high"
	]
},
"es_ES-carlfm-x_low": {
	"key": "es_ES-carlfm-x_low",
....

I wrote a guide for using custom piper voices with Home Assistant today which explains how to use custom voices in scripts without messing with the contents of the docker container.

Thanks,

Think I forgot to mention that I am running everything as a docker container, including Home Assistant. I am also running multiple satellites and it seem your option outputs to one device.

I can’t help you with issues related to docker but if you need output to go to multiple speakers, you can do that by providing a comma separated list to media_player_entity_id like this:

Got the voice to show up and it seems to be seeing the files. The voice option is now showing as an option. When I select and try to use it seems to try and download the file, but it already in the directory where it downloads the other voices.

Here is the error that it logs:

piper         | ERROR:asyncio:Task exception was never retrieved
piper         | future: <Task finished name='wyoming event handler' coro=<AsyncEventHandler.run() done, defined at /app/lib/python3.10/site-packages/wyoming/server.py:31> exception=VoiceNotFoundError('George-Carlin-V1')>
piper         | Traceback (most recent call last):
piper         |   File "/app/lib/python3.10/site-packages/wyoming/server.py", line 41, in run
piper         |     if not (await self.handle_event(event)):
piper         |   File "/app/lib/python3.10/site-packages/wyoming_piper/handler.py", line 53, in handle_event
piper         |     raise err
piper         |   File "/app/lib/python3.10/site-packages/wyoming_piper/handler.py", line 48, in handle_event
piper         |     return await self._handle_event(event)
piper         |   File "/app/lib/python3.10/site-packages/wyoming_piper/handler.py", line 83, in _handle_event
piper         |     piper_proc = await self.process_manager.get_process(voice_name=voice_name)
piper         |   File "/app/lib/python3.10/site-packages/wyoming_piper/process.py", line 114, in get_process
piper         |     ensure_voice_exists(
piper         |   File "/app/lib/python3.10/site-packages/wyoming_piper/download.py", line 77, in ensure_voice_exists
piper         |     find_voice(name, data_dirs)
piper         |   File "/app/lib/python3.10/site-packages/wyoming_piper/download.py", line 183, in find_voice
piper         |     raise VoiceNotFoundError(name)
piper         | wyoming_piper.download.VoiceNotFoundError: George-Carlin-V

docker compose edit:

...
   environment:  
      - TZ=America/Chicago  
      - PIPER_LENGTH=1.55
      - PIPER_NOISE=0.667
      - PIPER_NOISEW=0.333
      - PIPER_SPEAKER=0
      - PIPER_SILENCE=0.8     
      - PIPER_VOICE=/data/en_US-carlin-high           
    volumes:  
      - /opt/voiceAssistant/piper-data:/data
...

Hi,

A bit late to post, but I was having the same issue and managed to finally solve it by modifying the voices.json file. What I did was, I created a copy of another voice (in my case “fi_FI-harri-medium”) and renamed the copy’s json-key as ‘teppo’ to match the dataset name I had in my fi_FI-teppo-medium.onnx.json (i.e. “dataset”: “teppo”). I left the ‘key’ unchanged so it’s still “fi_Fi-teppo-medium”.

I’m running piper on a container with docker compose with additional parameter: command: --data-dir /data --voice fi_FI-teppo-medium . This alone was enough to test run the custom voice in browser but it seems like the wyoming protocol calls the piper api by the dataset name that then tries to match it to voices.json (or download it automatically from hugginface if missing, which it obviously fails for custom voices).

Hope this helps!

You need to specify the current data for your onnx and json - size and md5 hash.

"ru_RU-marina-medium": {
        "key": "ru_RU-marina-medium",
        "name": "marina",
        "language": {
            "code": "ru_RU",
            "family": "ru",
            "region": "RU",
            "name_native": "Русский",
            "name_english": "Russian",
            "country_english": "Russia"
        },
        "quality": "medium",
        "num_speakers": 1,
        "speaker_id_map": {},
        "files": {
            "ru_RU-marina-medium.onnx": {
                "size_bytes": 63511038,   // < - This
                "md5_digest": "5427e3a73b1a200d24af3115e2d487b7"  // < - This
            },
            "ru_RU-marina-medium.onnx.json": {
                "size_bytes": 7096,  // < - This
                "md5_digest": "65d53f256249481c9aa6c95b4e22cb0c"  // < - This
            },
            "MODEL_CARD": {
                "size_bytes": 271,
                "md5_digest": "397e67453b4ea5a95642673d0debb5ba"
            }
        },
        "aliases": []
    },

After that, the new voices will be available, just like the other voices.

You also need to replace the prepared file in the container
- /path/to/persistent/data/voices.json:/app/lib/python3.10/site-packages/wyoming_piper/voices.json:ro.
The path may vary, so check the contents of the container and locate the directory where the voices.json is located.