微软(TTS)文本转语音服务API实现

这篇具有很好参考价值的文章主要介绍了微软(TTS)文本转语音服务API实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

此博客实现与java实现微软文本转语音(TTS)经验总结_java tts_${简简单单}的博客-CSDN博客之上,首先感谢博客源码的提供,本人在上面添加了一些详细的注释,方便大家跟好的理解和使用,毕竟我已经用原文调试了一下午才调通,一些细节的问题给大家标注出来,免得浪费大家的时间,下面直接开始代码吧!

首先大家需要去微软官网获取到密钥,方便调用时可以使用,大家注意看下图,我们一定要注意给我们分配到的区域,我这里是分配到eastus ,就是east us(美国东部)的意思,大家一定需要注意一下,后面会使用到的,然后终结点里面的地址就是我们获取token的地址

下面我们准备几个类,方便后面使用,大家把代码都复制到自己项目中,不要有遗漏:

package com.daoversal.util;

public class ByteArray {
    private byte[] data;
    private int length;
 
    public ByteArray(){
        length = 0;
        data = new byte[length];
    }
 
    public ByteArray(byte[] ba){
        data = ba;
        length = ba.length;
    }
 
    /**
    合并数组
     */
    public  void cat(byte[] second, int offset, int length){
 
        if(this.length + length > data.length) {
            int allocatedLength = Math.max(data.length, length);
            byte[] allocated = new byte[allocatedLength << 1];
            System.arraycopy(data, 0, allocated, 0, this.length);
            System.arraycopy(second, offset, allocated, this.length, length);
            data = allocated;
        }else {
            System.arraycopy(second, offset, data, this.length, length);
        }
 
        this.length += length;
    }
 
    public  void cat(byte[] second){
        cat(second, 0, second.length);
    }
 
    public byte[] getArray(){
        if(length == data.length){
            return data;
        }
 
        byte[] ba = new byte[length];
        System.arraycopy(data, 0, ba, 0, this.length);
        data = ba;
        return ba;
    }
 
    public int getLength(){
        return length;
    }
}
package com.daoversal.util;

import javax.net.ssl.HttpsURLConnection;
import java.net.URL;

public class HttpsConnection {
 
    public static HttpsURLConnection getHttpsConnection(String connectingUrl) throws Exception {
 
        URL url = new URL(connectingUrl);
        return (HttpsURLConnection) url.openConnection();
    }
}
package com.daoversal.util;

import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;

@Slf4j
public class XmlDom {
    public static String createDom(String locale, String genderName, String voiceName, String textToSynthesize){
        Document doc = null;
        Element speak, voice;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dbf.newDocumentBuilder();
            doc = builder.newDocument();
            if (doc != null){
                speak = doc.createElement("speak");
                speak.setAttribute("version", "1.0");
                speak.setAttribute("xml:lang", "en-US");
                voice = doc.createElement("voice");
                voice.setAttribute("xml:lang", locale);
                voice.setAttribute("xml:gender", genderName);
                voice.setAttribute("name", voiceName);
                voice.appendChild(doc.createTextNode(textToSynthesize));
                speak.appendChild(voice);
                doc.appendChild(speak);
            }
        } catch (ParserConfigurationException e) {
            log.error("Create ssml document failed: {}",e.getMessage());
            return null;
        }
        return transformDom(doc);
    }
 
    private static String transformDom(Document doc){
        StringWriter writer = new StringWriter();
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer;
            transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            transformer.transform(new DOMSource(doc), new StreamResult(writer));
        } catch (TransformerException e) {
            log.error("Transform ssml document failed: {}",e.getMessage());
            return null;
        }
        return writer.getBuffer().toString().replaceAll("\n|\r", "");
    }
}

 下面这个类我给大家重点讲一下,大家去下面网址看看自己的参数Text to speech API reference (REST) - Speech service - Azure AI services | Microsoft Learn

AUDIO_24KHZ_48KBITRATE_MONO_MP3 :语言类型,这个不重要,那个声音好听用那个,去下图找:

微软(TTS)文本转语音服务API实现,microsoft,开发语言,java

ACCESS_TOKEN_URI :就是本文章的第一张图里面,里面获取token的地址,直接将地址复制进来就好了。

API_KEY :自己的api key,就是密钥。

 TTS_SERVICE_URI : 这个地址一定要对应分配的区域才行,不然会报权限错误

Synthesis tts speech failed Server returned HTTP response code: 401 for URL: https://.........

我这里是 east us(美国东部),所以就使用美国东部里面的地址即可。

微软(TTS)文本转语音服务API实现,microsoft,开发语言,java

package com.daoversal.util;

public class TtsConst {
    /**
     * 音频合成类型(亲测这种效果最佳,其他的你自己去试试)
     * 里面有很多类型,可以去里面找自己需要的
     * https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech?tabs=streaming
     */
    public static final String AUDIO_24KHZ_48KBITRATE_MONO_MP3 = "audio-24khz-48kbitrate-mono-mp3";
    /**
     * 授权url   获取密钥页面 终结点 里面的地址,我们使用这个获取token
     */
    public static final String ACCESS_TOKEN_URI = "token获取地址";
    /**
     * api key
     */
    public static final String API_KEY = "自己的密钥";
    /**
     * tts服务url,这里一定要根据自己分配的地区找相应的地址才行
     */
    public static final String TTS_SERVICE_URI = "https://eastus.tts.speech.microsoft.com/cognitiveservices/v1/";


}

下面参数给大家讲一下:

textToSynthesize : 传入的合成语音文本内容

locale:语言类型,大家可以参考,中文在嵌入式语音里面,大家可以在两个页面找到自己需要的语言。

Embedded Speech - Speech service - Azure AI services | Microsoft Learn

Language support - Speech service - Azure AI services | Microsoft Learn

微软(TTS)文本转语音服务API实现,microsoft,开发语言,java

微软(TTS)文本转语音服务API实现,microsoft,开发语言,java

gender:为发声人性别,Male表示男性

 voiceName :发声者名称,大家可以去下图找出对应的,比如中文的话:

微软(TTS)文本转语音服务API实现,microsoft,开发语言,java

package com.daoversal.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import java.io.DataOutputStream;
import java.io.InputStream;

@Slf4j
@Component
public class TtsService {
 
    @Resource
    private Authentication authentication;

    /**
     * 合成音频
     * @param textToSynthesize 传入需要翻译的文本
     * @param locale    要合成的语言类型
     * @param gender    性别
     * @param voiceName 发音者名称
     * @return
     */
    public byte[] genAudioBytes(String textToSynthesize, String locale, String gender, String voiceName) {
        String accessToken = authentication.genAccessToken();
        if (StringUtils.isEmpty(accessToken)) {
            return new byte[0];
        }
        try {
            HttpsURLConnection webRequest = HttpsConnection.getHttpsConnection(TtsConst.TTS_SERVICE_URI);
            webRequest.setRequestProperty("Host", "eastus.tts.speech.microsoft.com");
            webRequest.setRequestProperty("Content-Type", "application/ssml+xml");
            webRequest.setRequestProperty("X-Microsoft-OutputFormat", TtsConst.AUDIO_24KHZ_48KBITRATE_MONO_MP3);
            webRequest.setRequestProperty("Authorization", "Bearer " + accessToken);
            webRequest.setRequestProperty("Ocp-Apim-Subscription-Key", TtsConst.API_KEY);
            webRequest.setRequestProperty("User-Agent", "Mozilla/5.0");
            webRequest.setRequestProperty("Accept", "*/*");
            webRequest.setDoInput(true);
            webRequest.setDoOutput(true);
            webRequest.setConnectTimeout(5000);
            webRequest.setReadTimeout(300000);
            webRequest.setRequestMethod("POST");
 
            String body = XmlDom.createDom(locale, gender, voiceName, textToSynthesize);
            if (StringUtils.isEmpty(body)) {
                return new byte[0];
            }
            byte[] bytes = body.getBytes();
            webRequest.setRequestProperty("content-length", String.valueOf(bytes.length));
            webRequest.connect();
            DataOutputStream dop = new DataOutputStream(webRequest.getOutputStream());
            dop.write(bytes);
            dop.flush();
            dop.close();
            InputStream inSt = webRequest.getInputStream();
            ByteArray ba = new ByteArray();
            int rn2 = 0;
            int bufferLength = 4096;
            byte[] buf2 = new byte[bufferLength];
            while ((rn2 = inSt.read(buf2, 0, bufferLength)) > 0) {
                ba.cat(buf2, 0, rn2);
            }
            inSt.close();
            webRequest.disconnect();
            return ba.getArray();
        } catch (Exception e) {
            log.error("Synthesis tts speech failed {}", e.getMessage());
        }
        return null;
    }

}
package com.daoversal.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

/**
 * 此类获取token,每次调用都需要使用到token的
 * token的有效期是10分钟,但是不建议大家10分钟调一次,免得使用了失效的token
 */
@Component
@Slf4j
public class Authentication {

    @Autowired
    private RedissonClient redisson;

    public String genAccessToken() {
        InputStream inSt;
        HttpsURLConnection webRequest;
        try {
            //先从redis里面取缓存的token,如果没有就远程拉取,有的话就直接使用,大家可根据自己的业务调整
            Object ob = redisson.getBucket("accessToken").get();
            String accessToken = ob == null ? null : ob.toString();
            if (StringUtils.isEmpty(accessToken)) {
                webRequest = HttpsConnection.getHttpsConnection(TtsConst.ACCESS_TOKEN_URI);
                webRequest.setDoInput(true);
                webRequest.setDoOutput(true);
                webRequest.setConnectTimeout(5000);
                webRequest.setReadTimeout(5000);
                webRequest.setRequestMethod("POST");
 
                byte[] bytes = new byte[0];
                webRequest.setRequestProperty("content-length", String.valueOf(bytes.length));
                //api的key,取微软官网获取
                webRequest.setRequestProperty("Ocp-Apim-Subscription-Key", TtsConst.API_KEY);
                webRequest.connect();
 
                DataOutputStream dop = new DataOutputStream(webRequest.getOutputStream());
                dop.write(bytes);
                dop.flush();
                dop.close();
 
                inSt = webRequest.getInputStream();
                InputStreamReader in = new InputStreamReader(inSt);
                BufferedReader bufferedReader = new BufferedReader(in);
                StringBuilder strBuffer = new StringBuilder();
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    strBuffer.append(line);
                }
 
                bufferedReader.close();
                in.close();
                inSt.close();
                webRequest.disconnect();
 
                accessToken = strBuffer.toString();
                //获取到了token,缓存到redis里面,5分钟失效
                redisson.getBucket("accessToken").set(accessToken,5L, TimeUnit.MINUTES);
                //设置accessToken的过期时间为5分钟
                log.info("New tts access token {}", accessToken);
            }
            return accessToken;
        } catch (Exception e) {
            log.error("Generate tts access token failed {}", e.getMessage());
        }
        return null;
    }
}

最后就是调用了,大家可以测试了:

package com.daoversal.web;


import com.daoversal.framework.http.Response;
import com.daoversal.task.DvWeekCountTask;
import com.daoversal.task.RechargeTask;
import com.daoversal.task.UserGradeCountTask;
import com.daoversal.task.WindControlMsgTask;
import com.daoversal.util.TtsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import okhttp3.*;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * <p>
 * 套餐价值释放记录表 前端控制器
 * </p>
 *
 * @author HayDen
 * @since 03 22 10:44:13
 */
@RestController
@RequestMapping("/test")
@Api(value = "test")
public class TestController {

    @Resource
    private TtsService testService;

    @PostMapping("/ttsService")
    @ApiOperation(value = "获取ttsService", httpMethod = "POST" )
    public void ttsService(String text) {
       // byte[] bte = testService.genAudioBytes(res,"en-US","Male","en-US-JennyNeural");
        byte[] bte = testService.genAudioBytes(text,"zh-CN","Male","zh-CN-YunxiNeural");
        String value = "hllo.mp3";
        convertByteArrayToFile(bte,value);
        System.out.println("213213123");
    }

    /**
     * 此文件是将byte[] 转换成文件存储到指定路径的
     * @param arr
     * @param value
     */
    public static void convertByteArrayToFile(byte[] arr,String value) {
        try (
                BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(arr));
                //这里是转换以后的文件存储的路径
                FileOutputStream fileOutputStream = new FileOutputStream("/Users/recovery/Downloads/"+value);
                BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream)
        ) {
            int data;
            while ((data = bis.read()) != -1) {
                bos.write(data);
            }
            bos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

最后大家需要注意一下就是如果你选的是英文en-US,但是输入的文本是中文的话他是不会翻译的,所以大家一定要注意自己的语言类型不要弄错了,如果有疑问可以留言哦,我看到肯定会毫无保留的给大家说明的。文章来源地址https://www.toymoban.com/news/detail-725252.html

到了这里,关于微软(TTS)文本转语音服务API实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [chatgpt+Azure]unity AI二次元小女友之使用微软Azure服务实现RestfulApi->语音识别+语音合成

            如题所述,这个小项目是在unity引擎端,使用了chatgpt+微软azure的一个AI二次元女友对话的项目,实现原理也比较简单,即在unity端实现AI二次元女友的交互界面,接入chatgpt-3.5-turbo的api接口,借助chatgpt的自然语言生成能力,作为这个项目的聊天引擎。聊天功能也比较

    2024年02月04日
    浏览(33)
  • [Unity+OpenAI TTS] 集成openAI官方提供的语音合成服务,构建海王暖男数字人

            最近openAI官方发布了很多新功能,其中就包括了最新发布的TTS语音合成服务的api接口。说到这个语音合成接口,大家可能会比较陌生,但是说到chatgpt官方应用上的聊天机器人,那个台湾腔的海王暖男的声音,可能就有印象了吧。那么从官方文档中,可以发现,openA

    2024年02月04日
    浏览(30)
  • 微软认知服务-语音识别相关

    在csdn上面看到有微软认知服务的试用,之前正好因为一些需求,接触到了这块的一些东西,正好总结一下,之前使用的是国外的账号,这个登录以后看到是国内世纪互联运营的国内的azure,在识别这块应该针对中文方面有更好的适配 0元试用微软 Azure人工智能认知服务,精美

    2024年02月14日
    浏览(30)
  • Android快速集成微软语音服务(Azure认知服务)

    在网上溜了一圈,发现使用微软语音服务(Azure)的文章好少,为之感叹,在国内,百度语音、讯飞语音算是前沿语音技术,使用的公司和人自然不少,不过,在国际语言,小语种这块,还需要努力。刚开始,我也想使用百度语音翻译来着,后面发现集成好麻烦,API请求参数

    2024年02月04日
    浏览(83)
  • 如何注册微软Azure并获取语音合成服务?

    按步骤,一步步来。 使用条件,以下可选: 1、有信用卡 2、有学生邮箱、学校邮箱。 步骤: 1、打开地址,去注册。 信用卡注册: 文本转语音 – 真实 AI 语音生成器 | Microsoft Azure 学生邮箱: 面向学生的 Azure - 免费帐户额度 | Microsoft Azure 2、注册后去后台,打开语音服务。 后

    2024年02月03日
    浏览(34)
  • edge-tts微软文本转语音库,来听听这些语音是否很熟悉?

    上期图文教程,我们分享了Azure机器学习的文本转语音的账号申请与API申请的详细步骤,也介绍了基于python3实现Azure机器学习文本转语音功能的代码实现过程,虽然我们可以使用Azure账号免费提供一年的试用期,但是毕竟是要付费的,我们的API也无法长期使用,好在微软发布了

    2024年02月07日
    浏览(38)
  • 我开发了一个【免费】使用微软的文字转语音服务的js库

    尝试过各种TTS的方案,一番体验下来,发现微软才是这个领域的王者,其 Azure文本转语音 服务的转换出的语音效果最为自然,但Azure是付费服务,注册操作付费都太麻烦了。但在其官网上竟然提供了一个 完全体 的演示功能,能够完完整整的体验所有角色语音,说话风格…

    2024年02月05日
    浏览(35)
  • 用python协写个调用移动语音通知API的服务

    要实现这个功能,你需要使用Python中的第三方库,如 requests 和 datetime 库。同时,你需要先注册移动语音通知API的账号并获取API密钥。 以下是一个基本的Python代码示例,它使用移动语音通知API来发送语音通知:

    2024年02月13日
    浏览(22)
  • 微软/edge文本转语音API接口

    类型:websocket 类型:websocket

    2023年04月16日
    浏览(24)
  • C#调用微软api文本转语音

    目录 1.注册微软云服务,搭建文本转语音标准应用(每月500万字免费好像) 2.Visual studio使用nuget给程序安装Microsoft.CognitiveServices.Speech框架  3.引用命名空间 4.文本转语音参考代码 5.文本转语音下载到本地参考代码

    2024年02月12日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包