Compare commits

..

6 Commits

Author SHA1 Message Date
deadvey
31e7eab069 removed duplicating words when using .split(' '), which produces empty None strings, used filter(None, ...) to remove these empty strings 2026-04-02 01:18:25 +01:00
deadvey
aff8a8dd43 added a dedicated sleep function 2026-04-01 18:27:39 +01:00
deadvey
a912836c07 Added the help command 2026-03-30 15:21:29 +01:00
deadvey
302d7ea2e4 readme formatting 2026-03-30 15:15:16 +01:00
deadvey
9923bda2a1 updated the top argument list in readme 2026-03-30 15:14:31 +01:00
deadvey
c59e00cf78 Added support for different voices, renamed language and quote files with their 2 letter abreviations.
New arguments: -v, -c
2026-03-30 15:11:54 +01:00
12 changed files with 1197 additions and 20 deletions

View File

@@ -4,7 +4,7 @@ You can configure the playback speed, language and mode (timed, words, quote or
## Command line options ## Command line options
All these options overide configuration in config.json<br/> All these options overide configuration in config.json<br/>
-w,-m,-f,-o,-t,-q,-l,-u,-i,-h c,f,h,i,l,m,o,q,t,u,v,w<br/>
**--wpm, -w <int>**<br/> **--wpm, -w <int>**<br/>
set the rate of dictation, defaults to 50, note: this is not exact as it measures the time between words in order to avoid a very short gap after a long word.<br/> set the rate of dictation, defaults to 50, note: this is not exact as it measures the time between words in order to avoid a very short gap after a long word.<br/>
**--mode, -m <mode>**<br/> **--mode, -m <mode>**<br/>
@@ -19,6 +19,10 @@ All these options overide configuration in config.json<br/>
Specify a quote ID for quotes mode, see all quotes in your selected language with -u<br/> Specify a quote ID for quotes mode, see all quotes in your selected language with -u<br/>
**--language, -l <language>**<br/> **--language, -l <language>**<br/>
Selects a language, defaults to english, must be a listed language in -i<br/> Selects a language, defaults to english, must be a listed language in -i<br/>
**--voice, -v <voice id>**<br/>
Selects a voice to use, defaults to gwm/en in config.json<br/>
**--list-voices, -c**<br/>
Lists all the available voices you can use, also see [voices.txt](voices.txt)<br/>
**--list-quotes, -u**<br/> **--list-quotes, -u**<br/>
Lists the available quotes and exits<br/> Lists the available quotes and exits<br/>
**--list-languages, -i**<br/> **--list-languages, -i**<br/>
@@ -26,6 +30,11 @@ All these options overide configuration in config.json<br/>
**--help, -h**<br/> **--help, -h**<br/>
Output's this help text and exits<br/> Output's this help text and exits<br/>
## TODO
- Get the dictation to work with non-latin letters
- Get more languages supported
- Make the voice sound less robotic
## Languages ## Languages
Current languages: English or Spanish, I plan to add more though.<br/> Current languages: English or Spanish, I plan to add more though.<br/>
The languages were downloaded from monkeytype.com The languages were downloaded from monkeytype.com

40
args.py
View File

@@ -1,12 +1,14 @@
import os import os
import json import json
def handle_arguments(arguments, config): def handle_arguments(arguments, config, engine):
for index, arg in enumerate(arguments[1:]): for index, arg in enumerate(arguments[1:]):
match arg: match arg:
case '--wpm'|'-w': case '--wpm'|'-w':
config['wpm'] = int(arguments[index+2]) config['wpm'] = int(arguments[index+2])
case '--language'|'-l': case '--language'|'-l':
config['language'] = arguments[index+2] config['language'] = arguments[index+2]
case '--voice'|'-v':
config['voice'] = arguments[index+2]
case '--mode'|'-m': case '--mode'|'-m':
config['mode'] = arguments[index+2] config['mode'] = arguments[index+2]
case '--words'|'-o': case '--words'|'-o':
@@ -28,6 +30,42 @@ def handle_arguments(arguments, config):
for index,quote in enumerate(quotes): for index,quote in enumerate(quotes):
print(f'{index}: {quote['quote']} - {quote['author']}') print(f'{index}: {quote['quote']} - {quote['author']}')
exit() exit()
case '--list-voices'|'-c':
voices = engine.getProperty('voices')
for voice in voices:
print(voice)
exit()
case '--help'|'h':
print('''Command line options
All these options overide configuration in config.json
c,f,h,i,l,m,o,q,t,u,v,w
--wpm, -w <int>
set the rate of dictation, defaults to 50, note: this is not exact as it measures the time between words in order to avoid a very short gap after a long word.
--mode, -m <mode>
Sets a mode, one of 'timed', 'words','quote' or 'file' followed by an optional modifier representing either the time (in seconds) or the number of words, or the quote ID, or the file name.
--filename, -f <filename>
Passes a filename as parameter for the file mode
--words, -o <number of words>
Number of words for words mode
--time, -t <time>
Time in seconds for timed mode
--quote, -q <time>
Specify a quote ID for quotes mode, see all quotes in your selected language with -u
--language, -l <language>
Selects a language, defaults to english, must be a listed language in -i
--voice, -v <voice id>
Selects a voice to use, defaults to gwm/en in config.json
--list-voices, -c
Lists all the available voices you can use, also see [voices.txt](voices.txt)
--list-quotes, -u
Lists the available quotes and exits
--list-languages, -i
Lists the installed languages and exits
--help, -h
Output's this help text and exits
''')
exit()
case _: case _:
continue continue
return config return config

View File

@@ -3,5 +3,6 @@
"words": 20, "words": 20,
"time": 30, "time": 30,
"wpm": 50, "wpm": 50,
"language": "english" "language": "en",
"voice": "gmw/en"
} }

View File

@@ -27,7 +27,7 @@ def words(config, engine):
engine.say(word) engine.say(word)
engine.runAndWait() engine.runAndWait()
# Break between words as determined by the wpm # Break between words as determined by the wpm
time.sleep(1/(config['wpm']/60)) maths.sleep(config['wpm'])
# TIMED # # TIMED #
def timed(config, engine): def timed(config, engine):
@@ -46,8 +46,7 @@ def timed(config, engine):
print(f'{word} ') print(f'{word} ')
engine.runAndWait() engine.runAndWait()
# Break between words as determined by the wpm # Break between words as determined by the wpm
time.sleep(1/(config['wpm']/60)) maths.sleep(config['wpm'])
# check if too much time has elapsed for mode: time # check if too much time has elapsed for mode: time
now = time.time() now = time.time()
# Break condition # Break condition
@@ -67,13 +66,13 @@ def quote(config, engine):
x = random.randint(0, len(quotes)-1) x = random.randint(0, len(quotes)-1)
quote = quotes[x] quote = quotes[x]
print(f'{quote['quote']}\n\t\t\t - {quote['author']}') print(f'{quote['quote']}\n\t\t\t - {quote['author']}')
dictation = quote['quote'].split(' ') dictation = filter(None, quote['quote'].split(' ')) # turn the string into a list of words, the filter function removes empty strings
# Dictate the quote # Dictate the quote
for word in dictation: for word in dictation:
engine.say(word) engine.say(word)
engine.runAndWait() engine.runAndWait()
# Break between words as determined by the wpm # Break between words as determined by the wpm
time.sleep(1/(config['wpm']/60)) maths.sleep(config['wpm'])
# FILE # # FILE #
def file(config, engine): def file(config, engine):
@@ -89,8 +88,8 @@ def file(config, engine):
print(line) print(line)
# Dictation loop # Dictation loop
for line in lines: for line in lines:
for word in line.split(' '): for word in filter(None, line.split(' ')): # the filter function removes empty strings
engine.say(word) engine.say(word)
engine.runAndWait() engine.runAndWait()
# Break between words as determined by the wpm # Break between words as determined by the wpm
time.sleep(1/(config['wpm']/60)) maths.sleep(config['wpm'])

View File

@@ -8,16 +8,14 @@ import dictate
engine = pyttsx3.init() engine = pyttsx3.init()
config = {}
with open('config.json', 'r') as file: with open('config.json', 'r') as file:
config = json.load(file) config = json.load(file)
# Handle the command line arguments # Handle the command line arguments
config = args.handle_arguments(sys.argv, config) config = args.handle_arguments(sys.argv, config, engine)
dictation = ''
engine.setProperty('rate', config['wpm']) engine.setProperty('rate', config['wpm'])
engine.setProperty('voice', config['voice'])
# TODO: match case # TODO: match case
match config['mode']: match config['mode']:
case 'words': case 'words':

View File

@@ -1,4 +1,11 @@
import random import random
import time
# Random number generator that's biased towards 0 # Random number generator that's biased towards 0
def biased_random(max_value, strength=3): def biased_random(max_value, strength=3):
return round((random.random() ** strength) * max_value) return round((random.random() ** strength) * max_value)
def sleep(wpm):
sleep_time = (1/(wpm/60))-1
if sleep_time > 0.0:
time.sleep(sleep_time)

View File

@@ -105,5 +105,7 @@
{ "quote":"A computer is like air conditioning - it becomes useless when you open Windows", "author":"Linus Torvalds"}, { "quote":"A computer is like air conditioning - it becomes useless when you open Windows", "author":"Linus Torvalds"},
{ "quote":"Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.", "author": "Linus Torvalds"}, { "quote":"Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.", "author": "Linus Torvalds"},
{ "quote":"An idiot admires complexity, a genius admires simplicity.", "author":"Terry A. Davis"}, { "quote":"An idiot admires complexity, a genius admires simplicity.", "author":"Terry A. Davis"},
{ "quote":"It is not the well-fed long-haired man I fear, but the pale and the hungry looking.", "author":"Gauis Julius Caesar"} { "quote":"It is not the well-fed long-haired man I fear, but the pale and the hungry looking.", "author":"Gauis Julius Caesar"},
{ "quote":"No, Luke, I am your father", "author":"Anakin Skywalker"},
{ "quote":"Do you wish me a good morning, or mean that it is a good morning whether I want it or not; or that you feel good this morning; or that it is a morning to be good on?", "author":"J.R.R. Tolkien (Gandalf)"}
] ]

423
quotes/es.json Normal file
View File

@@ -0,0 +1,423 @@
[
{
"quote": "La pluma es la lengua del alma.",
"author": "Miguel de Cervantes"
},
{
"quote": "El que quiere interesar a los demás tiene que provocarlos.",
"author": "Salvador Dalí"
},
{
"quote": "Todos los niños nacen artistas. El problema es cómo seguir siendo artistas al crecer.",
"author": "Pablo Picasso"
},
{
"quote": "Una es más auténtica, mientras más se parece a lo que soñó de sí misma.",
"author": "Pedro Almovodar"
},
{
"quote": "Soy el desesperado, la palabra sin ecos, el que lo perdió todo, y el que todo lo tuvo.",
"author": "Pablo Neruda"
},
{
"quote": "Aprender a sonreír es aprender a ser libres.",
"author": "Octavio Paz"
},
{
"quote": "Memoria selectiva para recordar lo bueno, prudencia lógica para no arruinar el presente, y optimismo desafiante para encarar el futuro.",
"author": "Isabel Allende"
},
{
"quote": "¿Se pueden inventar verbos? quiero decirte uno: Yo te cielo, así mis alas se extienden enormes para amarte sin medida.",
"author": "Frida Kalho"
},
{
"quote": "Se necesitan dos años para aprender a hablar y sesenta para aprender a callar.",
"author": "Ernest Hemingway"
},
{
"quote": "No hay que ir para atrás ni para darse impulso.",
"author": "Lao Tsé"
},
{
"quote": "No hay caminos para la paz; la paz es el camino.",
"author": "Mahatma Gandhi"
},
{
"quote": "Haz el amor y no la guerra.",
"author": "John Lennon"
},
{
"quote": "Para trabajar basta estar convencido de una cosa: que trabajar es menos aburrido que divertirse.",
"author": "Charles Baudelaire"
},
{
"quote": "Lo peor que hacen los malos es obligarnos a dudar de los buenos.",
"author": "Jacinto Benavente"
},
{
"quote": "Las guerras seguirán mientras el color de la piel siga siendo más importante que el de los ojos.",
"author": "Bob Marley"
},
{
"quote": "Aprende a vivir y sabrás morir bien.",
"author": "Confucio"
},
{
"quote": "Cada día sabemos más y entendemos menos.",
"author": "Albert Einstein"
},
{
"quote": "El mundo no está en peligro por las malas personas sino por aquellas que permiten la maldad.",
"author": "Albert Einstein"
},
{
"quote": "La medida del amor es amar sin medida.",
"author": "San Agustín"
},
{
"quote": "No hay nada que un hombre no sea capaz de hacer cuando una mujer le mira.",
"author": "Casanova"
},
{
"quote": "Dar el ejemplo no es la principal manera de influir sobre los demás; es la única manera.",
"author": "Albert Einstein"
},
{
"quote": "El dinero no puede comprar la vida.",
"author": "Bob Marley"
},
{
"quote": "Si es bueno vivir, todavía es mejor soñar, y lo mejor de todo, despertar.",
"author": "Antonio Machado"
},
{
"quote": "La mayor declaración de amor es la que no se hace; el hombre que siente mucho, habla poco.",
"author": "Platón"
},
{
"quote": "Si das pescado a un hombre hambriento lo nutres durante una jornada. Si le enseñas a pescar, le nutrirás toda su vida.",
"author": "Lao Tsé"
},
{
"quote": "Vale más actuar exponiéndose a arrepentirse de ello, que arrepentirse de no haber hecho nada.",
"author": "Giovanni Boccaccio"
},
{
"quote": "Ningún hombre es lo bastante bueno para gobernar a otros sin su consentimiento.",
"author": "Abraham Lincoln"
},
{
"quote": "Todo lo que se come sin necesidad se roba al estómago de los pobres.",
"author": "Mahatma Gandhi"
},
{
"quote": "Vivir sola es como estar en una fiesta donde nadie te hace caso.",
"author": "Marilyn Monroe"
},
{
"quote": "El cuerpo humano es el carruaje; el yo, el hombre que lo conduce; el pensamiento son las riendas, y los sentimientos, los caballos.",
"author": "Platón"
},
{
"quote": "Estar preparado es importante, saber esperarlo es aún más, pero aprovechar el momento adecuado es la clave de la vida.",
"author": "Arthur Schnitzler"
},
{
"quote": "No estoy tan enamorado de mis propias opiniones que ignore lo que los demás puedan pensar acerca de ellas.",
"author": "Copérnico"
},
{
"quote": "La más estricta justicia no creo que sea siempre la mejor política.",
"author": "Abraham Lincoln"
},
{
"quote": "El sabio no dice nunca todo lo que piensa, pero siempre piensa todo lo que dice.",
"author": "Aristóteles"
},
{
"quote": "Hay dos cosas que son infinitas: el universo y la estupidez humana; de la primera no estoy muy seguro.",
"author": "Albert Einstein"
},
{
"quote": "El nacimiento y la muerte no son dos estados distintos, sino dos aspectos del mismo estado.",
"author": "Mahatma Gandhi"
},
{
"quote": "Lo que importa verdaderamente en la vida no son los objetivos que nos marcamos, sino los caminos que seguimos para lograrlo.",
"author": "Peter Bamm"
},
{
"quote": "El mundo es bello, pero tiene un defecto llamado hombre.",
"author": "Friedrich Nietzsche"
},
{
"quote": "La pereza viaja tan despacio que la pobreza no tarda en alcanzarla.",
"author": "Benjamin Franklin"
},
{
"quote": "Una velada en que todos los presentes estén absolutamente de acuerdo es una velada perdida.",
"author": "Albert Einstein"
},
{
"quote": "Pienso, luego existo.",
"author": "René Descartes"
},
{
"quote": "Lo que no te mata, te hace más fuerte.",
"author": "Friedrich Nietzsche"
},
{
"quote": "No abras los labios si no estás seguro de que lo que vas a decir es más hermoso que el silencio.",
"author": "Proverbio árabe"
},
{
"quote": "De todos los animales de la creación el hombre es el único que bebe sin tener sed, come sin tener hambre y habla sin tener nada que decir.",
"author": "John Steinbeck"
},
{
"quote": "La esperanza es un estimulante vital muy superior a la suerte.",
"author": "Friedrich Nietzsche"
},
{
"quote": "Un hermano puede no ser un amigo, pero un amigo será siempre un hermano.",
"author": "Benjamin Franklin"
},
{
"quote": "Sólo puede ser feliz siempre el que sepa ser feliz con todo.",
"author": "Confucio"
},
{
"quote": "Ninguna persona merece tus lágrimas, y quien se las merezca no te hará llorar.",
"author": "Gabriel García Márquez"
},
{
"quote": "De humanos es errar y de necios permanecer en el error.",
"author": "Marco Tulio Cicerón"
},
{
"quote": "Algunas personas son tan falsas que ya no distinguen que lo que piensan es justamente lo contrario de lo que dicen.",
"author": "Marcel Aymé"
},
{
"quote": "La verdadera sabiduría está en reconocer la propia ignorancia.",
"author": "Sócrates"
},
{
"quote": "La peor experiencia es la mejor maestra.",
"author": "Kovo"
},
{
"quote": "La Educación es el pasaporte hacia el futuro, el mañana pertenece a aquellos que se preparan para él en el día de hoy.",
"author": "Malcolm X"
},
{
"quote": "Los amigos se convierten con frecuencia en ladrones de nuestro tiempo.",
"author": "Platón"
},
{
"quote": "No permitas que ningún ser humano te haga caer tan bajo como para odiarle.",
"author": "Martin Luther King"
},
{
"quote": "El pesimista se queja del viento; el optimista espera que cambie; el realista ajusta las velas.",
"author": "William George Ward"
},
{
"quote": "Un amigo de todos es una amigo de nadie.",
"author": "Aristóteles"
},
{
"quote": "Hace falta toda una vida para aprender a vivir.",
"author": "Séneca"
},
{
"quote": "Son dolor no hay resultado.",
"author": "Benjamin Franklin"
},
{
"quote": "Estos son mis principios y si no te gustan, tengo otros.",
"author": "Groucho Marx"
},
{
"quote": "La política es el arte de buscar problemas, encontrarlos, realizar un diagnóstico falso y aplicar después remedios equivocados.",
"author": "Groucho Marx"
},
{
"quote": "Los verdaderos líderes deben estar dispuestos a sacrificarlo todo por la libertad de su pueblo.",
"author": "Nelson Mandela"
},
{
"quote": "Es mejor permanecer callado y parecer tonto que hablar y despejar las dudas definitivamente.",
"author": "Groucho Marx"
},
{
"quote": "Aquel que más posee, más miedo tiene de perderlo.",
"author": "Leonardo Da Vinci"
},
{
"quote": "La inspiración existe, pero tiene que encontrarte trabajando.",
"author": "Pablo Picasso"
},
{
"quote": "Incluso la gente que afirma que no podemos hacer nada para cambiar nuestro destino, mira antes de cruzar la calle.",
"author": "Stephen Hawking"
},
{
"quote": "Ojo por ojo y el mundo acabará ciego.",
"author": "Mahatma Gandhi"
},
{
"quote": "Vive como si fueras a morir mañana; aprende como si el mundo fuera a durar para siempre.",
"author": "Mahatma Gandhi"
},
{
"quote": "Solo sé que no sé nada.",
"author": "Sócrates"
},
{
"quote": "Nunca rompas el silencio si no es para mejorarlo.",
"author": "Ludwig van Beethoven"
},
{
"quote": "Puedes engañar a todo el mundo algún tiempo. Puedes engañar a algunos todo el tiempo. Pero no puedes engañar a todo el mundo todo el tiempo.",
"author": "Abraham Lincoln"
},
{
"quote": "La mejor manera de librarse de la tentación es caer en ella.",
"author": "Oscar Wilde"
},
{
"quote": "La duda es la madre de la invención.",
"author": "Galileo Galilei"
},
{
"quote": "Podrán cortar todas las flores, pero no podrán detener la primavera.",
"author": "Pablo Neruda"
},
{
"quote": "Es tan corto el amor y tan largo el olvido.",
"author": "Pablo Neruda"
},
{
"quote": "Uno llega a ser grande por lo que lee y no por lo que escribe.",
"author": "Jorge Luis Borges"
},
{
"quote": "Uno es dueño de lo que calla y esclavo de lo que habla.",
"author": "Sigmund Freud"
},
{
"quote": "El único hombre que no se equivoca es el que nunca hace nada.",
"author": "Goethe"
},
{
"quote": "Vale más hacer y arrepentirse, que no hacer y arrepentirse.",
"author": "Maquiavelo"
},
{
"quote": "Si quieres cambiar al mundo, cámbiate a ti mismo.",
"author": "Mahatma Gandhi"
},
{
"quote": "Un amigo fiel es un alma en dos cuerpos.",
"author": "Aristóteles"
},
{
"quote": "La vida no es sino una continua sucesión de oportunidades para sobrevivir.",
"author": "Gabriel García Márquez"
},
{
"quote": "Se necesita poco para hacer las cosas bien, pero menos aún para hacerlas mal.",
"author": "Paul Bocuse"
},
{
"quote": "Con veinte años todos tienen el rostro que Dios les ha dado; con cuarenta el rostro que les ha dado la vida y con sesenta el que se merecen.",
"author": "Albert Schweitzer"
},
{
"quote": "El amor no tiene cura, pero es la única medicina para todos los males.",
"author": "Konrad Adenauer"
},
{
"quote": "No hay camino para la verdad, la verdad es el camino.",
"author": "Mahatma Gandhi"
},
{
"quote": "El éxito tiene muchos padres, pero el fracaso es huérfano.",
"author": "John Fitzgerald Kennedy"
},
{
"quote": "Quien no haya sufrido lo que yo, que no me de consejos.",
"author": "Sófocles"
},
{
"quote": "La vida es un diez por ciento como la hacemos y un noventa por ciento como la tomamos.",
"author": "Irving Berlín"
},
{
"quote": "El hombre que más ha vivido no es aquél que más años ha cumplido, sino aquel que más ha experimentado la vida.",
"author": "Jean Jacques Rousseau"
},
{
"quote": "En los momentos de crisis, solo la imaginación es más importante que el conocimiento.",
"author": "Albert Einstein"
},
{
"quote": "Nuestros hijos no tendrán tiempo para discutir sobre el cambio climático. Solo podrán convivir con sus efectos.",
"author": "Barack Obama"
},
{
"quote": "Si quieres cambiar el mundo, toma tu pluma y escribe.",
"author": "Martín Lutero"
},
{
"quote": "Hay verdades que no son para todos los hombres, ni para todos los tiempos.",
"author": "Voltaire"
},
{
"quote": "Sé el cambio que quieres ver en el mundo.",
"author": "Mahatma Gandhi"
},
{
"quote": "La raíz del sufrimiento es el apego.",
"author": "Buda"
},
{
"quote": "La religión es el opio del pueblo.",
"author": "Karl Marx"
},
{
"quote": "Hay dos clases de hombres: quienes hacen la historia y quienes la padecen.",
"author": "Camilo José Cela"
},
{
"quote": "La verdad es siempre revolucionaria.",
"author": "Vladimir Lenin"
},
{
"quote": "La peor lucha es la que no se hace.",
"author": "Karl Marx"
},
{
"quote": "Vence la ira con serenidad. Vence la maldad con bondad. Vence el egoísmo con generosidad. Vence la deshonestidad con verdad.",
"author": "Buda"
},
{
"quote": "Hay dos maneras de vivir su vida: una como si nada es un milagro, la otra es como si todo es un milagro.",
"author": "Albert Einstein"
},
{
"quote": "La historia se repite, ese es uno de los errores de la historia.",
"author": "Charles Darwin"
},
{
"quote": "La felicidad se alcanza cuando lo que uno piensa, lo que uno dice y lo que uno hace están en armonía.",
"author": "Mahatma Gandhi"
},
{
"quote": "Los pecados escriben la historia, el bien es silencioso.",
"author": "Goethe"
}
]

View File

@@ -1,5 +0,0 @@
[
{"quote": "La pluma es la lengua del alma.", "author": "Miguel de Cervantes"},
{"quote": "Todos los niños nacen artistas. El problema es cómo seguir siendo artistas al crecer.", "author": "Pablo Picasso"},
{"quote": "No puedo cambiar la dirección del viento, pero sí ajustar mis velas para llegar a mi destino.", "author":"Jimmy Dean" }
]

705
voices.txt Normal file
View File

@@ -0,0 +1,705 @@
<Voice id=gmw/af
name=Afrikaans
languages=['af']
gender=Male
age=None>
<Voice id=sem/am
name=Amharic
languages=['am']
gender=Male
age=None>
<Voice id=roa/an
name=Aragonese
languages=['an']
gender=Male
age=None>
<Voice id=sem/ar
name=Arabic
languages=['ar']
gender=Male
age=None>
<Voice id=inc/as
name=Assamese
languages=['as']
gender=Male
age=None>
<Voice id=trk/az
name=Azerbaijani
languages=['az']
gender=Male
age=None>
<Voice id=trk/ba
name=Bashkir
languages=['ba']
gender=Male
age=None>
<Voice id=zle/be
name=Belarusian
languages=['be']
gender=Male
age=None>
<Voice id=zls/bg
name=Bulgarian
languages=['bg']
gender=Male
age=None>
<Voice id=inc/bn
name=Bengali
languages=['bn']
gender=Male
age=None>
<Voice id=inc/bpy
name=Bishnupriya Manipuri
languages=['bpy']
gender=Male
age=None>
<Voice id=zls/bs
name=Bosnian
languages=['bs']
gender=Male
age=None>
<Voice id=roa/ca
name=Catalan
languages=['ca']
gender=Male
age=None>
<Voice id=roa/ca-ba
name=Catalan (Balearic)
languages=['ca-ba']
gender=Male
age=None>
<Voice id=roa/ca-nw
name=Catalan (North-western)
languages=['ca-nw']
gender=Male
age=None>
<Voice id=roa/ca-va
name=Catalan (Valencian)
languages=['ca-va']
gender=Male
age=None>
<Voice id=iro/chr
name=Cherokee
languages=['chr-US-Qaaa-x-west']
gender=Male
age=None>
<Voice id=sit/cmn
name=Chinese (Mandarin, latin as English)
languages=['cmn']
gender=Male
age=None>
<Voice id=sit/cmn-latn-pinyin
name=Chinese (Mandarin, latin as Pinyin)
languages=['cmn-latn-pinyin']
gender=Male
age=None>
<Voice id=zlw/cs
name=Czech
languages=['cs']
gender=Male
age=None>
<Voice id=trk/cv
name=Chuvash
languages=['cv']
gender=Male
age=None>
<Voice id=cel/cy
name=Welsh
languages=['cy']
gender=Male
age=None>
<Voice id=gmq/da
name=Danish
languages=['da']
gender=Male
age=None>
<Voice id=gmw/de
name=German
languages=['de']
gender=Male
age=None>
<Voice id=grk/el
name=Greek
languages=['el']
gender=Male
age=None>
<Voice id=gmw/en-029
name=English (Caribbean)
languages=['en-029']
gender=Male
age=None>
<Voice id=gmw/en
name=English (Great Britain)
languages=['en-gb']
gender=Male
age=None>
<Voice id=gmw/en-gb-scotland
name=English (Scotland)
languages=['en-gb-scotland']
gender=Male
age=None>
<Voice id=gmw/en-gb-x-gbclan
name=English (Lancaster)
languages=['en-gb-x-gbclan']
gender=Male
age=None>
<Voice id=gmw/en-gb-x-gbcwmd
name=English (West Midlands)
languages=['en-gb-x-gbcwmd']
gender=Male
age=None>
<Voice id=gmw/en-gb-x-rp
name=English (Received Pronunciation)
languages=['en-gb-x-rp']
gender=Male
age=None>
<Voice id=gmw/en-shaw
name=English (Shavian alphabet)
languages=['en-shaw']
gender=Male
age=None>
<Voice id=gmw/en-us
name=English (America)
languages=['en-us']
gender=Male
age=None>
<Voice id=gmw/en-us-nyc
name=English (America, New York City)
languages=['en-us-nyc']
gender=Male
age=None>
<Voice id=art/eo
name=Esperanto
languages=['eo']
gender=Male
age=None>
<Voice id=roa/es
name=Spanish (Spain)
languages=['es']
gender=Male
age=None>
<Voice id=roa/es-419
name=Spanish (Latin America)
languages=['es-419']
gender=Male
age=None>
<Voice id=urj/et
name=Estonian
languages=['et']
gender=Male
age=None>
<Voice id=eu
name=Basque
languages=['eu']
gender=Male
age=None>
<Voice id=ira/fa
name=Persian
languages=['fa']
gender=Male
age=None>
<Voice id=ira/fa-latn
name=Persian (Pinglish)
languages=['fa-latn']
gender=Male
age=None>
<Voice id=urj/fi
name=Finnish
languages=['fi']
gender=Male
age=None>
<Voice id=gmq/fo
name=Faroese
languages=['fo']
gender=Male
age=None>
<Voice id=roa/fr-be
name=French (Belgium)
languages=['fr-be']
gender=Male
age=None>
<Voice id=roa/fr-ch
name=French (Switzerland)
languages=['fr-ch']
gender=Male
age=None>
<Voice id=roa/fr
name=French (France)
languages=['fr-fr']
gender=Male
age=None>
<Voice id=cel/ga
name=Gaelic (Irish)
languages=['ga']
gender=Male
age=None>
<Voice id=cel/gd
name=Gaelic (Scottish)
languages=['gd']
gender=Male
age=None>
<Voice id=sai/gn
name=Guarani
languages=['gn']
gender=Male
age=None>
<Voice id=grk/grc
name=Greek (Ancient)
languages=['grc']
gender=Male
age=None>
<Voice id=inc/gu
name=Gujarati
languages=['gu']
gender=Male
age=None>
<Voice id=sit/hak
name=Hakka Chinese
languages=['hak']
gender=Male
age=None>
<Voice id=map/haw
name=Hawaiian
languages=['haw']
gender=Male
age=None>
<Voice id=sem/he
name=Hebrew
languages=['he']
gender=Male
age=None>
<Voice id=inc/hi
name=Hindi
languages=['hi']
gender=Male
age=None>
<Voice id=zls/hr
name=Croatian
languages=['hr']
gender=Male
age=None>
<Voice id=roa/ht
name=Haitian Creole
languages=['ht']
gender=Male
age=None>
<Voice id=urj/hu
name=Hungarian
languages=['hu']
gender=Male
age=None>
<Voice id=ine/hy
name=Armenian (East Armenia)
languages=['hy']
gender=Male
age=None>
<Voice id=ine/hyw
name=Armenian (West Armenia)
languages=['hyw']
gender=Male
age=None>
<Voice id=art/ia
name=Interlingua
languages=['ia']
gender=Male
age=None>
<Voice id=poz/id
name=Indonesian
languages=['id']
gender=Male
age=None>
<Voice id=art/io
name=Ido
languages=['io']
gender=Male
age=None>
<Voice id=gmq/is
name=Icelandic
languages=['is']
gender=Male
age=None>
<Voice id=roa/it
name=Italian
languages=['it']
gender=Male
age=None>
<Voice id=jpx/ja
name=Japanese
languages=['ja']
gender=Male
age=None>
<Voice id=art/jbo
name=Lojban
languages=['jbo']
gender=Male
age=None>
<Voice id=ccs/ka
name=Georgian
languages=['ka']
gender=Male
age=None>
<Voice id=trk/kaa
name=Karakalpak
languages=['kaa']
gender=Male
age=None>
<Voice id=trk/kk
name=Kazakh
languages=['kk']
gender=Male
age=None>
<Voice id=esx/kl
name=Greenlandic
languages=['kl']
gender=Male
age=None>
<Voice id=dra/kn
name=Kannada
languages=['kn']
gender=Male
age=None>
<Voice id=ko
name=Korean
languages=['ko']
gender=Male
age=None>
<Voice id=inc/kok
name=Konkani
languages=['kok']
gender=Male
age=None>
<Voice id=ira/ku
name=Kurdish
languages=['ku']
gender=Male
age=None>
<Voice id=trk/ky
name=Kyrgyz
languages=['ky']
gender=Male
age=None>
<Voice id=itc/la
name=Latin
languages=['la']
gender=Male
age=None>
<Voice id=gmw/lb
name=Luxembourgish
languages=['lb']
gender=Male
age=None>
<Voice id=art/lfn
name=Lingua Franca Nova
languages=['lfn']
gender=Male
age=None>
<Voice id=bat/lt
name=Lithuanian
languages=['lt']
gender=Male
age=None>
<Voice id=bat/ltg
name=Latgalian
languages=['ltg']
gender=Male
age=None>
<Voice id=bat/lv
name=Latvian
languages=['lv']
gender=Male
age=None>
<Voice id=poz/mi
name=Māori
languages=['mi']
gender=Male
age=None>
<Voice id=zls/mk
name=Macedonian
languages=['mk']
gender=Male
age=None>
<Voice id=dra/ml
name=Malayalam
languages=['ml']
gender=Male
age=None>
<Voice id=inc/mr
name=Marathi
languages=['mr']
gender=Male
age=None>
<Voice id=poz/ms
name=Malay
languages=['ms']
gender=Male
age=None>
<Voice id=sem/mt
name=Maltese
languages=['mt']
gender=Male
age=None>
<Voice id=miz/mto
name=Totontepec Mixe
languages=['mto']
gender=Male
age=None>
<Voice id=sit/my
name=Myanmar (Burmese)
languages=['my']
gender=Male
age=None>
<Voice id=gmq/nb
name=Norwegian Bokmål
languages=['nb']
gender=Male
age=None>
<Voice id=azc/nci
name=Nahuatl (Classical)
languages=['nci']
gender=Male
age=None>
<Voice id=inc/ne
name=Nepali
languages=['ne']
gender=Male
age=None>
<Voice id=gmw/nl
name=Dutch
languages=['nl']
gender=Male
age=None>
<Voice id=trk/nog
name=Nogai
languages=['nog']
gender=Male
age=None>
<Voice id=cus/om
name=Oromo
languages=['om']
gender=Male
age=None>
<Voice id=inc/or
name=Oriya
languages=['or']
gender=Male
age=None>
<Voice id=inc/pa
name=Punjabi
languages=['pa']
gender=Male
age=None>
<Voice id=roa/pap
name=Papiamento
languages=['pap']
gender=Male
age=None>
<Voice id=art/piqd
name=Klingon
languages=['piqd']
gender=Male
age=None>
<Voice id=zlw/pl
name=Polish
languages=['pl']
gender=Male
age=None>
<Voice id=roa/pt
name=Portuguese (Portugal)
languages=['pt']
gender=Male
age=None>
<Voice id=roa/pt-br
name=Portuguese (Brazil)
languages=['pt-br']
gender=Male
age=None>
<Voice id=art/py
name=Pyash
languages=['py']
gender=Male
age=None>
<Voice id=art/qdb
name=Lang Belta
languages=['qdb']
gender=Male
age=None>
<Voice id=qu
name=Quechua
languages=['qu']
gender=Male
age=None>
<Voice id=myn/quc
name=K'iche'
languages=['quc']
gender=Male
age=None>
<Voice id=art/qya
name=Quenya
languages=['qya']
gender=Male
age=None>
<Voice id=roa/ro
name=Romanian
languages=['ro']
gender=Male
age=None>
<Voice id=zle/ru
name=Russian
languages=['ru']
gender=Male
age=None>
<Voice id=zle/ru-cl
name=Russian (Classic)
languages=['ru-cl']
gender=Male
age=None>
<Voice id=zle/ru-lv
name=Russian (Latvia)
languages=['ru-lv']
gender=Male
age=None>
<Voice id=inc/sd
name=Sindhi
languages=['sd']
gender=Male
age=None>
<Voice id=tai/shn
name=Shan (Tai Yai)
languages=['shn']
gender=Male
age=None>
<Voice id=inc/si
name=Sinhala
languages=['si']
gender=Male
age=None>
<Voice id=art/sjn
name=Sindarin
languages=['sjn']
gender=Male
age=None>
<Voice id=zlw/sk
name=Slovak
languages=['sk']
gender=Male
age=None>
<Voice id=zls/sl
name=Slovenian
languages=['sl']
gender=Male
age=None>
<Voice id=urj/smj
name=Lule Saami
languages=['smj']
gender=Male
age=None>
<Voice id=ine/sq
name=Albanian
languages=['sq']
gender=Male
age=None>
<Voice id=zls/sr
name=Serbian
languages=['sr']
gender=Male
age=None>
<Voice id=gmq/sv
name=Swedish
languages=['sv']
gender=Male
age=None>
<Voice id=bnt/sw
name=Swahili
languages=['sw']
gender=Male
age=None>
<Voice id=dra/ta
name=Tamil
languages=['ta']
gender=Male
age=None>
<Voice id=dra/te
name=Telugu
languages=['te']
gender=Male
age=None>
<Voice id=tai/th
name=Thai
languages=['th']
gender=Male
age=None>
<Voice id=sem/ti
name=Tigrinya
languages=['ti']
gender=Male
age=None>
<Voice id=trk/tk
name=Turkmen
languages=['tk']
gender=Male
age=None>
<Voice id=bnt/tn
name=Setswana
languages=['tn']
gender=Male
age=None>
<Voice id=trk/tr
name=Turkish
languages=['tr']
gender=Male
age=None>
<Voice id=trk/tt
name=Tatar
languages=['tt']
gender=Male
age=None>
<Voice id=trk/ug
name=Uyghur
languages=['ug']
gender=Male
age=None>
<Voice id=zle/uk
name=Ukrainian
languages=['uk']
gender=Male
age=None>
<Voice id=inc/ur
name=Urdu
languages=['ur']
gender=Male
age=None>
<Voice id=trk/uz
name=Uzbek
languages=['uz']
gender=Male
age=None>
<Voice id=aav/vi
name=Vietnamese (Northern)
languages=['vi']
gender=Male
age=None>
<Voice id=aav/vi-vn-x-central
name=Vietnamese (Central)
languages=['vi-vn-x-central']
gender=Male
age=None>
<Voice id=aav/vi-vn-x-south
name=Vietnamese (Southern)
languages=['vi-vn-x-south']
gender=Male
age=None>
<Voice id=art/xex
name=xextan-test
languages=['xex']
gender=Male
age=None>
<Voice id=sit/yue
name=Chinese (Cantonese)
languages=['yue']
gender=Male
age=None>
<Voice id=sit/yue-latn-jyutping
name=Chinese (Cantonese, latin as Jyutping)
languages=['yue']
gender=Male
age=None>