Escrito por

Software Architect at Visum
Artigo Yuri Marx · Fev. 21, 2022 6m read

Serviço REST para converter texto em áudio usando IRIS e Python gTTS

Olá Comunidade,

Imagine habilitar seu aplicativo para ler texto para seu cliente? Isso agora é possível com o novo recurso IRIS, Embedded Python. Com essa nova funcionalidade, o IRIS pode executar nativamente qualquer biblioteca Python comercial ou de código aberto. gTTS (https://pypi.org/project/gTTS/) é uma biblioteca gratuita que transforma texto em áudio usando o serviço Google Translate.

Como funciona

Basta passar o texto por parâmetro e o gTTS retorna um arquivo mp3 com o texto transformado em áudio. Ou seja, seu aplicativo pode reproduzir o áudio de qualquer texto! Veja como fazer:

1. Vá em https://openexchange.intersystems.com/package/IRIS-Text2Audio e clique Download.

2. Clone/git pull o repositório em qualquer diretório local

$ git clone https://github.com/yurimarx/iris-tts.git

3. Abra um terminal docker no diretório criado e execute:

$ docker-compose build

4. Execute o IRIS container:

$ docker-compose up -d 

5. Vá no Postman (ou similar) e configure a requisição como na figura:

Request TTS input

6. Clique em enviar e obtenha uma resposta com um player para reproduzir o arquivo mp3, como na imagem acima.

Explicando o Código Fonte

1. O Dockerfile instala o IRIS com Python e gTTS

 

Dockerfile

FROMintersystemsdc/iris-community

 

USERroot

 

ENVDEBIAN_FRONTENDnoninteractive

 

# install libraries required to gTTS to process TTS
RUNapt-get-yupdate\
    &&apt-get-yinstallapt-utils\
    &&apt-getinstall-ybuild-essentialunzippkg-configwget\
    &&apt-getinstall-ypython3-pip  

 

# use pip3 (the python zpm) to install gTTS dependencies
RUNpip3install--upgradepipsetuptoolswheel
RUNpip3install--target/usr/irissys/mgr/pythongTTS

 

USERroot  
WORKDIR/opt/irisbuild
RUNchown${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP}/opt/irisbuild
USER${ISC_PACKAGE_MGRUSER}

 

WORKDIR/opt/irisbuild
COPY  srcsrc
COPYInstaller.clsInstaller.cls
COPYmodule.xmlmodule.xml
COPYiris.scriptiris.script

 

USER${ISC_PACKAGE_MGRUSER}

 

RUNirisstartIRIS\
    &&irissessionIRIS<iris.script\
    &&irisstopIRISquietly

2. Uma ClassMethod foi criada com linguagem Python e usa gTTS para transformar texto em audio e gravar em um arquivo mp3:

 

Método Python para gerar audio a partir do texto

///TTS engine
Classdc.tts.TTSEngine
{

 

///Text to audio file
ClassMethodGenerateAudioFileFromText(sentence,language,domain)[Language=python]
{
        fromgttsimportgTTS
        importuuid

 

        tts =gTTS(sentence,lang=str(language),tld=str(domain))
        output =str(uuid.uuid1()) + '.mp3'
        tts.save('/opt/irisbuild/' +output)
        returnoutput
}

 

}

3. Uma API REST API em ObjectScript foi criada para expor a funcionalidade Python como um microserviço TTS (muito chique!)

 

TTS REST Service

Classdc.tts.TTSRESTAppExtends%CSP.REST
{

 

ParameterCHARSET="utf-8";

 

ParameterCONVERTINPUTSTREAM=1;

 

ParameterCONTENTTYPE="application/json";

 

ParameterVersion="1.0.0";

 

ParameterHandleCorsRequest=1;

 

XDataUrlMap[XMLNamespace="http://www.intersystems.com/urlmap"]
{
<Routes>
<!--ServerInfo-->
<RouteUrl="/"Method="GET"Call="GetInfo"Cors="true"/>
<!--Swaggerspecs-->
<RouteUrl="/_spec"Method="GET"Call="SwaggerSpec"/>

 

<!--generatetextfromaudiofile-->
<RouteUrl="/texttoaudio"Method="POST"Call="GenerateAudioFromText"/>

 

</Routes>
}

 

//Generate audio file from text

 

ClassMethodGenerateAudioFromText()As%Status
{
    SettSC=$$$OK
   
    try{
      // get the sentence to be processed
      Setsentence=$ZCONVERT(%request.Content.Read(),"I","UTF8")

 

      SetLanguage=%request.Get("lang")
      SetDomain=%request.Get("domain")

 

      SetLanguage=$GET(Language,0)
      IfLanguage=""{
        SetLanguage="en"
      }

 

      SetDomain=$GET(Domain,0)
      IfDomain=""{
        SetDomain="com"
      }

 

      //call embedded python classmethod to get mp3 audio file from text
      Setoutput=##class(dc.tts.TTSEngine).GenerateAudioFileFromText(sentence,Language,Domain)

 

      Set%response.ContentType="audio/mp3"
     
      Do%response.SetHeader("Content-Disposition","attachment;filename="""_output_"""")
      Set%response.NoCharSetConvert=1
      Set%response.Headers("Access-Control-Allow-Origin")="*"

 

      Setstream=##class(%Stream.FileBinary).%New()
      Setsc=stream.LinkToFile("/opt/irisbuild/"_output)
      Dostream.OutputToDevice()
       
      SettSC=$$$OK
 
    //returns error message to the user
    }catche{
        SettSC=e.AsStatus()
        SetpOutput=tSC
    }

 

    QuittSC
}

 

///General information
ClassMethodGetInfo()As%Status
{
  SETversion=..#Version
  SETfmt=##class(%SYS.NLS.Format).%New("ptbw")
 
  SETinfo={
    "Service":"TTS Service API",
    "version":(version),
    "Developer":"Yuri Gomes",
    "Status":"Ok",
    "Date":($ZDATETIME($HOROLOG))
  }
  Set%response.ContentType=..#CONTENTTYPEJSON
  Set%response.Headers("Access-Control-Allow-Origin")="*"

 

  Writeinfo.%ToJSON()
  Quit$$$OK
}

 

ClassMethod%ProcessResult(pStatusAs%Status={$$$OK},pResultAs%DynamicObject="")As%Status[Internal]
{
  #dim%responseAs%CSP.Response
  SETtSC=$$$OK
  IF$$$ISERR(pStatus){
    SET%response.Status=500
    SETtSC=..StatusToJSON(pStatus,.tJSON)
    IF$isobject(tJSON){
      SETpResult=tJSON
    }ELSE{
      SETpResult={"errors":[{"error":"Unknown error parsing status code"}]}
    }
  }
  ELSEIFpStatus=1{
    IF'$isobject(pResult){
      SETpResult={
      }
    }
  }
  ELSE{
    SET%response.Status=pStatus
    SETerror=$PIECE(pStatus," ",2,*)
    SETpResult={
      "error":(error)
    }
  }
 
  IFpResult.%Extends("%Library.DynamicAbstractObject"){
    WRITEpResult.%ToJSON()
  }
  ELSEIFpResult.%Extends("%JSON.Adaptor"){
    DOpResult.%JSONExport()
  }
  ELSEIFpResult.%Extends("%Stream.Object"){
    DOpResult.OutputToDevice()
  }
 
  QUITtSC
}

 

ClassMethodSwaggerSpec()As%Status
{
  SettSC=##class(%REST.API).GetWebRESTApplication($NAMESPACE,%request.Application,.swagger)
  Doswagger.info.%Remove("x-ISC_Namespace")
  Setswagger.basePath="/iris-tts"
  Setswagger.info.title="TTS Service API"
  Setswagger.info.version="1.0"
  Setswagger.host="localhost:52773"
  Return..%ProcessResult($$$OK,swagger)
}

 

}