文本转语音服务项目

      项目效果显示页面2017/7月前有效:   http://myjavaweb1.mybluemix.net/


          摘要:Text to Speech 服务提供的应用程序编程接口 (API) 使用 IBM 的语音合成功能将文本转换成音频信号。此服务提供了具象状态传输 (REST) 接口,支持将各种语言、口音和语音的文本合成自然语音。此服务目前可将英语或西班牙语的书面文本合成男声(英语和西班牙语)或女声(仅限英语)朗读的音频信号。音频可通过流式方法传输回客户机,延迟时间最短。

本文工程下载:http://download.csdn.net/detail/evankaka/9427964

本文实例访问:http://texttospeechtest.eu-gb.mybluemix.net/

BluxMix账号注册:https://apps.admin.ibmcloud.com/manage/trial/bluemix.html?cm_mmc=CMDeveloperGCG-_-Bluemix-_-CSDN-_-onlineeventQ2


一、Bluemix创建web工程并添加文本转语音服务

1、创建Bluemix上的web工程.(如何创建工程可看基于IBM Bluemix部署Java Web项目实战演练)

2、添加文本转语音服务


添加服务


3、最后绑定的服务的工程如下:



二、本地创建工程

这里需要创建一个dynamic 的web工程,本文是直接在https://github.com/watson-developer-cloud/text-to-speech-java这上工程的基础上来做修改的。

最终目录如下:


下面来分析一下关键的代码,这里是以Servlet来实现语音的获取的

(1)DemoServlet.java

这是本工程的核心代码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.ibm.cloudoe.samples;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.URI;  
  5. import java.util.logging.Level;  
  6. import java.util.logging.Logger;  
  7.   
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletOutputStream;  
  10. import javax.servlet.annotation.MultipartConfig;  
  11. import javax.servlet.http.HttpServlet;  
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.   
  15. import org.apache.http.HttpStatus;  
  16. import org.apache.http.client.fluent.Executor;  
  17. import org.apache.http.client.fluent.Request;  
  18. import org.apache.http.client.fluent.Response;  
  19.   
  20. import com.ibm.ws.xs.json.java.JSONArray;  
  21. import com.ibm.ws.xs.json.java.JSONObject;  
  22.   
  23. @MultipartConfig  
  24. public class DemoServlet extends HttpServlet {  
  25.     private static Logger logger = Logger.getLogger(DemoServlet.class.getName());  
  26.     private static final long serialVersionUID = 1L;  
  27.   
  28.     private String serviceName = "text_to_speech";  
  29.   
  30.     // 此处需要修改成您自己的  
  31.     private String baseURL = "https://stream.watsonplatform.net/text-to-speech/api";  
  32.     private String username = "bd546fff-2e43-42c9-8c76-71075c257128";  
  33.     private String password = "AL7sK4TRu0T0";  
  34.   
  35.     /** 
  36.      * 处理前台传过来的请求 
  37.      */  
  38.     @Override  
  39.     protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {  
  40.         if (req.getParameter("text") == null || req.getParameter("voice") == null) { //如果文本或语音为空,返回到初始界面  
  41.             req.getRequestDispatcher("/index.jsp").forward(req, resp);  
  42.         } else {  
  43.             boolean download = false;  
  44.             if (req.getParameter("download") != null && req.getParameter("download").equalsIgnoreCase("true")) { //判断是否下载语音  
  45.                 download = true;  
  46.             }  
  47.   
  48.             req.setCharacterEncoding("UTF-8");  
  49.             try {  
  50.                 String queryStr = req.getQueryString();  
  51.                 String url = baseURL + "/v1/synthesize";  
  52.                 if (queryStr != null) {  
  53.                     url += "?" + queryStr;//连接url  
  54.                 }  
  55.                 URI uri = new URI(url).normalize();  
  56.   
  57.                 Request newReq = Request.Get(uri); //构造请求头  
  58.                 newReq.addHeader("Accept""audio/ogg; codecs=opus"); //设置语音格式,还可以为"audio/wav"或者 "audio/flac"  
  59.   
  60.                 Executor executor = Executor.newInstance().auth(username, password);  
  61.                 Response response = executor.execute(newReq);//发送请求报文,并取得返回  
  62.                 if (download)  
  63.                 {  
  64.                     resp.setHeader("content-disposition""attachment; filename=transcript.ogg");//下载语音  
  65.                 }  
  66.                 ServletOutputStream servletOutputStream = resp.getOutputStream();  
  67.                 response.returnResponse().getEntity()  
  68.                 .writeTo(servletOutputStream);//将语音流返回前台  
  69.                 servletOutputStream.flush();  
  70.                 servletOutputStream.close();  
  71.             } catch (Exception e) {  
  72.                 // Log something and return an error message  
  73.                 logger.log(Level.SEVERE, "got error: " + e.getMessage(), e);  
  74.                 resp.setStatus(HttpStatus.SC_BAD_GATEWAY);  
  75.             }  
  76.         }  
  77.     }  
  78.   
  79.     /** 
  80.      * 取得环境变量 
  81.      */  
  82.     private JSONObject getVcapServices() {  
  83.         String envServices = System.getenv("VCAP_SERVICES");  
  84.         if (envServices == nullreturn null;  
  85.         JSONObject sysEnv = null;  
  86.         try {  
  87.             sysEnv = JSONObject.parse(envServices);  
  88.         } catch (IOException e) {  
  89.             // Do nothing, fall through to defaults  
  90.             logger.log(Level.SEVERE, "Error parsing VCAP_SERVICES: "+e.getMessage(), e);  
  91.         }  
  92.         return sysEnv;  
  93.     }  
  94.   
  95.     @Override  
  96.     public void init() throws ServletException {  
  97.         super.init();  
  98.         processVCAP_Services();  
  99.     }  
  100.       
  101.     /** 
  102.      * 取得环境变量的参数 
  103.      */  
  104.     private void processVCAP_Services() {  
  105.         logger.info("Processing VCAP_SERVICES");  
  106.         JSONObject sysEnv = getVcapServices();  
  107.         if (sysEnv == nullreturn;  
  108.         logger.info("Looking for: "+ serviceName );  
  109.   
  110.         for (Object key : sysEnv.keySet()) {  
  111.             String keyString = (String) key;  
  112.             logger.info("found key: " + key);  
  113.             if (keyString.startsWith(serviceName)) {  
  114.                 JSONArray services = (JSONArray)sysEnv.get(key);  
  115.                 JSONObject service = (JSONObject)services.get(0);  
  116.                 JSONObject credentials = (JSONObject)service.get("credentials");  
  117.                 baseURL  = (String)credentials.get("url");  
  118.                 username = (String)credentials.get("username");  
  119.                 password = (String)credentials.get("password");  
  120.                 logger.info("baseURL  = "+baseURL);  
  121.                 logger.info("username = "+username);  
  122.                 logger.info("password = "+password);  
  123.             } else {  
  124.                 logger.info("Doesn't match /^"+serviceName+"/");  
  125.             }  
  126.         }  
  127.     }  
  128. }  

这里的原理其实就是前台传文本过来后,在doget方法中再构造request请求头到语音处理中心,它将结果返回到servlet,再返回到前台。

(2)前台关键代码

这是页面的内容:

index.jsp

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
  2. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  
  3. <!DOCTYPE html>  
  4. <html lang="en">  
  5. <head>  
  6.     <title>文本转语音实例</title>  
  7.     <meta charset="utf-8">  
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  9.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  10.     <link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon">  
  11.     <link rel="icon" href="images/favicon.ico" type="image/x-icon">  
  12.     <link rel="stylesheet" href="css/watson-bootstrap-dark.css">  
  13.     <link rel="stylesheet" href="css/style.css">  
  14. </head>  
  15.   
  16. <body>  
  17.     <div class="container">  
  18.         <div class="row">  
  19.             <div class="col-lg-7 col-md-7 col-xs-12">  
  20.                 <h2>文本转语音</h2>  
  21.                 <div class="well">  
  22.                     <form method="get" class="form-horizontal">  
  23.                         <fieldset>  
  24.                             <div class="row">  
  25.                                 <div class="col-lg-12 col-xs-12">  
  26.                                     <label for="textArea" class="control-label">请输入或复制要转换成语音的文本:</label>  
  27.                                     <textarea id="textArea" name="text" rows="8" required class="form-control"></textarea><span class="help-block"><small>注意只能输入现一种语言,语音返回会有点慢,请耐心等待</small></span>  
  28.                                 </div>  
  29.                             </div>  
  30.                             <div style="margin-bottom:30px;" class="row">  
  31.                                 <label for="voice" class="col-lg-12 col-xs-12 control-label">请选择语音类型:</label>  
  32.                                 <div class="col-lg-12 col-xs-12">  
  33.                                     <select class="select-voice" id="voice" style="width:100%" name="voice" required class="form-control">  
  34.                                     </select>  
  35.                                 </div>  
  36.                             </div>  
  37.                             <div class="row">  
  38.                                 <div class="col-lg-4 col-xs-4 download-container">  
  39.                                     <input value="Download" class="btn btn-block download-button">  
  40.                                 </div>  
  41.                                 <div class="col-lg-4 col-xs-4 text-center"></div>  
  42.                                 <div class="col-lg-4 col-xs-4 ie-speak">  
  43.                                     <input value="Speak" class="btn btn-block speak-button">  
  44.                                     <div class="arrow-box">  
  45.                                         <p>请使用谷歌或火狐浏览器</p>  
  46.                                     </div>  
  47.                                 </div>  
  48.                             </div>  
  49.                         </fieldset>  
  50.                     </form>  
  51.                 </div>  
  52.             </div>  
  53.             <div class="col-lg-5 col-md-5 col-xs-12">  
  54.                 <h2>语音输出</h2>  
  55.                 <div class="row">  
  56.                     <div class="col-lg-12 col-xs-12">  
  57.                         <div style="display:none" class="well result">  
  58.                             <div class="text-center">  
  59.                                 <audio autoplay preload="auto" autobuffer controls class="audio"></audio>  
  60.                             </div>  
  61.                             <div><span class="help-block">返回的语音是以<a href="http://www.vorbis.com/">Ogg Vorbis</a> 格式的,它可以使用<a href="http://www.videolan.org/vlc/index.html">VLC</a><a href="http://audacity.sourceforge.net/">Audacity</a> 等来播放</span>  
  62.                             </div>  
  63.                         </div>  
  64.                         <div style="display:none" class="well error">  
  65.                             <div class="form-group row">  
  66.                                 <div class="col-lg-12 col-xs-12">  
  67.                                     <p class="errorMsg">处理请求失败</p>  
  68.                                 </div>  
  69.                             </div>  
  70.                         </div>  
  71.                     </div>  
  72.                 </div>  
  73.             </div>  
  74.         </div>  
  75.         <div class="row">  
  76.             <div class="help-block text-center"><small>请使用谷歌浏览器 <a href="https://www.google.com/intl/en/chrome/browser/desktop/" target="_blank">Chrome </a>火狐浏览器 <a href="https://www.mozilla.org/en-US/firefox/new/" target="_blank">Firefox.</a></small>  
  77.             </div>  
  78.         </div>  
  79.     </div>  
  80.     <script type="text/javascript" src="js/browser-detect.js"></script>  
  81.     <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>  
  82.     <script type="text/javascript" src="js/constants.js"></script>  
  83.     <script type="text/javascript" src="js/demo.js"></script>  
  84. </body>  
  85.   
  86. </html>  
demo.js,引用的js文件内容:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 'use strict';  
  2. //页面一加载完成就执行  
  3. $(function () {   
  4.   var audio = $('.audio').get(0),//语音播放器  
  5.     textArea = $('#textArea'); //文本内容  
  6.   
  7.   //为语音选择器添加内容  
  8.   Object.keys(VOICES).forEach(function(key) {  
  9.     $('<option>', { value : key })  
  10.     .appendTo($('.select-voice'))  
  11.     .text(VOICES[key]);  
  12.   });  
  13.   //设置初始文本内容  
  14.   function updateSampleText() {  
  15.     var lang = $('.select-voice').val().substr(0,5);  
  16.     $('#textArea').text(SAMPLE_TEXT[lang]);  
  17.   }  
  18.   $('.select-voice').change(updateSampleText);  
  19.   updateSampleText();  
  20.   
  21.   // IE 和 Safari 不支持此实例语音播放,让speak按钮 无效  
  22.   if ($('body').hasClass('ie') || $('body').hasClass('safari')) {  
  23.     $('.speak-button').prop('disabled'true);  
  24.   }  
  25.   
  26.   if ($('.speak-button').prop('disabled')) {  
  27.     $('.ie-speak .arrow-box').show();  
  28.   }  
  29.   //播放错误信息  
  30.   $('.audio').on('error'function () {  
  31.     $('.result').hide();  
  32.     $('.errorMgs').text('Error processing the request.');  
  33.     $('.errorMsg').css('color','red');  
  34.     $('.error').show();  
  35.   });  
  36.  //播放语音  
  37.   $('.audio').on('loadeddata'function () {  
  38.     $('.result').show();  
  39.     $('.error').hide();  
  40.   });  
  41.   //download点击事件  
  42.   $('.download-button').click(function() {  
  43.     textArea.focus();  
  44.     if (validText(textArea.val())) {  
  45.       window.location.href = '?download=true&' + $('form').serialize();  
  46.     }  
  47.   });  
  48.   
  49.   //speak按钮点击事件  
  50.   $('.speak-button').click(function() {  
  51.     $('.result').hide();  
  52.     audio.pause();  
  53.   
  54.     $('#textArea').focus();  
  55.     if (validText(textArea.val())) {  
  56.       audio.setAttribute('src','?&' + $('form').serialize());  
  57.     }  
  58.   });  
  59.   
  60.   //校验文本的输入内容  
  61.   function validText(text) {  
  62.     $('.error').hide();  
  63.     $('.errorMsg').css('color','#5a5a5a');  
  64.   
  65.     if ($.trim(text).length === 0) {  
  66.       $('.errorMsg').text('Please enter the text you would like to synthesize in the text window.');  
  67.       $('.errorMsg').css('color','#5a5a5a');  
  68.       $('.error').show();  
  69.       return false;  
  70.     }  
  71.   
  72.     if (!containsAllLatin1(text)) {  
  73.       $('.errorMsg').text('Language not supported. Please use only ISO 8859 characters');  
  74.       $('.error').show();  
  75.       return false;  
  76.     }  
  77.   
  78.     return true;  
  79.   }  
  80.   
  81.   /** 
  82.    * Check that the text doesn't contains non latin-1 characters. 
  83.    * @param  String  The string to test 
  84.    * @return true if the string is latin-1 
  85.    */  
  86.   function containsAllLatin1(str) {  
  87.     return  /^[A-z\u00C0-\u00ff\s?@¿''\.,-\/#!$%\^&\*;:{}=\-_`~()0-9]+$/.test(str);  
  88.   }  
  89.   
  90. });  

其它具体的请看工程代码,这里不再做分析。

(3)添加jar包

本地运行需要添加如下jar包,记得!

其中json-org.jar和ogclient.jar可到这里下载ftp://public.dhe.ibm.com/cloud/bluemix/datacache/


同时工程右键设置属性中,编辑的JDK选择1.6,web版本选择2.5

(4)本地发布运行

右键运行即可,

输入http://localhost:8088/app/


测试过后没有问题。下一步发布到个人bluemix中心。


三、发布到个人bluemix中心

(1)打包war包

因为本工程使用了ant.其实内容如下:

build.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE xml>  
  3.   
  4. <project basedir="." default="build" name="WebApp">  
  5.     <property environment="env" />  
  6.     <property name="srcDir" value="." />  
  7.     <property name="debuglevel" value="source,lines,vars" />  
  8.     <property name="target" value="1.6" />  
  9.     <property name="source" value="1.6" />  
  10.     <property name="ARCHIVE_DIR" value="output" />  
  11.     <property name="LIB_DIR" value="./lib" />  
  12.     <property name="WEB_INF_LIB_DIR" value="./WebContent/WEB-INF/lib" />  
  13.     <property name="warname" value="webApp.war" />  
  14.     <path id="classpathDir">  
  15.         <pathelement location="build/bin" />  
  16.         <fileset dir="${LIB_DIR}">  
  17.             <include name="*.jar" />  
  18.         </fileset>  
  19.         <fileset dir="${WEB_INF_LIB_DIR}">  
  20.             <include name="*.jar" />  
  21.         </fileset>  
  22.     </path>  
  23.     <target name="init">  
  24.         <mkdir dir="build" />  
  25.         <mkdir dir="build/bin" />  
  26.     </target>  
  27.     <target name="clean">  
  28.         <delete dir="build" />  
  29.         <delete file="${ARCHIVE_DIR}/${warname}" />  
  30.     </target>  
  31.     <target name="build" depends="build-project,build-war" />  
  32.     <target name="cleanall" depends="clean" />  
  33.     <target name="build-project" depends="clean,init">  
  34.         <copy todir="${ARCHIVE_DIR}">  
  35.           <fileset file="manifest.yml" />  
  36.         </copy>  
  37.         <echo message="${ant.project.name}: ${ant.file}" />  
  38.         <javac debug="true" debuglevel="${debuglevel}" destdir="build/bin" source="${source}" target="${target}" includeantruntime="false">  
  39.             <src path="src" />  
  40.             <classpath refid="classpathDir" />  
  41.         </javac>  
  42.     </target>  
  43.   
  44.     <target name="build-war" depends="build-project">  
  45.         <war destfile="${ARCHIVE_DIR}/${warname}" webxml="WebContent/WEB-INF/web.xml">  
  46.             <webinf dir="WebContent/WEB-INF" />  
  47.             <zipfileset dir="src" prefix="WEB-INF/src" />  
  48.             <fileset dir="WebContent">  
  49.                 <include name="**/*" />  
  50.             </fileset>  
  51.             <lib dir="WebContent/WEB-INF/lib" />  
  52.             <classes dir="build/bin" />  
  53.         </war>  
  54.     </target>  
  55.   
  56. </project>  
另外,要发布到bluemix中去,本工程还配置了初始的参数

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. ---  
  2. declared-services:  
  3.   text-to-speech-service:  
  4.     label: text_to_speech  
  5.     plan: standard  
  6. applications:  
  7. - services:  
  8.   - text-to-speech-service  
  9.   name: TextToSpeechTest  <span style="font-family: Arial, Helvetica, sans-serif;">#改成你的Bluxmix中心上对应的web工程名</span>  
  10.   path: webApp.war #改成你的war包名,上传时这个注释要去掉  
  11.   memory: 512M  

现在来打包下:

打包后的输出路径:

(2)上传到个个Bluxmix中心

登陆

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. cf login  
  2. 输入用户名、邮箱、选择工程空间(记得选择你此次web项目所在的空间)  

上传

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. cf push TextToSpeechTest -p D:\marJee-workspace\text-to-speech-java-master\output\webApp.war -m 512M  


最后如果出现如下内容,表明上传成功且运行成功
当然,也可以到bluxmix中心去看


最后,打开网址:http://texttospeechtest.eu-gb.mybluemix.net/

点击Speak按钮,即可!注意,等待语音返回比较慢,请耐心等待!注意,等待语音返回比较慢,请耐心等待!注意,等待语音返回比较慢,请耐心等待!



本文工程下载:http://download.csdn.net/detail/evankaka/9427964

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值