RESTful API

更新时间:
复制 MD 格式

一句话识别 RESTful API 支持通过 HTTP POST 请求上传不超过 1 分钟的音频。服务端处理完成后,在 HTTP 响应中一次性返回 JSON 格式的识别结果。

前提条件

调用接口前,需准备以下信息:

  • 项目 AppKey。创建项目并获取 AppKey 的方法,请参见创建项目

  • 访问 Token。获取方法,请参见获取 Token

音频要求

要求

说明

编码

单声道、16 bit 采样位数。

格式

PCM、PCM 编码的 WAV、OGG 封装的 Opus、OGG 封装的 Speex、AMR、MP3、AAC。

采样率

8000 Hz 或 16000 Hz。

时长

不超过 1 分钟。

语种和场景模型不能通过请求参数指定。需在控制台为项目选择与音频匹配的模型,具体操作请参见管理项目

重要

不要在浏览器前端代码中直接调用该接口。浏览器可能因跨域资源共享(CORS)限制而拒绝请求,而且前端代码会暴露 AppKey 和 Token。

快速测试

下载示例音频 nls-sample-16k.wav。该文件为 16 kHz WAV 文件,适用于通用模型。

设置 AppKey 和 Token 后,运行以下命令:

curl -X POST \
  -H "X-NLS-Token: <token>" \
  "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/asr?appkey=<appkey>&format=wav&sample_rate=16000" \
  --data-binary @nls-sample-16k.wav

成功响应示例:

{
  "task_id": "cf7b0c5339244ee29cd4e43fb97f****",
  "result": "北京的天气。",
  "status": 20000000,
  "message": "SUCCESS"
}

交互流程

客户端在一个 HTTP POST 请求中发送鉴权信息、请求参数和完整音频。服务端处理完音频后,在同一 HTTP 连接中返回一次 JSON 响应。收到响应前不要中断连接。

  1. 客户端向服务端发起 POST 请求。

  2. 服务端校验鉴权信息和请求参数,并处理音频。

  3. 服务端返回任务 ID、状态码和识别结果。

服务地址

根据项目所在地域和网络环境选择服务地址。公网地址支持 HTTPS 和 HTTP,建议使用 HTTPS。

地域

网络

服务地址

华东 2(上海)

公网

https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/asr

华北 2(北京)

公网

https://nls-gateway-cn-beijing.aliyuncs.com/stream/v1/asr

华南 1(深圳)

公网

https://nls-gateway-cn-shenzhen.aliyuncs.com/stream/v1/asr

华东 2(上海)

内网

http://nls-gateway-cn-shanghai-internal.aliyuncs.com/stream/v1/asr

华北 2(北京)

内网

http://nls-gateway-cn-beijing-internal.aliyuncs.com/stream/v1/asr

华南 1(深圳)

内网

http://nls-gateway-cn-shenzhen-internal.aliyuncs.com/stream/v1/asr

API 说明

请求由请求行、请求头和请求体组成。

请求行

POST /stream/v1/asr?appkey=<appkey>&format=pcm&sample_rate=16000&enable_punctuation_prediction=true HTTP/1.1

参数

类型

是否必选

默认值

说明

appkey

String

项目 AppKey。

format

String

pcm

音频格式。取值:pcm、wav、opus、speex、amr、mp3、aac。

sample_rate

Integer

16000

音频采样率。取值:8000、16000,单位为 Hz。

vocabulary_id

String

热词表 ID。

customization_id

String

自学习模型 ID。

enable_punctuation_prediction

Boolean

false

是否在后处理中添加标点。

enable_inverse_text_normalization

Boolean

false

是否启用逆文本标准化,将口语数字转换为阿拉伯数字等规范格式。

enable_voice_detection

Boolean

false

是否启用语音活动检测(VAD),自动检测有效语音的开始和结束。

disfluency

Boolean

false

是否过滤语气词。

audio_address

String

可通过公网访问的音频文件 URL。设置该参数时不需要在请求体中传入音频。

请求头

请求头

类型

是否必选

说明

X-NLS-Token

String

用于身份验证的访问 Token。

Content-Type

String

application/octet-stream

Content-Length

Long

请求体中的音频数据大小,单位为字节。

Host

String

所选服务地址的域名,例如 nls-gateway-cn-shanghai.aliyuncs.com。

请求体

将完整音频的二进制数据写入请求体,并将 Content-Type 设置为 application/octet-stream

也可以通过 audio_address 传入可通过公网访问的音频文件 URL。使用该参数时,请求体为空。建议使用签名 URL,生成方法请参见使用预签名 URL 下载或预览文件

请求示例

POST /stream/v1/asr?appkey=23f5****&format=pcm&sample_rate=16000 HTTP/1.1
X-NLS-Token: 450372e4279bcc2b3c793****
Content-Type: application/octet-stream
Content-Length: 94616
Host: nls-gateway-cn-shanghai.aliyuncs.com

[audio data]
POST /stream/v1/asr?appkey=23f5****&format=wav&sample_rate=16000&audio_address=https%3A%2F%2Fexample.com%2Faudio.wav HTTP/1.1
X-NLS-Token: 450372e4279bcc2b3c793****
Host: nls-gateway-cn-shanghai.aliyuncs.com
Content-Length: 0

响应说明

响应参数

参数

类型

说明

task_id

String

32 位任务 ID。排查问题时需提供该 ID。

result

String

识别结果。识别失败时为空字符串。

status

Integer

状态码。

message

String

状态说明。

成功响应

{
  "task_id": "cf7b0c5339244ee29cd4e43fb97f****",
  "result": "北京的天气。",
  "status": 20000000,
  "message": "SUCCESS"
}

失败响应

{
  "task_id": "8bae3613dfc54ebfa811a17d8a7a****",
  "result": "",
  "status": 40000001,
  "message": "Gateway:ACCESS_DENIED:The token is invalid"
}

排查失败请求时,记录响应中的任务 ID。

状态码

出现偶发的服务端错误(5xxxxxxx)时可以重试。如果错误持续出现,请提交工单并提供响应中的任务 ID。

状态码

说明

处理建议

20000000

请求成功。

无需处理。

40000000

客户端错误。

根据错误消息检查请求。

40000001

身份验证失败。

检查 Token 是否正确且未过期。

40000002

请求无效。

检查请求是否符合接口要求。

40000003

参数无效。

检查参数值是否在有效范围内。

40000004

客户端超时。

检查客户端是否停止发送数据。

40000005

请求速率超限。

检查并发数或 QPS 是否超过限制。

41010100

音频格式不支持。

检查 format 参数和实际音频格式。

41010101

采样率不支持。

检查 sample_rate 是否与音频和项目模型匹配。

50000000

服务端错误。

持续出现时提交工单并提供任务 ID。

50000001

服务内部调用错误。

持续出现时提交工单并提供任务 ID。

示例代码

以下示例从环境变量读取服务地址、AppKey、Token 和本地音频路径,并以二进制方式发送 PCM 音频。

获取 Token 的方法,请参见获取 Token

环境变量

说明

NLS_ENDPOINT

https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/asr

NLS_APP_KEY

项目 AppKey。

NLS_TOKEN

有效的访问 Token。

NLS_AUDIO_FILE

16 kHz、16 bit、单声道 PCM 音频文件的本地路径。

Java

示例使用 JDK 21。

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;

public class SpeechRecognition {
    private static String required(String name) {
        String value = System.getenv(name);
        if (value == null || value.isBlank()) {
            throw new IllegalArgumentException("Missing environment variable: " + name);
        }
        return value;
    }

    public static void main(String[] args) throws Exception {
        String endpoint = required("NLS_ENDPOINT");
        String appKey = URLEncoder.encode(required("NLS_APP_KEY"), StandardCharsets.UTF_8);
        String token = required("NLS_TOKEN");
        Path audioFile = Path.of(required("NLS_AUDIO_FILE"));
        String url = endpoint + "?appkey=" + appKey
                + "&format=pcm&sample_rate=16000"
                + "&enable_punctuation_prediction=true"
                + "&enable_inverse_text_normalization=true";

        HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                .header("X-NLS-Token", token)
                .header("Content-Type", "application/octet-stream")
                .POST(HttpRequest.BodyPublishers.ofFile(audioFile))
                .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(
                request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
        System.out.println(response.body());
    }
}

C++

示例使用 C++17 and libcurl 8.7.1。

#include <curl/curl.h>

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <string>

std::string required(const char* name) {
    const char* value = std::getenv(name);
    if (value == nullptr || *value == '\0') {
        throw std::runtime_error(std::string("Missing environment variable: ") + name);
    }
    return value;
}

size_t writeResponse(char* data, size_t size, size_t count, void* target) {
    static_cast<std::string*>(target)->append(data, size * count);
    return size * count;
}

int main() {
    std::ifstream file(required("NLS_AUDIO_FILE"), std::ios::binary);
    if (!file) throw std::runtime_error("Cannot open audio file");
    std::string audio((std::istreambuf_iterator<char>(file)),
                      std::istreambuf_iterator<char>());

    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();
    if (curl == nullptr) throw std::runtime_error("Cannot initialize cURL");
    char* escaped = curl_easy_escape(curl, required("NLS_APP_KEY").c_str(), 0);
    std::string url = required("NLS_ENDPOINT") + "?appkey=" + escaped
            + "&format=pcm&sample_rate=16000"
            + "&enable_punctuation_prediction=true"
            + "&enable_inverse_text_normalization=true";
    curl_free(escaped);

    std::string response;
    std::string tokenHeader = "X-NLS-Token: " + required("NLS_TOKEN");
    curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, tokenHeader.c_str());
    headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, audio.data());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(audio.size()));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeResponse);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    CURLcode code = curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    if (code != CURLE_OK) throw std::runtime_error(curl_easy_strerror(code));
    std::cout << response << std::endl;
}

Python

示例使用 Python 3.14。

import os
import urllib.parse
import urllib.request


def required(name):
    value = os.getenv(name)
    if not value:
        raise RuntimeError(f"Missing environment variable: {name}")
    return value


endpoint = required("NLS_ENDPOINT")
query = urllib.parse.urlencode({
    "appkey": required("NLS_APP_KEY"),
    "format": "pcm",
    "sample_rate": 16000,
    "enable_punctuation_prediction": "true",
    "enable_inverse_text_normalization": "true",
})
with open(required("NLS_AUDIO_FILE"), "rb") as audio_file:
    request = urllib.request.Request(
        f"{endpoint}?{query}",
        data=audio_file.read(),
        headers={
            "X-NLS-Token": required("NLS_TOKEN"),
            "Content-Type": "application/octet-stream",
        },
        method="POST",
    )
with urllib.request.urlopen(request) as response:
    print(response.read().decode("utf-8"))

PHP

示例使用 PHP 8.5 with the cURL extension。

<?php

function required_env(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Missing environment variable: " . $name);
    }
    return $value;
}

$query = http_build_query([
    'appkey' => required_env('NLS_APP_KEY'),
    'format' => 'pcm',
    'sample_rate' => 16000,
    'enable_punctuation_prediction' => 'true',
    'enable_inverse_text_normalization' => 'true',
]);
$audio = file_get_contents(required_env('NLS_AUDIO_FILE'));
if ($audio === false) {
    throw new RuntimeException('Cannot read the audio file');
}

$curl = curl_init(required_env('NLS_ENDPOINT') . '?' . $query);
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $audio,
    CURLOPT_HTTPHEADER => [
        'X-NLS-Token: ' . required_env('NLS_TOKEN'),
        'Content-Type: application/octet-stream',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($curl);
if ($response === false) {
    throw new RuntimeException(curl_error($curl));
}
echo $response . PHP_EOL;

Node.js

示例使用 Node.js 22。

import fs from "node:fs";
import http from "node:http";
import https from "node:https";

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Missing environment variable: ${name}`);
  return value;
}

const endpoint = new URL(required("NLS_ENDPOINT"));
endpoint.search = new URLSearchParams({
  appkey: required("NLS_APP_KEY"),
  format: "pcm",
  sample_rate: "16000",
  enable_punctuation_prediction: "true",
  enable_inverse_text_normalization: "true",
});
const audio = fs.readFileSync(required("NLS_AUDIO_FILE"));
const transport = endpoint.protocol === "https:" ? https : http;

const request = transport.request(endpoint, {
  method: "POST",
  headers: {
    "X-NLS-Token": required("NLS_TOKEN"),
    "Content-Type": "application/octet-stream",
    "Content-Length": audio.length,
  },
}, (response) => {
  let body = "";
  response.setEncoding("utf8");
  response.on("data", (chunk) => { body += chunk; });
  response.on("end", () => console.log(body));
});
request.on("error", (error) => { throw error; });
request.end(audio);

C#

示例使用 .NET 8。

using System.Net.Http.Headers;

static string Required(string name)
{
    string? value = Environment.GetEnvironmentVariable(name);
    if (string.IsNullOrWhiteSpace(value))
        throw new ArgumentException($"Missing environment variable: {name}");
    return value;
}

string query = string.Join("&", new Dictionary<string, string>
{
    ["appkey"] = Required("NLS_APP_KEY"),
    ["format"] = "pcm",
    ["sample_rate"] = "16000",
    ["enable_punctuation_prediction"] = "true",
    ["enable_inverse_text_normalization"] = "true",
}.Select(item => $"{Uri.EscapeDataString(item.Key)}={Uri.EscapeDataString(item.Value)}"));

using HttpClient client = new();
using ByteArrayContent audio = new(await File.ReadAllBytesAsync(Required("NLS_AUDIO_FILE")));
audio.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
using HttpRequestMessage request = new(HttpMethod.Post, $"{Required("NLS_ENDPOINT")}?{query}");
request.Headers.Add("X-NLS-Token", Required("NLS_TOKEN"));
request.Content = audio;
using HttpResponseMessage response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());

Go

示例使用 Go 1.24。

package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
)

func required(name string) string {
	value := os.Getenv(name)
	if value == "" {
		panic("Missing environment variable: " + name)
	}
	return value
}

func main() {
	audio, err := os.ReadFile(required("NLS_AUDIO_FILE"))
	if err != nil {
		panic(err)
	}
	query := url.Values{
		"appkey":                            {required("NLS_APP_KEY")},
		"format":                            {"pcm"},
		"sample_rate":                       {"16000"},
		"enable_punctuation_prediction":     {"true"},
		"enable_inverse_text_normalization": {"true"},
	}
	request, err := http.NewRequest(
		http.MethodPost, required("NLS_ENDPOINT")+"?"+query.Encode(), bytes.NewReader(audio))
	if err != nil {
		panic(err)
	}
	request.Header.Set("X-NLS-Token", required("NLS_TOKEN"))
	request.Header.Set("Content-Type", "application/octet-stream")
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, err := io.ReadAll(response.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
}

相关文档