通过参考官方TTS REST API文档,我将用密钥交换一个令牌,并使用该令牌将文本转换为语音。我会得到一个音频数据的字节数组,然后我使用JLayer来播放音频。
这是我的示例:
public class TestTTS {
static String key = "f1a0ea***********fa5e35";
static String tokenEndpoint = "https://southeastasia.api.cognitive.microsoft.com/sts/v1.0/issueToken";
static String serviceEndpoint = "https://southeastasia.tts.speech.microsoft.com/cognitiveservices/v1";
public static String GetToken(){
Map<String, String> headers = new HashMap<>();
headers.put("Ocp-Apim-Subscription-Key",key);
headers.put("Content-Type","application/x-www-form-urlencoded");
try(CloseableHttpClient client = HttpClients.createDefault()){
HttpPost post = new HttpPost(new URI(tokenEndpoint));
for (String key : headers.keySet()) {
post.setHeader(key, headers.get(key));
}
post.setEntity(new StringEntity(""));
CloseableHttpResponse result = client.execute(post);
return EntityUtils.toString(result.getEntity());
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public static byte[] GetAudio(String token) {
String content = "<speak version='1.0' xml:lang='en-US'><voice xml:lang='en-US' xml:gender='Female' name='en-US-JessaRUS'>Microsoft Speech Service Text-to-Speech API</voice></speak>";
Map<String, String> headers = new HashMap<>();
headers.put("Authorization","Bearer " + token);
headers.put("Content-Type","application/ssml+xml");
headers.put("X-Microsoft-OutputFormat"," audio-16khz-64kbitrate-mono-mp3");
try(CloseableHttpClient client = HttpClients.createDefault()){
HttpPost post = new HttpPost(new URI(serviceEndpoint));
for (String key : headers.keySet()) {
post.setHeader(key, headers.get(key));
}
post.setEntity(new StringEntity(content));
CloseableHttpResponse result = client.execute(post);
byte[] bytes = EntityUtils.toByteArray(result.getEntity());
return bytes;
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new byte[0];
}
public static void main(String[] args) {
byte[] bytes = GetAudio(GetToken());
System.out.println(bytes.length);
try(InputStream is = new ByteArrayInputStream(bytes)){
Player player=new Player(is);
player.play();
} catch (IOException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
对于带有 mp3Plugin 的 JMF,我将音频数据保存到一个临时文件中,然后播放。
public static void PlayWithJMF(){
Format input1 = new AudioFormat(AudioFormat.MPEGLAYER3);
Format input2 = new AudioFormat(AudioFormat.MPEG);
Format output = new AudioFormat(AudioFormat.LINEAR);
PlugInManager.addPlugIn(
"com.sun.media.codec.audio.mp3.JavaDecoder",
new Format[]{input1, input2},
new Format[]{output},
PlugInManager.CODEC
);
try{
FileOutputStream fos = new FileOutputStream("tmp.mp3");
byte[] bytes = GetAudio(GetToken());
System.out.println(bytes.length);
fos.write(bytes);
fos.flush();
fos.close();
File file = new File("tmp.mp3");
javax.media.Player player = Manager.createPlayer(new MediaLocator(file.toURI().toURL()));
player.start();
while(true){
if(player.getState() == 500){
player.close();
break;
}
Thread.sleep(500);
}
}catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoPlayerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}