Gmod TTS: 3D voice chatbox Text To Speech with accents!

In light of lots of programmers jumping on the text to speech train abusing Gran PC’s peniscorp API’s bandwidth, disk space, and CPU, and also the generally low quality of such scripts, I made my own for all of you.

This uses the google API as much as possible, giving each player a unique voice based on the player’s current name. When too many people are talking in a short span, it will use Gran PC’s peniscorp robot voice as a backup server.

Voices are 3D, and follow the player.

Accents used:

Robot
English (USA)
English (British)
French
Russian

Pitch, speed, and accent are all affected by the speaking player’s name.

This also accounts for TTT and DarkRP. In TTT, being a spectator or being dead means you don’t get TTS. In DarkRP, PMs, OOC, etc, do not have TTS. In DarkRP, TTS is not heard from over 500 units away. The DarkRP default non-OOC chat range is 250.

Put this code in autorun/client/gmodtts.lua

[lua]
local accents = {
http://translate.google.co.uk/translate_tts?tl=en&q=”,
http://translate.google.com/translate_tts?tl=en&q=”,
http://translate.google.com/translate_tts?tl=fr&q=”,
http://translate.google.com/translate_tts?tl=ru&q=”,
"http://tts.peniscorp.com/speak.lua?"
}

local wait = false
local channels = {}

local function playvoice(ply,text,accent,speed)
if wait then
accent = "http://tts.peniscorp.com/speak.lua?"
end
sound.PlayURL(accent…text,“3d noplay”,function(channel,errorid,errorname)
if channel == nil || errorid != nil || errorname != nil then --peniscorp backup; google is upset
if wait == false then
wait = true
timer.Simple(125,function() wait = false end)
playvoice(ply,text,accent,speed)
end
return
end
channel:SetPos(ply:GetPos(),Vector(0,0,0))
channel:Set3DFadeDistance(300,9999999999)
channel:SetPlaybackRate(math.Clamp(.5+speed,.5,2))
channel:Play()
table.insert(channels,{channel,ply})
end)
end

hook.Add(“Think”,“TTSThink”,function()
for k, v in pairs(channels) do
if !v[1]:IsValid() then table.remove(channels,k) return end
if v[2] == nil ||
v[1]:GetState() != GMOD_CHANNEL_PLAYING ||
v[1]:GetTime() >= v[1]:GetLength() then
v[1]:Stop()
table.remove(channels,k)
return
end
v[1]:SetPos(v[2]:GetPos(),Vector(0,0,0))
end
end)

hook.Add(“OnPlayerChat”,“TTSPlayerChat”,function(ply,text,team,dead)
–firstly, checking for popular gamemode limitations
local dotts = true
if engine.ActiveGamemode() == “terrortown” then
if dead then dotts = false end
if ply.IsSpec != nil && ply:IsSpec() then dotts = false end
end
if engine.ActiveGamemode() == “darkrp” then
if text[1] == “/” then dotts = false end
if ply:GetPos():Distance(LocalPlayer():GetPos()) > 500 then dotts = false end --250 = default chat range
end
if dotts then
local speed,accent,nick = 1, accents[1], ply:Nick()
local nlen = #nick
local vowels, vow, notvow, vrat = {“a”,“e”,“i”,“o”,“u”,“y”}, 0, 0, 1
for i = 1, nlen do
if table.HasValue(vowels,nick*) then vow = vow+1 else notvow = notvow+1 end
end
if vow == 0 then notvow = nlen end
vrat = vow/notvow
accent = accents[math.Clamp(vow,1,#accents)]
speed = vrat
playvoice(ply,text,accent,speed)
end
end)
[/lua]

Better than mine by a long shot, nice :slight_smile:

Text To Speech has a special place in my heart - I don’t quite know why I love it so much, I just do

Thank you for this, and great work!

1 crappy drawback is how low it sounds in-game versus in a web browser

you can barely hear it sometimes

but this is really cool, good job.

So can I remove the Russian and French voices if I don’t want them without an issue?

yes, but that’ll only hurt the unique voices aspect

it isn’t a translation, just a different way of saying the words

sweet american tts.

Nice job tho.

Its better to set up an own TTS servers, because i had problems with 3 players continuesly using google translator tts. (spam protection)

Yes, as did I. Sometimes it would not play, sometimes it would.

Non-English voices pronounce numbers in their native language, not English.

If a sound is not received, the script falls back on Gran PC’s server instead of google. I don’t know what problem you’re having, other than Gran PC’s latency issues.

Fun non-the-less.

I heard in WAYWO that Google’s unofficial tts “api” requires a captcha to be filled out after a few requests (hence not getting the sound) in addition to having a 100 character limit

[editline]e[/editline]

Yeah, I read that. I knew there was a fallback; I was just pointing out the reasons that might be the case.

[editline]27th January 2015[/editline]

come on

[editline]27th January 2015[/editline]

yeah but that can only happen once every few minutes at most, and when it does, it repeats the message under peniscorp

Works like a sharm!
I see there is also a funny example on API page (http://tts.peniscorp.com/): :v: :dance: [[dah<500,20>][dah<500,20>][dah<400,16>][dah<130,23>][dah<500,20>][dah<400,16>][dah<130,23>][dah<600,20>][_<300>][dah<500,27>][dah<500,27>][dah<500,27>][dah<400,28>][dah<130,23>][dah<500,19>][dah<400,16>][dah<130,23>][dah<500,20>]"]dah-dah-dah-dah…](http://tts.peniscorp.com/speak.lua?[dah<500,20>)

This will go great with my gag space gamemode

Does typing soisoisoisoisoi behave the same way?

That was Microsoft Sam, I’m pretty sure.

Peniscorp uses DECTalk, the same from moonbase alpha. The google accents are something different, and sound far less robotic.

I want to use your script in my gamemode. Buttt… oh, there is no my gamemode, whilst I didn’t make it yet. Wait for alpha version :wink:
OK, main idea of my GM is to construct quest (in single player), share it, place the players (in MP, or just one player in SP) and make them communicate and do other stuff to finish task. Now I only have HTML-interface of splash screen, so I can not show it at the moment. IT’S NOT whole idea, I just need some more time to learn other stuff, and there will be brand new colossal awesome gamemode. :smiley: Best regards!