通过 cURL、Postman、Java SDK 和 Python 示例调用语音识别与语音合成服务,完成请求发送、结果获取和音频保存。
前提条件
按照 快速开始完成服务开通、项目创建和访问凭证准备。根据要调用的服务配置项目模型,识别模型的语种和采样率需与输入音频一致。
语音识别和语音合成示例使用项目 Appkey 与 NLS Token;Token 获取方法请参见通过 SDK 获取 Token。Python 录音文件识别使用 AccessKey 对请求签名,不使用 NLS Token。优先使用已授权的 RAM 用户 AccessKey,不在代码中硬编码凭证。
调用可能产生费用,计费规则请参见计费项。
选择示例
|
功能 |
调用方式 |
用途 |
|
cURL / Postman |
识别不超过 60 秒的本地音频。 |
|
|
Java |
分块发送音频流,按句获取识别结果。 |
|
|
Python |
通过音频 URL 提交异步任务,轮询获取结果。 |
|
|
Java |
将文本合成为 WAV 文件。 |
配置访问参数
在终端或 IDE 的运行配置中设置环境变量。以下命令使用 Bash 语法;Windows 环境可在系统或 IDE 中设置同名变量。将占位值替换为实际值,并确保 IDE 进程能读取这些变量。
export NLS_APP_KEY="<APPKEY>"
export NLS_TOKEN="<NLS_TOKEN>"
export NLS_HTTP_URL="https://nls-gateway-ap-southeast-1.aliyuncs.com"
export NLS_WS_URL="wss://nls-gateway-ap-southeast-1.aliyuncs.com/ws/v1"
Appkey、Token 和访问地址必须对应同一账号的项目及服务地域。Token 有有效期,到期后需重新获取并更新环境变量。
一句话识别
下载示例录音文件,保存为 nls-sample-16k.wav。示例为普通话录音,使用匹配的 16 kHz 识别模型。也可以使用自己的录音,要求不超过 60 秒、16 kHz、16 位、单声道 PCM 编码 WAV 格式,且语种与识别模型一致。
export NLS_AUDIO_FILE="./nls-sample-16k.wav"
cURL
发送识别请求:
curl -X POST "${NLS_HTTP_URL}/stream/v1/asr?appkey=${NLS_APP_KEY}&format=wav&sample_rate=16000" \
-H "X-NLS-Token: ${NLS_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary "@${NLS_AUDIO_FILE}"
Postman
安装 Postman,创建 POST 请求。在 Postman 中设置 NLS_HTTP_URL、NLS_APP_KEY 和 NLS_TOKEN 变量,值与前面的访问参数一致。
|
位置 |
配置 |
|
URL |
|
|
Params |
|
|
Headers |
|
|
Body |
选择 binary,上传准备好的 WAV 文件。 |
成功响应示例如下,result 为识别文本:
{
"task_id": "<TASK_ID>",
"result": "北京的天气",
"status": 20000000,
"message": "SUCCESS"
}
完整参数和音频要求请参见一句话识别 RESTful API。
实时语音识别
使用 Java SDK,将本地 WAV 文件读取为 PCM 音频流后分块发送。示例使用 SDK 2.2.1。在 Maven 项目的 dependencies 中添加:
<dependency>
<groupId>com.alibaba.nls</groupId>
<artifactId>nls-sdk-transcriber</artifactId>
<version>2.2.1</version>
</dependency>
下载示例录音文件,将 NLS_AUDIO_FILE 设置为本地文件路径。沿用 NLS_APP_KEY、NLS_TOKEN 和 NLS_WS_URL。代码以本地文件模拟实时音频流,输入为 16 kHz、16 位、单声道 PCM 编码 WAV 文件。
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriber;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberListener;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberResponse;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat;
import java.io.File;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class RealtimeExample {
private static String env(String name) {
String value = System.getenv(name);
if (value == null || value.isEmpty()) {
throw new IllegalArgumentException("Set " + name);
}
return value;
}
public static void main(String[] args) throws Exception {
String appKey = env("NLS_APP_KEY");
String token = env("NLS_TOKEN");
String url = env("NLS_WS_URL");
String audioFile = env("NLS_AUDIO_FILE");
CountDownLatch done = new CountDownLatch(1);
AtomicReference<String> error = new AtomicReference<>();
SpeechTranscriberListener listener = new SpeechTranscriberListener() {
public void onTranscriberStart(SpeechTranscriberResponse r) {
System.out.println("task_id=" + r.getTaskId());
}
public void onSentenceBegin(SpeechTranscriberResponse r) {}
public void onTranscriptionResultChange(SpeechTranscriberResponse r) {}
public void onSentenceEnd(SpeechTranscriberResponse r) {
System.out.println(r.getTransSentenceText());
}
public void onTranscriptionComplete(SpeechTranscriberResponse r) {
System.out.println(r.getName() + ": " + r.getStatus());
done.countDown();
}
public void onFail(SpeechTranscriberResponse r) {
error.set("task_id=" + r.getTaskId() + ", status="
+ r.getStatus() + ", message=" + r.getStatusText());
done.countDown();
}
};
NlsClient client = new NlsClient(url, token);
SpeechTranscriber transcriber = null;
try (AudioInputStream audio = AudioSystem.getAudioInputStream(new File(audioFile))) {
AudioFormat f = audio.getFormat();
if (!f.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
|| f.getSampleRate() != 16000 || f.getSampleSizeInBits() != 16
|| f.getChannels() != 1 || f.isBigEndian()) {
throw new IllegalArgumentException("Use a 16 kHz, 16-bit, mono PCM WAV file");
}
transcriber = new SpeechTranscriber(client, listener);
transcriber.setAppKey(appKey);
transcriber.setFormat(InputFormatEnum.PCM);
transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
transcriber.setEnablePunctuation(true);
transcriber.start();
byte[] buffer = new byte[3200];
int count;
while ((count = audio.read(buffer)) != -1) {
if (error.get() != null) throw new IllegalStateException(error.get());
transcriber.send(buffer, count);
Thread.sleep(Math.max(1, count / 32));
}
transcriber.stop();
if (!done.await(30, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timed out waiting for transcription completion");
}
if (error.get() != null) throw new IllegalStateException(error.get());
} finally {
if (transcriber != null) transcriber.close();
client.shutdown();
}
}
}
运行后输出识别文本和完成事件,例如:
task_id=<TASK_ID>
北京的天气。
TranscriptionCompleted: 20000000
更多 Java 示例可下载nls-sdk-java-demo。完整接口说明请参见实时语音识别接口说明。
录音文件识别
使用 Python 提交录音文件识别任务。服务通过 URL 读取音频,不在请求中上传文件内容。准备可供服务访问的音频 URL;文件大小不超过 512 MB,其他格式和时长要求请参见录音文件识别接口说明。
安装依赖。示例使用 aliyun-python-sdk-core 2.15.1。
python3 -m pip install aliyun-python-sdk-core
以下配置使用示例录音文件的 URL,沿用前面配置的 NLS_APP_KEY。
export ALIYUN_AK_ID="<ACCESS_KEY_ID>"
export ALIYUN_AK_SECRET="<ACCESS_KEY_SECRET>"
export NLS_FILE_URL="https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav"
使用自己的录音时,可将文件上传到 OSS 并替换 NLS_FILE_URL。私有文件的访问方式请参见使用预签名 URL 下载或预览文件,确保 URL 在服务读取音频时仍有效。
export NLS_REGION_ID="ap-southeast-1"
export NLS_FILETRANS_DOMAIN="filetrans.ap-southeast-1.aliyuncs.com"
export NLS_FILETRANS_API_VERSION="2019-08-23"
import json
import os
import time
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
def main():
client = AcsClient(os.environ["ALIYUN_AK_ID"],
os.environ["ALIYUN_AK_SECRET"],
os.environ["NLS_REGION_ID"])
def call(action, method, params):
request = CommonRequest()
request.set_domain(os.environ["NLS_FILETRANS_DOMAIN"])
request.set_version(os.environ["NLS_FILETRANS_API_VERSION"])
request.set_product("nls-filetrans")
request.set_protocol_type("https")
request.set_accept_format("json")
request.set_action_name(action)
request.set_method(method)
for key, value in params.items():
if method == "POST":
request.add_body_params(key, value)
else:
request.add_query_param(key, value)
return json.loads(client.do_action_with_exception(request))
task = {"appkey": os.environ["NLS_APP_KEY"],
"file_link": os.environ["NLS_FILE_URL"],
"version": "4.0", "enable_words": False}
result = call("SubmitTask", "POST", {"Task": json.dumps(task)})
if result.get("StatusText") != "SUCCESS" or not result.get("TaskId"):
raise RuntimeError(result)
task_id = result["TaskId"]
print("TaskId:", task_id)
for _ in range(60):
result = call("GetTaskResult", "GET", {"TaskId": task_id})
status = result.get("StatusText")
if status == "SUCCESS":
print(json.dumps(result.get("Result"), ensure_ascii=False, indent=2))
return
if status == "SUCCESS_WITH_NO_VALID_FRAGMENT":
print("No valid speech fragment was recognized.")
return
if status not in ("RUNNING", "QUEUEING"):
raise RuntimeError(result)
time.sleep(10)
raise TimeoutError("Task is still running. Query it later using TaskId: " + task_id)
if __name__ == "__main__":
main()
程序提交任务并等待识别完成,输出示例如下:
TaskId: <TASK_ID>
{
"Sentences": [
{
"EndTime": 3080,
"SilenceDuration": 0,
"SpeakerId": "1",
"BeginTime": 640,
"Text": "北京的天气。",
"ChannelId": 0,
"SpeechRate": 147,
"EmotionValue": 6.5
}
]
}
语音合成
使用 Java SDK 将文本合成为 16 kHz WAV 文件。示例使用 SDK 2.2.1,在 Maven 项目的 dependencies 中添加:
<dependency>
<groupId>com.alibaba.nls</groupId>
<artifactId>nls-sdk-tts</artifactId>
<version>2.2.1</version>
</dependency>
沿用 NLS_APP_KEY、NLS_TOKEN 和 NLS_WS_URL,设置音色和待合成文本:
export NLS_VOICE="siyue"
export NLS_TEXT="今天天气好晴朗。"
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class SynthesisExample {
private static String env(String name) {
String value = System.getenv(name);
if (value == null || value.isEmpty()) throw new IllegalArgumentException("Set " + name);
return value;
}
public static void main(String[] args) throws Exception {
String appKey = env("NLS_APP_KEY");
String token = env("NLS_TOKEN");
String url = env("NLS_WS_URL");
String voice = env("NLS_VOICE");
String text = env("NLS_TEXT");
CountDownLatch done = new CountDownLatch(1);
AtomicReference<String> error = new AtomicReference<>();
NlsClient client = new NlsClient(url, token);
SpeechSynthesizer synthesizer = null;
try (FileOutputStream output = new FileOutputStream("speech.wav")) {
SpeechSynthesizerListener listener = new SpeechSynthesizerListener() {
public void onMessage(ByteBuffer message) {
byte[] bytes = new byte[message.remaining()];
message.get(bytes);
try { output.write(bytes); }
catch (IOException e) { error.set(e.getMessage()); done.countDown(); }
}
public void onComplete(SpeechSynthesizerResponse r) {
System.out.println(r.getName() + ": " + r.getStatus());
done.countDown();
}
public void onFail(SpeechSynthesizerResponse r) {
error.set("task_id=" + r.getTaskId() + ", status="
+ r.getStatus() + ", message=" + r.getStatusText());
done.countDown();
}
public void onMetaInfo(SpeechSynthesizerResponse r) {}
};
synthesizer = new SpeechSynthesizer(client, listener);
synthesizer.setAppKey(appKey);
synthesizer.setFormat(OutputFormatEnum.WAV);
synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
synthesizer.setVoice(voice);
synthesizer.setText(text);
synthesizer.start();
if (!done.await(60, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timed out waiting for synthesis completion");
}
if (error.get() != null) throw new IllegalStateException(error.get());
System.out.println("Audio saved to speech.wav");
} finally {
if (synthesizer != null) synthesizer.close();
client.shutdown();
}
}
}
合成成功后,音频保存为 speech.wav,可直接播放。输出如下:
SynthesisCompleted: 20000000
Audio saved to speech.wav
更多 Java 示例可下载nls-sdk-java-demo。其他音色、语种和参数请参见语音合成接口说明。