This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

text to speech?
#5
As requested my code using voicerss.
First the user lib I use for controlling Sonos based on what existed - added some new functions (track info)

Code:
function upnpavcmd(host, port, cmd, param)    local client, soap, reqs, service, res, err    require('socket')    client = socket.tcp()    client:settimeout(3)    -- try connecting to upnp endpoint    res, err = client:connect(host, port)    if not res then    return nil, err    end    -- guess service name based on command  if cmd =='SetGroupVolume' or cmd == 'SetGroupMute' or cmd == 'SnapshotGroupVolume' then    service = 'GroupRenderingControl'  elseif cmd == 'SetVolume' or cmd == 'GetVolume' or cmd == 'SetMute' or cmd == 'GetMute' then    service = 'RenderingControl'    else    service = 'AVTransport'    end      -- soap envelope    soap = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' ..    '<s:Body>' ..    '<u:' .. cmd .. ' xmlns:u="urn:schemas-upnp-org:service:' .. service .. ':1">' ..    '<InstanceID>0</InstanceID>' ..    (param or '') ..    '</u:' .. cmd .. '>' ..    '</s:Body>' ..    '</s:Envelope>'        -- http request    reqs = 'POST /MediaRenderer/' .. service .. '/Control HTTP/1.1\r\n' ..    'CONNECTION: close\r\n' ..    'HOST: ' .. host .. ':' ..port.. '\r\n' ..    'CONTENT-LENGTH: ' .. soap:len() .. '\r\n' ..    'CONTENT-TYPE: text/xml; charset="utf-8"\r\n' ..    'SOAPACTION: "urn:schemas-upnp-org:service:' .. service .. ':1#' .. cmd .. '"\r\n' ..    '\r\n' .. soap        -- send http request    res, err = client:send(reqs)    if not res then    return nil, err    end        -- get reply and close connection    res, err = client:receive('*a')    client:close()        return res, err    end function Sonos_Find(sonos_name)  require("socket")  require('socket.http')  local udp = socket.udp()  if udp == nil then    return  else    local result, message    local datagram = "M-SEARCH * HTTP/1.1\r\n"                      .. "HOST: 239.255.255.250:1900\r\n"                      .. "ST: urn:schemas-upnp-org:device:ZonePlayer:1\r\n"                      .. "\r\n"    result, message = udp:sendto(datagram, "239.255.255.250", 1900)    for i = 1, 254 do      datagram, message = udp:receivefrom()        ip = datagram:match("http://(.-):1400")        if datagram == nil or ip == nil then          break        else        data = socket.http.request("http://" .. ip .. ":1400/status/zp")        zonename = data:match([[<ZoneName>(.-)</ZoneName>]])        ipaddress = data:match([[<IPAddress>(.-)</IPAddress>]])        macaddress = data:match([[<MACAddress>(.-)</MACAddress>]])        rincon = data:match([[<LocalUID>(.-)</LocalUID>]])        if zonename == sonos_name then          return {sonos_name = zonename, sonos_ipaddress = ipaddress, sonos_macaddress = macaddress, sonos_rincon = rincon}        end      end    end  end     udp:close() end function Sonos_Getpositioninfo(sonos_ipaddress) -- Get Sonos Player Position Info  position_info = upnpavcmd(sonos_ipaddress,1400,'GetPositionInfo')  -- Get Track  for i in string.gmatch(position_info, '<Track.-</Track>') do      if i ~= nil then      track_nr =  i:match([[<Track>(.-)</Track>]])      end     end  -- Get Track  for i in string.gmatch(position_info, '<TrackDuration.-</TrackDuration>') do      if i ~= nil then      track_duration =  i:match([[<TrackDuration>(.-)</TrackDuration>]])      end     end  -- Get Track Playing Time  for i in string.gmatch(position_info, '<RelTime.-</RelTime>') do      if i ~= nil then      track_playing_time =  i:match([[<RelTime>(.-)</RelTime>]])      end     end  -- Get Track Title  for i in string.gmatch(position_info, 'dc:title.-/dc:title') do      if i ~= nil then      track_title =  i:match([[dc:title&gt;(.-)&lt;/dc:title]])      end     end  -- Get Track Artist  for i in string.gmatch(position_info, 'dc:creator.-/dc:creator') do      if i ~= nil then      creator =  i:match([[dc:creator&gt;(.-)&lt;/dc:creator]])      end     end  if creator == nil then    for i in string.gmatch(position_info, '<TrackMetaData.-</TrackMetaData>') do      if i ~= nil then        creator =  i:match([[streamContent&gt;(.-)&lt;/r:streamContent]])      end    end  end  -- Get Track Album  for i in string.gmatch(position_info, 'upnp:album.-/upnp:album') do      if i ~= nil then      album =  i:match([[upnp:album&gt;(.-)&lt;/upnp:album]])      end     end --  -- Get Track Image URL --  for i in string.gmatch(position_info, 'upnp:albumArtURI.-/upnp:albumArtURI') do --      if i ~= nil then --      albumart =  i:match([[upnp:albumArtURI&gt;(.-)&lt;/upnp:albumArtURI]]) --      end --    end --  if albumart == nil then --    for i in string.gmatch(position_info, '<TrackURI.-</TrackURI>') do --      if i ~= nil then --        albumart =  i:match([[<TrackURI>(.-)</TrackURI>]]) --      end --    end --  end  return {TrackNr = track_nr, TrackDuration = track_duration, TrackRelTime = track_playing_time, TrackTitle = track_title, TrackCreator = creator, TrackAlbum = album}         end function Sonos_Gettransportinfo(sonos_ipaddress)  -- Get Sonos Player Transport Info  reply = upnpavcmd(sonos_ipaddress,1400,'GetTransportInfo')     for i in string.gmatch(reply, '<CurrentTransportState.-</CurrentTransportState>') do      if i ~= nil then      play_pause =  i:match([[<CurrentTransportState>(.-)</CurrentTransportState>]])      end     end  -- 'TRANSITIONING' , 'PLAYING' , 'PAUSED_PLAYBACK' or 'STOPPED'  return {Transportmode = play_pause}       end   function Sonos_GetVolume(sonos_ipaddress)  -- Get Sonos Player Volume Info  reply = upnpavcmd(sonos_ipaddress,1400,'GetVolume','<Channel>Master</Channel>')  for i in string.gmatch(reply, '<CurrentVolume.-</CurrentVolume>') do      if i ~= nil then      volume =  i:match([[<CurrentVolume>(.-)</CurrentVolume>]])      end     end  return {Volume = volume}       end function Sonos_Getmediainfo(sonos_ipaddress)  -- Get Sonos Player Media Info  reply = upnpavcmd(sonos_ipaddress,1400,'GetMediaInfo')     for i in string.gmatch(reply, '<CurrentURI.-</CurrentURI>') do      if i ~= nil then      currenturi =  i:match([[<CurrentURI>(.-)</CurrentURI>]])      end     end  -- 'TRANSITIONING' , 'PLAYING' , 'PAUSED_PLAYBACK' or 'STOPPED'    return {CurrentURI = currenturi}       end


Below the actual script:
It gets te mp3info and saves it on my synologyNas so the sonos can play it.
Before pausing the music (if playing), I save the tracknum and relpos so I can continue afterwards - works as expected.
My code only makes a distinction between playlist and radio station stubru - either one of them can be playing.
Since currently testing - it is not yet a function to call with a custom text - easy to make it that way.
The following weblink details the parameters for voicerss. http://www.voicerss.org/api/documentation.aspx
Have fun, Bart


Code:
-- Load modules require('json') require('socket.http') require('socket.ftp') require('user.Sonos') -- Set SONOS Variables Sonos_Player_Name = 'Eetkamer'   action = 'none' -- Read IP address from controller data = io.readproc('if-json') data = json.decode(data) LMip = data.eth0.inetaddr -- Set timout socket.http.TIMEOUT = 5 -- Set volumes TTS_Volume = 80 Default_Volume = 25 --Check if player exists reply = Sonos_Find(Sonos_Player_Name) current_sonosname = reply.sonos_name current_sonosplayerip = reply.sonos_ipaddress current_sonosmacaddress = reply.sonos_macaddress current_sonosrincon = reply.sonos_rincon -- Check if Sonos is playing? reply = Sonos_Gettransportinfo(current_sonosplayerip) previous_transportmode = reply.Transportmode -- Get VolumeInfo reply = Sonos_GetVolume(current_sonosplayerip) current_volume = reply.Volume -- Get VolumeInfo reply = Sonos_Getmediainfo(current_sonosplayerip) current_URI = reply.CurrentURI local MP3_data = socket.http.request("http://api.voicerss.org/?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx&hl=nl-nl&f=16khz_16bit_stereo&src=Mooi%20weer%20vandaag%20ik%20doe%20alles%20vandaag%20een%20beetje%20traag") --Store on synology res, err = socket.ftp.put({    host = '192.168.1.200',    user = 'xxx',    password = 'xxx',    path = '/music/Domotica/MP3/TTS.mp3',      source = ltn12.source.string(MP3_data)  }) -- Get trackinfo reply=Sonos_Getpositioninfo(current_sonosplayerip) current_mediatype = reply.TrackTitle current_TrackRelTime = reply.TrackRelTime current_TrackNr = reply.TrackNr if previous_transportmode == 'PLAYING' then    upnpavcmd(current_sonosplayerip, 1400, 'Pause') end upnpavcmd(current_sonosplayerip, 1400, 'SetVolume', '<Channel>Master</Channel><DesiredVolume>' ..TTS_Volume.. '</DesiredVolume>') upnpavcmd(current_sonosplayerip, 1400, 'SetAVTransportURI', '<CurrentURI>x-file-cifs://DISKSTATION/music/Domotica/MP3/TTS.mp3</CurrentURI><CurrentURIMetaData/>') os.sleep(1) -- Check if Sonos is playing? upnpavcmd(current_sonosplayerip, 1400, 'Play', '<Speed>1</Speed>') os.sleep(1) reply = Sonos_Gettransportinfo(current_sonosplayerip) current_transportmode = reply.Transportmode --Wait until playing TTS-MP3 is finished while (current_transportmode == 'PLAYING') do  os.sleep(1)     reply = Sonos_Gettransportinfo(current_sonosplayerip)     current_transportmode = reply.Transportmode end upnpavcmd(current_sonosplayerip, 1400, 'Pause') if current_mediatype == 'stubru.aac' then  Sonos_Action = 'playuri'    Sonos_Listtype = 'favorites'  Sonos_Listnumber = 3  local reply = socket.http.request('http://' .. LMip .. '/apps/data/sonos/sonos.lp?action=' .. Sonos_Action .. '&name=' .. Sonos_Player_Name .. '&listtype=' .. Sonos_Listtype.. '&listnumber=' ..Sonos_Listnumber.. '') else     upnpavcmd(current_sonosplayerip, 1400, 'SetAVTransportURI', '<CurrentURI>' ..current_URI.. '</CurrentURI><CurrentURIMetaData/>')     upnpavcmd(current_sonosplayerip, 1400, 'Seek', '<InstanceID>0</InstanceID><Unit>TRACK_NR</Unit><Target>' ..current_TrackNr.. '</Target>')     upnpavcmd(current_sonosplayerip, 1400, 'Seek', '<InstanceID>0</InstanceID><Unit>REL_TIME</Unit><Target>' ..current_TrackRelTime.. '</Target>') end upnpavcmd(current_sonosplayerip, 1400, 'SetVolume', '<Channel>Master</Channel><DesiredVolume>' ..current_volume.. '</DesiredVolume>') upnpavcmd(current_sonosplayerip, 1400, 'Pause') if previous_transportmode == 'PLAYING' then  upnpavcmd(current_sonosplayerip, 1400, 'Play', '<Speed>1</Speed>') end script.disable(_SCRIPTNAME) -- loop while condition is met
Reply


Messages In This Thread
text to speech? - by gjniewenhuijse - 07.12.2016, 19:20
RE: text to speech? - by gjniewenhuijse - 09.01.2017, 14:41
RE: text to speech? - by bmodeco - 21.03.2017, 10:12
RE: text to speech? - by gjniewenhuijse - 21.03.2017, 13:05
RE: text to speech? - by bmodeco - 26.04.2017, 18:13

Forum Jump: