使用Powershell调用讯飞在线语音合成


$csCode = @"
using System;  
using System.IO;
using System.Text;
using System.Runtime.InteropServices;

namespace Test
{
	public class MultMedia
	{
		[DllImport("winmm.dll",EntryPoint="mciSendStringA", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true, CallingConvention=CallingConvention.Cdecl)]
		private static extern int mciSendString(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);  
		[DllImport("winmm.dll",EntryPoint="mciGetErrorStringA", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true, CallingConvention=CallingConvention.Cdecl)]
		private static extern int mciGetErrorString(int nError, ref byte strErrorText, int nErrorText);  
		/// 调用系统麦克风,设置音频参数,开始录音
		public static void StartRecord() {  
			mciSendString("open new type waveaudio alias recSound", "", 0, 0);   
			string strCMD = "set recSound time format ms";
			strCMD += " bitspersample 16";
			strCMD += " channels 1";
			strCMD += " samplespersec 16000";
			strCMD += " bytespersec 32000";			// bytespersec = bitspersample*channels*samplespersec/8
			strCMD += " alignment 2";				// alignment = bitspersample*channels/8
			strCMD += " format tag pcm";
			mciSendString(strCMD, "", 0, 0);
			mciSendString("record recSound", "", 0, 0);   
		}
		/// 停止录音并保存音频数据至指定文件
		public static void SaveRecord(string strFileName) {  
			string strCMD = "save recSound " + strFileName + " wait";
			mciSendString(strCMD, "", 0, 0);  
			mciSendString("close recSound", "", 0, 0);  
		}
		/// 播放WAV文件
		public static void Play(string strFileName) {
			int nRet = 0;
			byte[] szError = new byte[255];

			string strCMD = "open " + strFileName + " type waveaudio alias playSound";
			nRet = mciSendString(strCMD, "", 0, 0);
			if (nRet != 0) { 
				Console.WriteLine("Open error code : {0}", nRet); 
				mciGetErrorString(nRet, ref szError[0], 255);
				Console.WriteLine("Description : {0}", System.Text.Encoding.Default.GetString(szError, 0, szError.Length));
				return;
			}

			
			nRet = mciSendString("play playSound wait", "", 0, 0);
			if (nRet != 0) { 
				Console.WriteLine("Play error code : {0}", nRet); 
				mciGetErrorString(nRet, ref szError[0], 255);
				Console.WriteLine("Description : {0}", System.Text.Encoding.Default.GetString(szError, 0, szError.Length));
				return;
			}

			nRet = mciSendString("close playSound", "", 0, 0);
			if (nRet != 0) { 
				Console.WriteLine("Close error code : {0}", nRet); 
				mciGetErrorString(nRet, ref szError[0], 255);
				Console.WriteLine("Description : {0}", System.Text.Encoding.Default.GetString(szError, 0, szError.Length));
				return;
			}
		}
	}
}
"@
Add-Type -TypeDefinition $csCode
function pause() {
	Write-Host "Press any key to continue..."
	[Console]::ReadKey() | Out-Null
}

# 定义使用常量
$URL = "https://api.xfyun.cn/v1/service/v1/tts"
$AUE = "raw"
$APPID = "YOUR_APPID"
$API_KEY = "YOUR_API_KEY"

$arrayAgents = $Null
$nAgentNum	 = 0
$strContent	 = ""

# 组装网页请求Header
function getHeader() {
	# 获取当前世界标准时间与1970年初的时间差总秒数
	$dtNow = Get-Date
	$dtDiff = $dtNow.ToUniversalTime() - $(Get-Date -Date "1970/01/01 00:00:00")
	$curTime = [Math]::Floor($dtDiff.TotalSeconds)
	Write-Host $curTime

	# 组装配置信息
	$param = "{`"aue`":`"$AUE`",`"auf`":`"audio/L16;rate=16000`",`"voice_name`":`"$VOICE_NAME`",`"engine_type`":`"intp65`"}"
	Write-Host $param

	$oUTF8 = New-Object -TypeName System.Text.UTF8Encoding
	$oMD5  = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider

	# 配置信息BASE64编码
	$strBase64 		= [Convert]::ToBase64String($oUTF8.GetBytes($param))
	Write-Host `$strBase64 : $strBase64

	# API_KEY+时间差+BASE64密文进行UTF8编码备用
	$strUTF8Con 	= $API_KEY + $curTime + $strBase64
	$arrayUTF8Con 	= $oUTF8.GetBytes($strUTF8Con)
	Write-Host `$strUTF8Con : $strUTF8Con
	Write-Host `$arrayUTF8Con : $arrayUTF8Con

	# 计算API_KEY+时间差+配置信息BASE64密文的MD5值
	$arrayBinCon 	= $oMD5.ComputeHash($arrayUTF8Con)
	$checkSum 		= [BitConverter]::ToString($arrayBinCon) -Replace "-", ""
	$checkSum 		= $checkSum.ToLower()
	Write-Host `$checkSum : $checkSum

	# 按需求组合请求Header的HASH表(一一对应相关变量)
	$header = @{
			"X-CurTime" = $curTime
			"X-Param" = $strBase64
			"X-Appid" = $APPID
			"X-CheckSum" = $checkSum
			"X-Real-Ip" = "127.0.0.1"
			"Content-Type" = "application/x-www-form-urlencoded; charset=utf-8"
	}
	#Write-Host $header
	return $header
}

# 组装合成语音文本的HASH表,仅TEXT一个字典
function getBody($text) {
	$data = @{
		#"text" =  [Web.HttpUtility]::UrlEncode($text)	#技术文档里面说需要URLENCODE编码,实际上不需要
		"text" =  $text
	}
	#Write-Host "转化的内容为 : $text"
	return $data
}

# 将返回音频流写入对应文件
function writeFile($file, $content){
	#param ([string] $file, [Byte[]] $content)
	[System.IO.File]::WriteAllBytes($file, $content)
}

# 选择发音角色
function getAgentList() {
	$oVoice1 = @{"index" = "1"; "name" = "讯飞小燕"; "type" = "普通话"; "nameID" = "xiaoyan"}
	$oVoice2 = @{"index" = "2"; "name" = "讯飞许久"; "type" = "普通话"; "nameID" = "aisjiuxu"}
	$oVoice3 = @{"index" = "3"; "name" = "讯飞小萍"; "type" = "普通话"; "nameID" = "aisxping"}
	$oVoice4 = @{"index" = "4"; "name" = "讯飞小婧"; "type" = "普通话"; "nameID" = "aisjinger"}
	$oVoice5 = @{"index" = "5"; "name" = "讯飞许小宝"; "type" = "普通话"; "nameID" = "aisbabyxu"}
	$oVoice6 = @{"index" = "6"; "name" = "讯飞小东"; "type" = "山东话"; "nameID" = "x_xiaodong"}
	$oVoice7 = @{"index" = "7"; "name" = "讯飞小王"; "type" = "湖北话"; "nameID" = "x_xiaowang"}
	$oVoice8 = @{"index" = "8"; "name" = "讯飞萌萌-中立"; "type" = "普通话"; "nameID" = "x_mengmengneutral"}
	$oVoice9 = @{"index" = "9"; "name" = "讯飞宁宁"; "type" = "普通话"; "nameID" = "x_ningning"}
	$oVoice10 = @{"index" = "10"; "name" = "讯飞小南"; "type" = "普通话"; "nameID" = "x_xiaonan"}
	$oVoice11 = @{"index" = "11"; "name" = "讯飞玲姐姐"; "type" = "普通话"; "nameID" = "x_xiaoling"}
	$oVoice12 = @{"index" = "12"; "name" = "讯飞小坤"; "type" = "河南话"; "nameID" = "x_xiaokun"}
	$oVoice13 = @{"index" = "13"; "name" = "讯飞小梅"; "type" = "广东话"; "nameID" = "x_xiaomei"}
	$oVoice14 = @{"index" = "14"; "name" = "讯飞小瑞"; "type" = "普通话"; "nameID" = "x_xiaonuo_novel"}
	$oVoice15 = @{"index" = "15"; "name" = "讯飞小师"; "type" = "普通话"; "nameID" = "x_xiaoshi_cts"}
	$oVoice16 = @{"index" = "16"; "name" = "讯飞小梦"; "type" = "普通话"; "nameID" = "x_xiaomeng"}
	$oVoice17 = @{"index" = "17"; "name" = "讯飞小施"; "type" = "普通话"; "nameID" = "x_xiaoshi"}
	$oVoice18 = @{"index" = "18"; "name" = "讯飞小强"; "type" = "湖南话"; "nameID" = "x_xiaoqiang"}
	$oVoice19 = @{"index" = "19"; "name" = "讯飞一峰"; "type" = "普通话"; "nameID" = "x_yifeng"}
	$oVoice20 = @{"index" = "20"; "name" = "讯飞小媛"; "type" = "普通话"; "nameID" = "x_xiaoyuan"}
	$oVoice21 = @{"index" = "21"; "name" = "讯飞晓倩"; "type" = "东北话"; "nameID" = "x_xiaoqian"}
	$oVoice22 = @{"index" = "22"; "name" = "讯飞小莹"; "type" = "陕西话"; "nameID" = "x_xiaoying"}
	$oVoice23 = @{"index" = "23"; "name" = "讯飞小乔"; "type" = "普通话"; "nameID" = "x_xiaoqiao"}
	$oVoice24 = @{"index" = "24"; "name" = "讯飞小瑶"; "type" = "普通话"; "nameID" = "x_xiaoyao"}
	$oVoice25 = @{"index" = "25"; "name" = "讯飞晓燕"; "type" = "普通话"; "nameID" = "x_xiaoyan"}
	$oVoice26 = @{"index" = "26"; "name" = "讯飞萌萌-悲伤"; "type" = "普通话"; "nameID" = "x_mengmengsad"}
	$oVoice27 = @{"index" = "27"; "name" = "讯飞小春"; "type" = "普通话"; "nameID" = "x_mengchun"}
	$oVoice28 = @{"index" = "28"; "name" = "讯飞马叔"; "type" = "普通话"; "nameID" = "x_laoma"}
	$oVoice29 = @{"index" = "29"; "name" = "讯飞小蓉"; "type" = "四川话"; "nameID" = "x_xiaorong"}
	$oVoice30 = @{"index" = "30"; "name" = "讯飞芳芳"; "type" = "普通话"; "nameID" = "x_xiaofang"}
	$oVoice31 = @{"index" = "31"; "name" = "讯飞晓峰"; "type" = "普通话"; "nameID" = "x_xiaofeng"}
	$oVoice32 = @{"index" = "32"; "name" = "讯飞小魏"; "type" = "普通话"; "nameID" = "x_xiaowei"}
	$oVoice33 = @{"index" = "33"; "name" = "讯飞楠楠"; "type" = "普通话"; "nameID" = "x_nannan"}
	$oVoice34 = @{"index" = "34"; "name" = "讯飞小肥"; "type" = "安徽合肥话"; "nameID" = "x_xiaofei"}
	$oVoice35 = @{"index" = "35"; "name" = "讯飞小雪"; "type" = "普通话"; "nameID" = "x_xiaoxue"}
	$oVoice36 = @{"index" = "36"; "name" = "讯飞晓琳"; "type" = "台湾普通话"; "nameID" = "x_xiaolin"}
	$oVoice37 = @{"index" = "37"; "name" = "讯飞小包"; "type" = "内蒙古方言"; "nameID" = "x_xiaobao"}
	$oVoice38 = @{"index" = "38"; "name" = "讯飞小华"; "type" = "普通话"; "nameID" = "x_xiaoyang_story"}
	$oVoice39 = @{"index" = "39"; "name" = "讯飞宋宝宝"; "type" = "普通话"; "nameID" = "x_xiaosong"}
	$oVoice40 = @{"index" = "40"; "name" = "讯飞玉儿"; "type" = "台湾普通话"; "nameID" = "x_yuer"}
	$oVoice41 = @{"index" = "41"; "name" = "讯飞萌萌-高兴"; "type" = "普通话"; "nameID" = "x_mengmenghappy"}

	$arrayVoices = @($oVoice1, $oVoice2, $oVoice3, $oVoice4, $oVoice5, $oVoice6, $oVoice7, $oVoice8,
			$oVoice9, $oVoice10, $oVoice11, $oVoice12, $oVoice13, $oVoice14, $oVoice15, $oVoice16,
			$oVoice17, $oVoice18, $oVoice19, $oVoice20, $oVoice21, $oVoice22, $oVoice23, $oVoice24,
			$oVoice25, $oVoice26, $oVoice27, $oVoice28, $oVoice29, $oVoice30, $oVoice31, $oVoice32,
			$oVoice33, $oVoice34, $oVoice35, $oVoice36, $oVoice37, $oVoice38, $oVoice39, $oVoice40,
			$oVoice41)

	return $arrayVoices
}

# 从参数或用户输入取得发音角色
function chooseAct() {
	Write-Host "请选择你要发音的角色 : "
	$arrayAgents | %{
		Write-Host "$($_["index"]). $($_["name"])-$($_["type"])"
	}
	$nRetAct = Read-Host "角色编号"
	return $nRetAct
}

function main() {
	$arrayAgents = getAgentList
	$VOICE_NAME = ""
	if ( $nAgentNum -eq 0 ) {
		$nAgentNum = chooseAct
	}
	do {
		clear
		$bFound = $false
		$arrayAgents | %{
			if ( $nAgentNum -eq $_["index"] ) {
				$bFound = $true
				$VOICE_NAME = "$($_["nameID"])"
				Write-Host `$VOICE_NAME : $VOICE_NAME
				break
			}
		}
		if ( $bFound ) { 
			break 
		} else {
			Write-Host "错误编号,请重新输入..."
			pause
		}
		$nAgentNum = chooseAct
	} while ($true)

	# 从参数或用户输入取得合成文本
	$strConTmp = ""
	if ( $strContent -ne "" ) {
		$strConTmp = $strContent
	} else {
		$strConTmp = Read-Host "Input translated text"
	}

	# 组装请求Header
	$oHeader 	= getHeader
	# 转换成JSON格式便于输出调试
	$strHeader	= ConvertTo-Json $oHeader
	# 组装请求内容
	$oBody   	= getBody $strConTmp
	# 转换成JSON格式便于输出调试
	$strBody 	= ConvertTo-Json $oBody
	Write-Host "`n`n`n"

	try {
		# 请求服务接口,传入需求数据
		Write-Host `$oPage = Invoke-WebRequest `-URI $URL `-Method Post `-Headers $strHeader `-Body $strBody
		$oPage = Invoke-WebRequest -URI "$URL" -Method Post -Headers $oHeader -Body $oBody
		#$oPage
		Write-Host "`n`n`n"

		# 取出内容分析返回格式,若为音频格式继续
		$contentType = $oPage.Headers['Content-Type']
		if ( $contentType -eq "audio/mpeg") {
			# 返回SID值,作为文件名
			$sid = $oPage.Headers['sid']
			# WAVE格式与MP3格式处理
			$strAudio = ""
			if ( !(Test-Path "audio") ) { mkdir "audio" }
			if ($AUE -eq "raw") {
				$strAudio = "$pwd\audio\$($sid).wav"
				writeFile -file $strAudio -content $($oPage.Content)
			} else {
				$strAudio = "$pwd\audio\$($sid).mp3"
				writeFile -file $strAudio -content $($oPage.Content)
			}
			Write-Host "success, sid = $sid" 

			#ffplay -hide_banner -autoexit -i $strAudio -showmode 1
			[Test.MultMedia]::Play($strAudio)

		} else {
			# 错误请求,输出返回结果
			Write-Host "Execute error, the detail is : $($oPage.RawContent)"
		}
	} catch {
		# 例外捕获
		Write-Host Erron on : $Error[0]
	}
}

if ($args.Count -ge 1) {
	$strContent = $args[0]
	Write-Host "获取内容参数 : $strContent"
}
if ($args.Count -ge 2) {
	$nAgentNum  = $args[1]
	Write-Host "获取角色参数 : $nAgentNum"
}
main
pause

注:请至 http://www.xfyun.cn注册账号并申请APPID

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注