mirror of
https://github.com/sr229/metastruct-experiments.git
synced 2024-09-19 22:20:35 +00:00
Include Google TTS v4
Signed-off-by: Ayane Satomi <ayane@vignetteapp.org>
This commit is contained in:
parent
7b6ed60bbc
commit
e7503545df
12 changed files with 184 additions and 0 deletions
7
starfallex/google_tts/libraries/hasvalue.lua
Normal file
7
starfallex/google_tts/libraries/hasvalue.lua
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
function HasValue(tab, val)
|
||||||
|
for _, v in pairs(tab) do
|
||||||
|
if v == val then return true end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
23
starfallex/google_tts/libraries/urlencode.lua
Normal file
23
starfallex/google_tts/libraries/urlencode.lua
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Char2Hex = function(c) return string.format("%%%02X", string.byte(c)) end
|
||||||
|
|
||||||
|
function UrlEncode(url)
|
||||||
|
if url == nil then return end
|
||||||
|
url = url:gsub("\n", "\r\n")
|
||||||
|
url = url:gsub("([^%w ])", Char2Hex)
|
||||||
|
url = url:gsub(" ", "+")
|
||||||
|
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
Hex2Char = function(x) return string.char(tonumber(x, 16)) end
|
||||||
|
|
||||||
|
UrlDecode = function(url)
|
||||||
|
if url == nil then return end
|
||||||
|
url = url:gsub("+", " ")
|
||||||
|
url = url:gsub("%%(%x%x)", Hex2Char)
|
||||||
|
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
-- ref: https://gist.github.com/ignisdesign/4323051
|
||||||
|
-- ref: http://stackoverflow.com/questions/20282054/how-to-urldecode-a-request-uri-string-in-lua
|
||||||
|
-- to encode table as parameters, see https://github.com/stuartpb/tvtropes-lua/blob/master/urlencode.lua
|
154
starfallex/google_tts/tts.lua
Normal file
154
starfallex/google_tts/tts.lua
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
--@name Starfall-TTS (Shared)
|
||||||
|
--@author Minori, Henke, Empy, et al.
|
||||||
|
--@include https://raw.githubusercontent.com/sr229/metastruct-experiments/master/starfallex/google_tts/libraries/hasvalue.lua as hasvalue.txt
|
||||||
|
--@include https://raw.githubusercontent.com/sr229/metastruct-experiments/master/starfallex/google_tts/libraries/urlencode.lua as urlencode.txt
|
||||||
|
--@shared
|
||||||
|
|
||||||
|
-- constants
|
||||||
|
local DEFAULT_LANGUAGE = "en-gb"
|
||||||
|
local DEBUG = true
|
||||||
|
local REMOTE_INDEX = "https://raw.githubusercontent.com/sr229/metastruct-experiments/master/starfall_metadata/allowed_google_voices.json"
|
||||||
|
local BASS_REFERENCES = {}
|
||||||
|
|
||||||
|
-- top level requires
|
||||||
|
require("urlencode.txt")
|
||||||
|
require("hasvalue.txt")
|
||||||
|
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
-- Userdata will collect the Player ID and the language.
|
||||||
|
-- Layout may look something like this:
|
||||||
|
-- userdata = {
|
||||||
|
-- [1] = "en-gb"
|
||||||
|
-- }
|
||||||
|
local userdata = {}
|
||||||
|
-- This is the server's copy of the remote index.
|
||||||
|
local srvidx = {}
|
||||||
|
-- if you just want to hide it from the idiots around you
|
||||||
|
-- chip():setOwner(true)
|
||||||
|
local function getRemoteLanguageIndex()
|
||||||
|
print("SERVER: Building language index. Please be patient...")
|
||||||
|
|
||||||
|
http.get(REMOTE_INDEX, function(body, len)
|
||||||
|
if len > 0 then
|
||||||
|
local rawData = json.decode(body)
|
||||||
|
|
||||||
|
if rawData then
|
||||||
|
for i, v in pairs(rawData.voices) do
|
||||||
|
table.insert(srvidx, i, v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error("Could not decode JSON")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #srvidx > 0 then
|
||||||
|
print("SERVER: Serverside hook initialized.")
|
||||||
|
print(string.format("Available Languages: %s", table.concat(srvidx, ", ")))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
getRemoteLanguageIndex()
|
||||||
|
|
||||||
|
hook.add("PlayerSay", "msgHandler", function(ply, msg)
|
||||||
|
if ply and string.sub(msg, 1, 1) == ";" and userdata[ply:getUserID()] then
|
||||||
|
|
||||||
|
net.start("broadcast_tts")
|
||||||
|
net.writeInt(ply:getUserID(), 32)
|
||||||
|
net.writeString(userdata[ply:getUserID()])
|
||||||
|
net.writeString(tostring(string.sub(msg, 2)))
|
||||||
|
net.send()
|
||||||
|
elseif ply and string.sub(msg, 1, 1) == ";" then
|
||||||
|
-- initialize the user
|
||||||
|
table.insert(userdata, ply:getUserID(), DEFAULT_LANGUAGE)
|
||||||
|
|
||||||
|
net.start("broadcast_tts")
|
||||||
|
net.writeInt(ply:getUserID(), 32)
|
||||||
|
net.writeString(userdata[ply:getUserID()])
|
||||||
|
net.writeString(tostring(string.sub(msg, 2)))
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
|
||||||
|
if ply and string.sub(msg, 1, 1) == ":" and userdata[ply:getUserID()] then
|
||||||
|
local preferredLang = tostring(string.sub(msg, 2))
|
||||||
|
|
||||||
|
if HasValue(srvidx, preferredLang) then
|
||||||
|
print(string.format("Swtiched to %s", preferredLang))
|
||||||
|
userdata[ply:getUserID()] = preferredLang
|
||||||
|
else
|
||||||
|
print("WARN: Invalid Language! No changes were made.")
|
||||||
|
end
|
||||||
|
elseif ply and string.sub(msg, 1, 1) == ":" then
|
||||||
|
local preferredLang = tostring(string.sub(msg, 2))
|
||||||
|
print("No preferences found for you. Initializing you with your preferred language.")
|
||||||
|
if HasValue(srvidx, preferredLang) then
|
||||||
|
table.insert(userdata, ply:getUserID(), preferredLang)
|
||||||
|
else
|
||||||
|
print("WARN: Your preferred language is not valid! Initializing you with the default one instead.")
|
||||||
|
table.insert(userdata, ply:getUserID(), DEFAULT_LANGUAGE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
-- Check if client has permission
|
||||||
|
if not hasPermission("bass.loadURL", "https://translate.google.com/translate_tts") then
|
||||||
|
print("WARNING: Your starfall settings prevents this chip from working, please redo your settings.")
|
||||||
|
else
|
||||||
|
print("CLIENT: Clientside hook initialized.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function requestTTS(txt, lng, callback)
|
||||||
|
local url = string.format("https://translate.google.com/translate_tts?ie=UTF-8&q=%s&tl=%s&client=tw-ob", txt, lng)
|
||||||
|
bass.loadURL(url, "3d noblock", callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function doTTS(ply, sound)
|
||||||
|
|
||||||
|
-- check for validity
|
||||||
|
if not sound then
|
||||||
|
error("Sound is invalid or nil!")
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(BASS_REFERENCES, {
|
||||||
|
ref = sound,
|
||||||
|
timestamp = os.time()
|
||||||
|
})
|
||||||
|
|
||||||
|
hook.add("think", "soundFollow", function()
|
||||||
|
if sound:isValid() then
|
||||||
|
sound:setPos(ply:getPos())
|
||||||
|
else
|
||||||
|
hook.remove("think", "soundFollow")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
sound:setVolume(1.3)
|
||||||
|
sound:play()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function gc()
|
||||||
|
table.sort(BASS_REFERENCES, function(a, b) return a.timestamp < b.timestamp end)
|
||||||
|
|
||||||
|
if #BASS_REFERENCES ~= 0 and #BASS_REFERENCES > 2 then
|
||||||
|
BASS_REFERENCES[1].ref:destroy()
|
||||||
|
table.remove(BASS_REFERENCES, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
net.receive("broadcast_tts", function()
|
||||||
|
local ply = player(net.readInt(32))
|
||||||
|
local lang = net.readString()
|
||||||
|
local msg = net.readString()
|
||||||
|
|
||||||
|
if DEBUG then print(string.format("DEBUG: Ply: %s, Lang: %s, Msg: %s", ply:getName(), lang, msg)) end
|
||||||
|
requestTTS(UrlEncode(msg), lang, function(s)
|
||||||
|
if s then
|
||||||
|
doTTS(ply, s)
|
||||||
|
gc()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
Loading…
Reference in a new issue