Aller au contenu
lionel

Text-2-Speech Sonos

Recommended Posts

bonsoir

 

comme il y'a des spécialistes du 'LUA'

 

sur le forum officiel :http://forum.fibaro.com/viewtopic.php?t=1196

 

le Text-2-Speech ,ne fonctionne que si on ne modifie pas le texte,

 

le code est modifié lorsque l on sauvegarde (juste avant le texte 'parlé')

 

 

-Avant modification:

POST /MediaRenderer/AVTransport/Control HTTP/1.1 
Content-Length: 439 
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI" 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID>,<CurrentURI>x-rincon-mp3radio://translate.google.com/translate_tts?tl=en&q=There+is+someone+at+the+door</CurrentURI>,<CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>0x0D0x0A0x0D0x0A

-Apres modification:

POST /MediaRenderer/AVTransport/Control HTTP/1.1
Content-Length: 439
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID>,<CurrentURI>x-rincon-mp3radio://translate.google.com/translate_tts?tl=en&q=Domotique+fibaro</CurrentURI>,<CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>0x0D0x0A0x0D0x0A

une idée?

 

Merci

Partager ce message


Lien à poster
Partager sur d’autres sites

Peut être le & dans la requête ;)

 

avant: translate.google.com/translate_tts?tl=en&amp;q=

après: translate.google.com/translate_tts?tl=en&q=

 

Et aussi le "Content-Length: 439" qui doit changer puisque la taille du corp de la requête change ().

Partager ce message


Lien à poster
Partager sur d’autres sites

en effet, pas mal cette fonction.. ce n'est pas possible de lui faire dire autre chose que ce qui est paramétré dans le forum officiel?

Partager ce message


Lien à poster
Partager sur d’autres sites

Tout àfait possible en suivant les points soulevés avant.

Partager ce message


Lien à poster
Partager sur d’autres sites

J’essaye de faire du "TTS" grâce au script trouvé sur le forum officiel...ça fonctionne impec.

POST /MediaRenderer/AVTransport/Control HTTP/1.1
Content-Length: 439
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID>,<CurrentURI>x-rincon-mp3radio://translate.google.com/translate_tts?tl=fr&q=Essais+sonos</CurrentURI>,<CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>0x0D0x0A0x0D0x0A

Par contre j'aimerais mieux que ca me parle en Francais, et ca, j'arrive pas, j'ai passer "en" en "fr" mais rien n'y fait....

 

Quelqu'un utilise le TTs ?

Partager ce message


Lien à poster
Partager sur d’autres sites

salut

chez moi toujours pareil ,ça ne fonctionne pas

 

tts?tl=fr&q=Essais+sonos

 

 

après la sauvegarde c est ça:

 

tts?tl=fr&q=Essais+sonos

 

:huh:  :angry: 

Partager ce message


Lien à poster
Partager sur d’autres sites

Aprés 3 jours d'investigation et des heures d'arrachage de cheveux, j'ai peut être isolé la cause du problème empêchant de faire du TTS !!!    :60:

 

Je suis content d'avoir isolé le soucis mais il y a toujours un "loup" quelque part... :angry:

 

Donc, bien respecter l'ordre ci dessous pour ajouter une commande vocale :

 

  • Créer un nouveau VD et renseigner l'IP de votre Play

 

  • Ajouter un bouton

 

  • Saisir ce code en "string" (les espaces sont supprimés, le prendre tel-quel ) :
POST /MediaRenderer/AVTransport/Control HTTP/1.1
Content-Length: 439
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID>,<CurrentURI>x-rincon-mp3radio://translate.google.com/translate_tts?tl=fr&q=la+commande+vocale+fonctionne+enfin</CurrentURI>,<CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>0x0D0x0A0x0D0x0A
  • Sauvegarder

( Pour info, aprés la sauvegarde, comme a dit @LionelA , la syntaxe " amp; " disparaît mais ce n'est pas génant...

 

TRES IMPORTANT:

 

Ne plus jamais modifier une partie de ce code aprés l'avoir enregistré sinon, cela ne fonctionnera plus!!!

Il faudra repartir d'un nouveau VD

 

Si vous souhaitez enregistrer une nouvelle commande vocale, il faudra donc recréer un VD, et pareil, ne plus le toucher!

 

Il y a donc un bug quelque par sur la box, en attendant, ça a l'air de fonctionner, mais si un pro du code lua veut bien se pencher dessus ou nous pondre un script permettant de faire du TTS via une variable et un code lua, ça serait top !!!  ;)

 

EDIT:

Même si le code ci-dessus est le bon, il faut impérativement partir de celui du forum officiel, et le modifier ( changer "en" en "fr" + le texte à  annoncer + enlever les espaces ) je comprends pas pourquoi l ??

Partager ce message


Lien à poster
Partager sur d’autres sites

Bonsoir,

 

Je m'insère dans la discussion pour vous transmettre mon experience.

 

Une fois crée un module virtuel, je peux changer le code à  l'intérieur, donc modifier le texte à  reproduire, en français ou en anglais. Par contre pour que cela fonctionne, il me faut toujours sauvegarder le bouton avec le changement suivant :

 

tl=fr&q= en lieu et place de ce qu'il remet à  chaque sauvegarde c à  d : tl=en&q=

 

Il faut également mettre modifier le 

 

  1. Content-Length: 439

 

et ce en fonction de la modification du nombre de caractères ajouter ou retirer...

 

Je suppose que tout le monde avait vu qu'il fallait faire lecture pour entendre le son et stop quand on en avait marre. Je le précise parce que si je ne l'avais pas lu, j'y serais encore….

 

J'espère que cela va permettre aux malchanceux de se rapprocher de leur but.

 

Arnaud.

Partager ce message


Lien à poster
Partager sur d’autres sites

Voici le TTS enfin opérationnel et ceci grâce à  Krikroff...

 

Il faut :

  • créer un périphérique virtuel
  • Renseigner adresse IP et Port du sonos ( 1400 )
  • Créer un Bouton et saisir le code ci-dessous :

Pour changer le tts, il suffira de modifier la dernière ligne du code.

 

Celle-ci étant conçue comme ceci : playTTS(strLang, strMessage, nil, intVolume)

 

strLang = Language du tts

strMessage = Message à  envoyer à  Sonos

nil = mode arrêt auto sinon remplacer par la durée

intVolume = volume des sonos

------------------------------------------------------------------------------------------- 
------------------------------------------------------------------------------------------- 
-- SONOS Text To Speech (TTS) - Give voice to your HC2 with SONOS wireless speakers 
-- Version 0.0.4 pre-release 
-- Copyright (C) 2014 Jean-Christophe Vermandé 
------------------------------------------------------------------------------------------- 
------------------------------------------------------------------------------------------- 

selfId = fibaro:getSelfId();    
ip = fibaro:get(selfId, 'IPAddress'); 
port = fibaro:get(selfId, 'TCPPort'); 
currentTransportState = ""; 
lastTransportState = ""; 
currentVolume = 0; 
lastVolume = 0; 
ttsVolumeIsDifferent = false; 

urlencode = function(str) 
  if (str) then 
    str = string.gsub (str, "\n", "\r\n"); 
    str = string.gsub (str, "([^%w ])", function (c) return string.format ("%%%02X", string.byte(c)) end); 
    str = string.gsub (str, " ", "+"); 
  end 
  return str; 
end 

createRequestBody = function(action, schema, data) 
  return string.format("<u:%s xmlns:u=\"%s\">%s</u:%s>", action, schema, data, action); 
end 

reponseCallback = function(fnc, args) 
  if (fnc == nil) then 
    return nil; 
  end 
  return fnc(args); 
end 

createSocket = function() 
    -- Check IP and PORT before 
  if (ip == nil or port == nil) then 
    fibaro:debug("You must configure IPAddress and TCPPort first"); 
    return; 
  end 
  local socket; 
  local status, err = pcall(function() 
      socket = Net.FTcpSocket(ip, port); 
      socket:setReadTimeout(1000); 
    end);  
  if (status ~= nil and status ~= true) then 
    fibaro:debug("socket status: " .. tostring(status or '')); 
  end  
  if (err ~= nil) then 
    fibaro:debug("socket err: " .. tostring(err or '')); 
    return; 
  end 
  return socket; 
end 

disposeSocket = function(socket) 
  if (socket ~= nil) then 
    socket:disconnect(); 
    socket = nil; 
    return true; 
  end 
  return false; 
end 

sendSoapMessage = function(url, service, action, args, callback, retry) 
    
  local socket = createSocket(); 
  if (socket == nil) then 
    return; 
  end 
  retry = retry or 0 
  -- prepare data 
  local url = "POST " .. url .. " HTTP/1.1"; 
  local soapaction = "SOAPACTION: \"" .. service .. "#" .. action.name .. "\""; 
  local body = createRequestBody(action.name, action.service, tostring(args or "")); 
  local envelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>" .. body .. "</s:Body></s:Envelope>"; 
  local ctl = "Content-Length: " .. string.len(envelope); 
  local payload = url .. "\r\n" .. ctl .. "\r\n" .. soapaction .. "\r\n" .. "\r\n" .. envelope; 
  -- write data 
  local bytes, errorcode = socket:write(payload); 
  if (errorcode == 0) then 
    local state, errorcode = socket:read(); 
    if (errorcode == 0) then 
      if (string.len(state or "") > 0) then 
        -- callback 
        if (callback ~= nil) then 
          reponseCallback(callback, state); 
        end 
        -- dispose ... 
        disposeSocket(socket); 
        return true; 
      else 
        fibaro:debug("Error: Invalid response. response length: " .. string.len(state or "")); 
      end 
    else      
      if (retry < 5) then 
        fibaro:debug("retry #"..retry.." action: " .. action.name); 
        return sendSoapMessage(url, service, action, args, callback, (retry + 1)); 
      else 
        fibaro:debug("Error: Code returned "..tostring(errorcode or "")); 
      end 
    end 
  elseif (errorcode == 2) then 
    fibaro:debug("Error: You must check your IP and PORT settings."); 
  else 
    if (retry < 5) then 
      fibaro:debug("retry #"..retry.." action: " .. action.name); 
      return sendSoapMessage(url, service, action, args, callback, (retry + 1)); 
    else 
      fibaro:debug("Error: Code returned "..tostring(errorcode or "")); 
    end 
  end  
  -- dispose ... 
  disposeSocket(socket); 
  -- default response 
  return false; 
end 

stop = function() 
  return sendSoapMessage( 
    -- control url 
    "/MediaRenderer/AVTransport/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:AVTransport:1", 
    -- action 
    { name = "Stop", service = "urn:schemas-upnp-org:service:AVTransport:1" }, 
    -- soap body data (options) 
    "<InstanceID>0</InstanceID><Speed>1</Speed>", 
      -- callback (options) 
    function(response) 
      fibaro:debug("stop sent"); 
    end);    
end 

unMute = function() 
  return sendSoapMessage( 
    -- control url 
    "/MediaRenderer/RenderingControl/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:RenderingControl:1", 
    -- action 
    { name = "SetMute", service = "urn:schemas-upnp-org:service:RenderingControl:1" }, 
    -- soap body data (options) 
    "<InstanceID>0</InstanceID><Channel>Master</Channel><DesiredMute>0</DesiredMute>", 
      -- callback (options) 
    function(response) 
      fibaro:debug("unMute sent"); 
    end); 
end 

play = function(duration) 
  return sendSoapMessage( 
    -- control url 
    "/MediaRenderer/AVTransport/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:AVTransport:1", 
    -- action 
    { name = "Play", service = "urn:schemas-upnp-org:service:AVTransport:1" }, 
    -- soap body data (options) 
    "<InstanceID>0</InstanceID><Speed>1</Speed>", 
      -- callback (options) 
    function(response)    
      if (duration ~= nil) then 
        fibaro:debug("play sent for " .. duration .. " seconds"); 
        fibaro:sleep(duration); 
        stop(); 
      else 
        fibaro:debug("play sent"); 
        local n = 0; 
        currentTransportState = "TRANSITIONING"; 
        while (currentTransportState == "TRANSITIONING") do 
          if (n > 10) then break end; 
          getTransportState(); 
          fibaro:debug(currentTransportState); 
          fibaro:sleep(5000); 
          n = n + 1; 
        end        
        local i = 0; 
        currentTransportState = "PLAYING"; 
        while (currentTransportState == "PLAYING") do 
          if (i > 10) then break end; 
          getTransportState(); 
          fibaro:debug(currentTransportState); 
          fibaro:sleep(2000); 
          i = i + 1; 
        end 
        fibaro:sleep(1000); 
        stop(); 
      end 
      -- update volume with value before tts if different 
      if (ttsVolumeIsDifferent == true) then 
          setVolume(lastVolume); 
        ttsVolumeIsDifferent = false; 
      end 
    end);    
end 

setVolume = function(value) 
  return sendSoapMessage( 
    -- control url 
    "/MediaRenderer/RenderingControl/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:RenderingControl:1", 
    -- action 
    { name = "SetVolume", service = "urn:schemas-upnp-org:service:RenderingControl:1" }, 
    -- soap body data (options) 
    "<InstanceID>0</InstanceID><Channel>Master</Channel><DesiredVolume>" .. tostring(value) .. "</DesiredVolume>", 
    -- callback (options) 
    function(response)      
      fibaro:debug("Volume set: " .. value); 
    end); 
end 

getVolume = function() 
  fibaro:log("Get volume, please wait..."); 
  return sendSoapMessage( 
    -- control url 
      "/MediaRenderer/RenderingControl/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:AVTransport:1", 
    -- action 
    { name = "GetVolume", service = "urn:schemas-upnp-org:service:RenderingControl:1" }, 
    -- soap body data (options)    
    "<InstanceID>0</InstanceID><Channel>Master</Channel>", 
    -- callback (options) 
    function(response) 
      currentVolume = tonumber(response:match("<CurrentVolume>(.+)</CurrentVolume>") or 0);    
    end); 
end 

getTransportState = function() 
  return sendSoapMessage( 
    -- control url 
      "/MediaRenderer/AVTransport/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:AVTransport:1", 
    -- action 
    { name = "GetTransportInfo", service = "urn:schemas-upnp-org:service:AVTransport:1" }, 
    -- soap body data (options) 
    "<InstanceID>0</InstanceID>", 
    -- callback (options) 
    function(response)      
      currentTransportState = response:match("<CurrentTransportState>(.+)</CurrentTransportState>") or ""; 
    end); 
end 

playTTS = function(lng, message, duration, volume) 
  return sendSoapMessage( 
    -- control url 
    "/MediaRenderer/AVTransport/Control", 
    -- service type 
    "urn:schemas-upnp-org:service:AVTransport:1", 
    -- action 
    { name = "SetAVTransportURI", service = "urn:schemas-upnp-org:service:AVTransport:1" }, 
    -- soap body data (options) 
    "<InstanceID>0</InstanceID>,<CurrentURI>x-rincon-mp3radio://translate.google.com/translate_tts?tl=".. lng .. "&a" .. "mp;q=" .. urlencode(message) .. "</CurrentURI>,<CurrentURIMetaData></CurrentURIMetaData>", 
    -- callback (options) 
    function(response) 
      -- retrieve current transport state 
      getTransportState(); 
      lastTransportState = currentTransportState; 
      -- unmute before 
      unMute(); 
      -- retrieve volume 
      getVolume(); 
      lastVolume = currentVolume; 
      -- set tts volume if <> with current 
      if (volume ~= nil and volume ~= currentVolume) then 
          setVolume(volume); 
        ttsVolumeIsDifferent = true; 
      end 
      -- play tts 
      fibaro:debug("tts: " .. message); 
      if (duration ~= nil) then 
        play(duration); 
      else 
        play(); 
      end 
    end);  
end 

playTTS("fr", "Bonjour les gens du forum ! Voici le T.T.S enfin fonctionnele !", nil, 12); 

Post officiel : http://forum.fibaro.com/viewtopic.php?p=30402#30373

Partager ce message


Lien à poster
Partager sur d’autres sites

C'est en effet simplement parfait pour la gestion des alarmes et notifications.

 

Merci encore Krikroff pour le code et Moicphil pour le rapatriement.

 

B)

Partager ce message


Lien à poster
Partager sur d’autres sites

Bonsoir,

 

J'ai une petite question. Est-ce qu'il serait envisageable que lorsque la lecture est terminée, ce qui était lu sur le sonos puisse redémarrer à  peu près la ou il en était ?

 

En gros, on écoute une musique, il y a une annonce et la musique revient au stade ou elle en était ?

 

Cela serait évidemment la cerise sur le gâteau !

 

A bientôt,

 

Et merci encore pour ce code.

Partager ce message


Lien à poster
Partager sur d’autres sites

à‡a serait bien en effet.

 

à‡a tombe bien, je crois que JC n'a plus rien à  se mettre sous la dent en ce moment...c'est ça non JC ?  :D

Partager ce message


Lien à poster
Partager sur d’autres sites

C'est ça Phil :lol: ...

 

Arnaud78, c'est déjà  implémenté dans le périphérique virtuel qui en cours de finalisation :D. Vous aurez aussi la possibilité de lancer un tts depuis n'importe quel périphérique virtuel ou bien scène ;) avec juste une ligne de code: top non ?

Aussi, retour d'informations du Sonos.

Aussi, gestion intelligente du polling, du GC (optimisation de la mémoire).

etc. etc.

 

Elle est pas belle la vie ;)

Partager ce message


Lien à poster
Partager sur d’autres sites

Rooooo bein si c'est ici qu'on fait ses courses pour du tts auprès de JC je verrais bien un menu en + sur le toolkit pour générer des xml automatiquement pour S.A.R.A.H, en fonction de phrases qu'on aurait renseigné dans le toolkit et des actions associées sur les modules :-D 3 fois rien ^^

Partager ce message


Lien à poster
Partager sur d’autres sites

Salut @Krikroff

 

penses tu ,qu il soit possible de lancer un titre Mp3 en particulier sur un sonos?

Partager ce message


Lien à poster
Partager sur d’autres sites

Oui @lionel, pas de problème, pour cela il faut utiliser l'action "SetAVTransportURI" et passer une url du type x-file-cifs://HOME-SERVER/Musique/CD/Dream Theater/A Change of Seasons/01-A Change of Seasons [Medley].flac, j'utilise cette méthode pour faire rejouer le titre en cours avant un TTS. Utilisable aussi pour par exemple déclencher un son de sonnerie ou d'alerte sur un événement ...

Partager ce message


Lien à poster
Partager sur d’autres sites

Concernant ton nouveau VD.

T'as pas besoin d'un béta testeur par hasard JC ?

:15:

Partager ce message


Lien à poster
Partager sur d’autres sites

déjà ,

bonne nouvelle,si tu arrives a le faire  ;)

 

donc si j ai un peu compris,c est dans le même type de prog que le premier post du sujet ?!

Partager ce message


Lien à poster
Partager sur d’autres sites

×