文章 Michael Lei · 五月 3, 2022 6m read

使用IRIS 和Python gTTS 实现文本转化声音的REST服务

Hi 社区,

想象一下,使您的应用程序能够阅读文本?现在有了IRIS的新功能--嵌入式Python,这就成为可能。有了这个新功能,IRIS可以原生地运行任何开源或商业的Python库。gTTS(https://pypi.org/project/gTTS/)是一个免费的库,使用谷歌翻译服务将文本转换成音频。

怎么做

只要通过参数传递文本,gTTS就会返回一个将文本转换为音频的MP3文件。也就是说,你的应用程序可以播放任何文本的音频! 请看如何做到这一点。

1. 进入https://openexchange.intersystems.com/package/IRIS-Text2Audio,点击下载按钮。

2. 克隆/git pull repo到任何本地目录中

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

3. 在这个目录中打开一个Docker终端,运行:

$ docker-compose build

4. 运行IRIS container:

$ docker-compose up -d 

5. 到Postman (或其他类似的 REST 客户端) 来配置请求,如图所示:

Request TTS input

6. 点击发送,就会收到一个播放器的回复,可以播放MP3文件,如上图

背后的代码

1. Docker文件安装IRIS与Python和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. 用Python语言配置创建了一个ClassMethod,使用gTTS将文本转化为音频并记录在MP3文件中。:

 

Python method to generate audio from text

///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. 在ObjectScript中创建了一个REST API,将Python功能作为一个TTS微服务公开(非常Cool!)

 

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)
}

 

}