Example: Hello Daisys, asynchronous client

This example shows:

  1. How to create the asyncio client using a context manager.

  2. Get a list of voices.

  3. If there are none, how to generate a voice.

  4. Reference the voice to generate audio (a “take”) for some text.

  5. Download the resulting audio.

  6. Get the take information by identifier or as a filtered list.

To run it, you must replace the username and password with your credentials.

Example output
$ python3 -m examples.hello_daisys_async
Found Daisys Speak API version=1 minor=0
Found voices: []
Not enough voices!
Using model "shakespeare"
Generating a voice.
Sally speaking!
Read 208940 bytes of wav data, wrote "hello_daisys.wav".
Checking take: True
Checking list of takes: True
Deleting take t01hbbgyx2008ggp61pzh6jaemf: True
Deleting voice v01hbbgyrpxxbcj6q37f1yd03gd: True
examples/hello_daisys_async.py
 1import os, asyncio
 2from daisys import DaisysAPI
 3from daisys.v1.speak import VoiceGender, SimpleProsody, DaisysTakeGenerateError, HTTPStatusError
 4
 5# Override DAISYS_EMAIL and DAISYS_PASSWORD with your details!
 6EMAIL = os.environ.get('DAISYS_EMAIL', 'user@example.com')
 7PASSWORD = os.environ.get('DAISYS_PASSWORD', 'pw')
 8
 9# Please see tokens_example.py for how to use an access token instead of a password.
10
11async def main():
12    async with DaisysAPI('speak', email=EMAIL, password=PASSWORD) as speak:
13        print('Found Daisys Speak API', await speak.version())
14
15        # The following is an example of how to use the Daisys API for generating a voice
16        # and then using it in a speech generation task.  The API generates "takes"
17        # representing one or more sentences from a speaker.  The same example is possible
18        # with the synchronous client, where the 'await' keywords should be removed.
19
20        # Get a list of all voices
21        voices = await speak.get_voices()
22        print('Found voices:', [voice.name for voice in voices])
23
24        # Choose one
25        if len(voices) > 0:
26            voice = voices[-1]
27            delete_voice = False
28        else:
29            print('Not enough voices!')
30
31            # Okay, let's generate a voice.
32
33            # First we need to know the model.
34            models = await speak.get_models()
35            if len(models) > 0:
36                model = models[0]
37                print(f'Using model "{model.displayname}"')
38            else:
39                print('No models found!')
40                return
41
42            print('Generating a voice.')
43            voice = await speak.generate_voice(name='Lucy', gender=VoiceGender.FEMALE, model=model.name)
44            delete_voice = True
45
46            # Try to modify the voice's name
47            voice.name = 'Sally'
48            await speak.update_voice(**dict(voice))
49            voice = await speak.get_voice(voice.voice_id)
50
51        # Now we have a voice.
52        print(voice.name, 'speaking!')
53
54        try:
55            # Synthesize some audio from text
56            take = await speak.generate_take(voice_id=voice.voice_id, text="Hello there, I am Daisys!",
57                                             prosody=SimpleProsody(pace=-3, pitch=2, expression=10))
58        except DaisysTakeGenerateError as e:
59            print('Error generating take:', str(e))
60            return
61
62        # The take is now READY.  We get its associated audio file.  We provide a filename
63        # so that it gets written to disk, but it is also returned.
64        audio_wav = await speak.get_take_audio(take.take_id, file='hello_daisys.wav')
65
66        print(f'Read {len(audio_wav)} bytes of wav data, wrote "hello_daisys.wav".')
67
68        # Let's check if we can get info on it again.
69        check_take = await speak.get_take(take.take_id)
70        print('Checking take:', check_take == take)
71
72        # Let's check if we can find it in the most recent 5 takes.
73        last_5_takes = await speak.get_takes(length=5)
74        print('Checking list of takes:', take.take_id in [t.take_id for t in last_5_takes])
75
76        # Delete the take
77        print(f'Deleting take {take.take_id}:', await speak.delete_take(take.take_id))
78
79        # Delete the voice
80        if delete_voice:
81            print(f'Deleting voice {voice.voice_id}:', await speak.delete_voice(voice.voice_id))
82
83if __name__=='__main__':
84    try:
85        asyncio.run(main())
86    except HTTPStatusError as e:
87        try:
88            print(f'HTTP error status {e.response.status_code}: {e.response.json()["detail"]}')
89        except:
90            print(f'HTTP error status {e.response.status_code}: {e.response.text}')