使用微软云人工智能,合成带感情的语音

以前公司下达了一个需求,要求用语音做广播,因为广播里面包含姓名,所以不能难以直接录制,需要使用合成语音。

一开始考虑到时间以及优先级问题,这边使用了百度的合成语音。

但是百度语音相对僵硬,而且没有感情,效果不甚满意。

不久前时间相对充沛,这边就使用了觉得最完美的方案——使用微软云的人工智能合成语音。

因为这个语音可以设置感情,没有机器合成那种僵硬的感觉,可以说是比真人还真人。

微软云合成语音demo网站:https://azure.microsoft.com/zh-cn/services/cognitive-services/text-to-speech/

感觉确实有需要的话,接下来就应该创建微软云账号,开始使用了,可以参考这个视频:https://www.bilibili.com/video/av670457802

不过要注意一点,创建微软云账号,需要绑定一张visa卡。如果没有的话,可以淘宝或者申请微软云学生账号。

申请微软云学生账号:https://www.daniao.org/6693.html

创建好微软云合成语音服务之后,就可以直接使用了。

文档地址:https://docs.microsoft.com/zh-cn/azure/cognitive-services/speech-service/get-started-text-to-speech?tabs=script%2Cwindowsinstall&pivots=programming-language-javascript

收费:在这里插入图片描述
每个月都有25万字的合成额度,如果需求量不大的话,已经够用了。如果需求量大,可以将通用的语音保存到服务器,将不通用项,如姓名,以单字的形式,请求后再存入服务器。每次访问时,先检查服务器存不存在这个字,如没有再请求api接口。

下面是简单使用的具体代码:

微软语音合成(人工智能)示例
	<script type="text/javascript">
		const sdk = SpeechSDK
		var synthesizer = null;

		/**
		 * 初始化微软语音
		 */
		function synthesizeMsSpeech() {
			const speechConfig = sdk.SpeechConfig.fromSubscription("你的密匙", "你的地区,如 eastus 不能输入中文");
			synthesizer = new sdk.SpeechSynthesizer(speechConfig);
		}

		/**
		 * 使用微软语音说话
		 * @param {Object} word
		 */
		function msSpeek(text) {
			//微软人工智能语音,需要使用xml字符串做配置
			let ssml = `<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis"
			    xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="en-US">
			  <voice name="zh-cn-XiaoxiaoNeural">
			    <mstts:express-as style="cheerful">
			      ${text}
			    </mstts:express-as>
			  </voice>
			</speak>`
			synthesizer.speakSsmlAsync(
				ssml,
				result => {
					if (result.errorDetails) {
						console.error(result.errorDetails);
					} else {
						// console.log(JSON.stringify(result));
					}
					synthesizer.close();
				},
				error => {
					console.log(error);
					synthesizer.close();
				});
		}

		synthesizeMsSpeech();
		msSpeek("你好,我是你的优乐美!")
	</script>
</body>

密匙就不解释了,微软云控制台可以看到,地区可以选eastus eastus2,以及另外几个, 具体看控制台上显示的地区

另外为方便理解,附带一个带界面的语音合成网页:


欢快 闲聊 冷静 生气 紧张 哭泣 轻蔑 严肃 亲切 温和 伤感 客服 数字助理 新闻
		</select>
		<br>
		<br>
		<button type="button" onclick="clickPlayBtn()">播放</button>
		<button type="button" onclick="clickDownBtn()">下载</button>
	</div>
	<!-- 去除语音直接播放的sdk。在sdi.min.js,搜索play(),去除第二个play,这样不会输入到流的时候,依然先自动播放语音,形成干扰 -->
	<script src="static/js/microsoft.speech.sdk.1.js"></script>

	<script type="text/javascript">
		const sdk = SpeechSDK
		var synthesizer = null;
		
		//还有很多种
		const STYLE = {
			cheerful: "cheerful", //欢快
			chat: "chat", //闲聊
			calm: "calm", //冷静
			angry: "angry", //生气
			fearful: "fearful" //紧张
		}

		/**
		 * 初始化微软语音
		 */
		function synthesizeMsSpeech() {
			const speechConfig = sdk.SpeechConfig.fromSubscription("你的微软云密匙", "你的地区,如eastus");
			synthesizer = new sdk.SpeechSynthesizer(speechConfig);
		}

		/**
		 * 请求微软语音
		 * @param {Object} text
		 */
		function requestMsAudio(text, style="cheerful") {
			return new Promise((resolve, reject) => {
				let xmlObj = `<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis"
				    xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="en-US">
				  <voice name="zh-cn-XiaoxiaoNeural">
				    <mstts:express-as style="${style}">
				      ${text}
				    </mstts:express-as>
				  </voice>
				</speak>`

				const ssml = xmlObj;
				synthesizer.speakSsmlAsync(
					ssml,
					result => {
						// synthesizer.close();  //关闭后,会只获取一轮
						if (result.errorDetails) {
							console.error(result.errorDetails);
							reject(result)
						} else {
							let arrayBuffer = result.audioData
							let blob = new Blob([arrayBuffer], {
								type: 'autio/wave'
							});
							var src = URL.createObjectURL(blob);
							resolve(src)
						}
					},
					error => {
						console.log(error);
						reject(error)
						// synthesizer.close();
					});
			})
		}


		/**
		 * 使用微软语音说话
		 * @param {Object} text
		 */
		function msSpeek(text, style="cheerful") {
			return new Promise((resolve, reject) => {
				requestMsAudio(text, style).then((src) => {
					var mp3 = new Audio(src);
					//播放完之后,执行事件
					mp3.addEventListener("ended", () => {
						resolve();
					})
					mp3.play().catch(playError); //播放语音
				});
			})
		}
		
		/**
		 * 合并播放,先播放完一个,再播放另一个
		 * @param {Object} src 资源链接
		 * @param {Object} text 要生成的文字
		 */
		function mergeSpeek(src, text, style="cheerful"){
			return new Promise((resolve, reject) => {
				requestMsAudio(text, style).then((msSrc) => {
					playAudio(src).then(()=>{
						var mp3 = new Audio(msSrc);
						//播放完之后,执行事件
						mp3.addEventListener("ended", () => {resolve();})
						mp3.play().catch(playError); //播放语音
					})
				});
			})
		}
		
		/**
		 * 下载微软语音
		 * @param {Object} text
		 */
		function msDownload(text, style) {
			return new Promise((resolve, reject) => {
				requestMsAudio(text, style).then((src) => {
					const pattern=/[`~!@#$^&*()=|{}':;',\\\[\]\.<>\/?~!@#¥……&*()——|{}【】';:""'。,、?\s]/g;
					let name = text.replace(pattern," ");
					_download(src, name +".wav")
				});
			})
		};

		/**
		 * 播放音频,then为播放完后的回调
		 * @param {Object} src
		 */
		function playAudio(src) {
			return new Promise((resolve, reject) => {
				var mp3 = new Audio(src);
				//播放完之后,执行事件
				mp3.addEventListener("ended", () => {
					resolve();
				})
				mp3.play().catch(playError); //播放语音
			})
		}
		
		
		/**
		 * 播放失败后的统一回调
		 */
		const playError = function(){
			console.error("播放失败,播放前,请先点击页面,以允许播放。")
		}
		
		
		// 下载
		function _download(src, filename) {
			var eleLink = document.createElement('a');
			eleLink.download = filename;
			eleLink.style.display = 'none';
			// 字符内容转变成blob地址 
			eleLink.href = src;
			// 自动触发点击 
			document.body.appendChild(eleLink);
			eleLink.click();
			// 然后移除 
			document.body.removeChild(eleLink);
		};
		
		synthesizeMsSpeech();
		
		/**
		 * 点击下载后触发
		 */
		function clickPlayBtn(){
			let text = document.getElementById("mainTxt").value;
			let style = document.getElementById("style").value
			if(text.length > 0){
				msSpeek(text, style)
			}
		}
		
		/**
		 * 点击下载后触发
		 */
		function clickDownBtn(){
			let text = document.getElementById("mainTxt").value;
			let style = document.getElementById("style").value
			if(text.length > 0){
				msDownload(text, style)
			}
		}
	</script>
</body>
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值