帮助与文档 > 产品文档 > 语音评测 > API 文档

简介

Hi,您好,欢迎使用有道智云智能语音评测服务。

本文档主要针对需要集成短语音识别服务HTTP API的开发工程师,详细描述有道智云只能语音评测能力及如何集成的技术内容。

如果您是非技术人员,想要体验我们的产品能力,请点击语音识别体验中心。也可以下拉到网站底部,扫描小程序二维码进行体验。

如果您对文档内容有任何疑问,可以通过以下几种方式联系我们:

客服QQ:1906538062

官方交流群:861723255

联系邮箱:zyservice@corp.youdao.com

接口介绍

接口地址:

http接口: http://openapi.youdao.com/iseapi

https接口: https://openapi.youdao.com/iseapi

接口参数:
调用API需要向接口发送以下字段来访问服务。

字段名类型含义必填备注
qtext要评测的音频文件的base64编码字符串True必须是Base64编码
texttext要翻译的音频文件对应的文本Truehave a good day
langTypetext源语言True语言列表
appKeytext应用 IDTrue可在 应用管理 查看
salttext随机数True
curtimetext当前时间戳True
signtext签名,通过sha256(appKey+input+salt+curtime+密钥)生成;input的生成规则见表下的备注True
signTypetext签名类型Truev2
formattext语音文件的格式,wavtruewav
ratetext采样率, 8000 或者 16000, 推荐 16000 采用率true8000
channeltext声道数, 仅支持单声道,请填写固定值1true1
typetext上传类型, 仅支持base64上传,请填写固定值1true1

input=q字符串的前10个字符 + q字符串长度 + q字符串后十个字符(当q长度大于20)或 q字符串(当q长度小于等于20).

具体示例如下:
a.比如:q="Welcome to youdao AICloud.",字符串长度为26,大于20,其input="Welcome to"(前10个字符) + 26(字符串长度) + "o AICloud."(q字符串后10个字符)。
b.比如:q = "sdT4bWrjS",字符串长度为9,小于20,input = "sdT4bWrjS".

输出结果

输出字段介绍

响应结果是以json形式输出,包含字段如下表所示:

字段含义
errorCode识别结果错误码,一定存在
refText请求的文本
start音频中句子开始时间,单位是秒
end音频中句子结束时间,单位是秒
integrity句子完整度得分
fluency句子流利度得分
pronunciation句子准确度得分
speed语速,单词/分钟
overall句子综合评分
words单词评分数组
-word单词
-start单词开始时间,单位是秒
-end单词结束时间,单位是秒
-pronunciation单词准确度得分
-phonemes音标数组
--phoneme音标
--start音标开始时间,单位是秒
--end音标结束时间,单位是秒
--judge判断音素是否错误,true为发音正确,false为发音错误,同时calibration给出提示
--calibration如果发音错误,提示用户该发音像什么
--prominence重音程度,分数越高,当前音标越可能是重音,分数在[0 100]
--stress_ref元音重音参考/标准答案,如果为true,说明参考答案认为该元音应该发重音,辅音时无意义
--stress_detect在一个单词中,用户该音标发音为重音

输出结果示例

{
    "integrity": 100,//句子完整度
    "refText": "have a good day ",//待评测语音对应的文本
    "pronunciation": 77.592987,//句子发音准确度
    "start": 0.030000,//音频开始时间,秒
    "words": [{//单词信息列表
        "pronunciation": 99.078613,//单词准确度分数
        "start": 0.030000,//单词开始时间,秒
        "end": 0.210000,//单词结束时间,秒
        "word": "have",,//单词文本
        "phonemes": [{//音标信息列表
            "stress_ref": false,//元音重音参考(即标准重音),如果为true,说明参考答案认为该元音应该发重音,辅音时无意义
            "pronunciation": 99.712486,//音标准确度评分
            "stress_detect": false,//在一个单词中,用户该音标发音不为重音
            "phoneme": "h",//音标名称
            "start": 0.030000,//音标开始时间,秒
            "end": 0.090000,//音标结束时间,秒
            "judge": true,//判断音标是否错误,true为发音正确,false为发音错误,同时calibration给出提示
            "calibration": "h",//判断音标是否错误,true为发音正确,false为发音错误,同时calibration给出提示
            "prominence": 75.887459//重音程度,当前音标越可能是重音,分数区间[0 100]
        }, {
            "stress_ref": true,
            "pronunciation": 97.723366,
            "stress_detect": true,
            "phoneme": "æ",
            "start": 0.090000,
            "end": 0.150000,
            "judge": true,
            "calibration": "æ",
            "prominence": 100
        }, {
            "stress_ref": false,
            "pronunciation": 99.800003,
            "stress_detect": true,
            "phoneme": "v",
            "start": 0.150000,
            "end": 0.210000,
            "judge": true,
            "calibration": "v",
            "prominence": 84.676437
        }]
    }, {
        "pronunciation": 96.424133,
        "start": 0.210000,
        "end": 1.140000,
        "word": "a",
        "phonemes": [{
            "stress_ref": false,
            "pronunciation": 96.424133,
            "stress_detect": true,
            "phoneme": "ə",
            "start": 0.210000,
            "end": 1.140000,
            "judge": true,
            "calibration": "ə",
            "prominence": 100
        }]
    }, {
        "pronunciation": 63.492290,
        "start": 1.140000,
        "end": 1.230000,
        "word": "good",
        "phonemes": [{
            "stress_ref": false,
            "pronunciation": 38.676857,
            "stress_detect": false,
            "phoneme": "g",
            "start": 1.140000,
            "end": 1.170000,
            "judge": false,
            "calibration": "ə",
            "prominence": 99.275475
        }, {
            "stress_ref": false,
            "pronunciation": 85.800003,
            "stress_detect": false,
            "phoneme": "ɪ",
            "start": 1.170000,
            "end": 1.200000,
            "judge": true,
            "calibration": "ɪ",
            "prominence": 99.332588
        }, {
            "stress_ref": false,
            "pronunciation": 66,
            "stress_detect": true,
            "phoneme": "d",
            "start": 1.200000,
            "end": 1.230000,
            "judge": true,
            "calibration": "d",
            "prominence": 100
        }]
    }, {
        "pronunciation": 57.099998,
        "start": 1.230000,
        "end": 1.290000,
        "word": "day",
        "phonemes": [{
            "stress_ref": false,
            "pronunciation": 47.799999,
            "stress_detect": true,
            "phoneme": "d",
            "start": 1.230000,
            "end": 1.260000,
            "judge": false,
            "calibration": "ə",
            "prominence": 100
        }, {
            "stress_ref": true,
            "pronunciation": 66.400002,
            "stress_detect": true,
            "phoneme": "e",
            "start": 1.260000,
            "end": 1.290000,
            "judge": true,
            "calibration": "e",
            "prominence": 99.169800
        }]
    }],
    "fluency": 100,//句子流利度
    "overall": 80.954041,//句子综合评分
    "errorCode": "0",//识别结果错误码,一定存在
    "end": 1.290000,//句子结束时间,秒
    "speed": 190.476196// 句子语速(单词/分钟)
}

支持的语言表

目前支持英文的语音评测。

语言代码
英文en

语音支持

格式支持:wav(不压缩、pcm编码)

采样率:8k或者16k。推荐16k。

编码:16bit位深的单声道

格式代码
wavwav

错误代码列表

错误码含义
101缺少必填的参数
102不支持的语言类型
103请求文本过长
104不支持的API类型
105不支持的签名类型
106不支持的响应类型
107不支持的传输加密类型
108appKey无效
109batchLog格式不正确
110无相关服务的有效实例
111用户无效
112请求服务无效
113请求文本不能为空
201解密失败
202签名检验失败
203访问IP地址不在可访问IP列表
205请求的接口与创建的应用的平台类型不一致
206因为时间戳无效导致签名校验失败
207重放请求
301词典查询失败
302小语种翻译失败
303服务的异常
401账户已经欠费停止
402offlinesdk不可用
411访问频率受限,请稍后访问
412超过最大请求字符数
11001不支持的语音识别格式
11002不支持的语音识别采样率
11003不支持的语音识别声道
11004不支持的语音上传类型
11005不支持的语言类型
11006识别音频文件过大
11007识别音频时长过长,最大支持30s
11008识别文件为空
11009不支持的识别文件类型
11010识别音频时长过短
11011环境音过大、发音过差或安静音频,不做评分
11201解密失败
11301语音识别失败
11303服务的异常
11411访问频率受限,请稍后访问
11412超过最大请求时长

常用语言 Demo

Java 示例
Python 示例
C# 示例
PHP 示例
                
package com.youdao.ai;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.Base64;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class IseV1Demo {
    private static final String YOUDAO_URL = "https://openapi.youdao.com/iseapi";

    private static final String APP_KEY = "您的应用ID";

    private static final String APP_SECRET = "您的应用密钥";

    public static String truncate(String q) {
        if (q == null) {
            return null;
        }
        int len = q.length();
        String result;
        return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
    }

    public static String loadAsBase64(String filename) {
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(filename);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(data);
    }

    public static String doRequest(String url, Map<String,String> requestParams) throws Exception{
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        for (String key : requestParams.keySet()) {
            params.add(new BasicNameValuePair(key, requestParams.get(key)));
        }
        httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
        CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
        try {
            HttpEntity httpEntity = httpResponse.getEntity();
            result = EntityUtils.toString(httpEntity, "utf-8");
            EntityUtils.consume(httpEntity);
        } finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch(IOException e) {
                System.out.println("## release resouce error ##" + e);
            }
        }
        return result;
    }

    public static String getDigest(String string) {
        if (string == null) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        byte[] btInput = string.getBytes();
        try {
            MessageDigest mdInst = MessageDigest.getInstance("SHA-256");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    public static void main(String[] args) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        String filename = "音频的路径";
        String langType = "en";
        map.put("appKey", APP_KEY);
        String q = loadAsBase64(filename);
        map.put("q", q);
        map.put("format", "wav");
        map.put("rate", "16000");
        map.put("channel", "1");
        map.put("docType", "json");
        map.put("type", "1");
        String salt = UUID.randomUUID().toString();
        map.put("salt", salt);
        map.put("langType", langType);
        map.put("text", "音频对应的文字");
        String curtime = String.valueOf(System.currentTimeMillis() / 1000);
        map.put("curtime", curtime);
        String signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET;
        String sign = getDigest(signStr);
        map.put("sign", sign);
        map.put("signType", "v2");

        String result = doRequest(YOUDAO_URL, map);
        System.out.println(result);
    }
}

                
            
                
# -*- coding: utf-8 -*-
import sys
import uuid
import requests
import wave
import base64
import hashlib
import time

reload(sys)
sys.setdefaultencoding('utf-8')

YOUDAO_URL = 'https://openapi.youdao.com/iseapi'
APP_KEY = '您的应用ID'
APP_SECRET = '您的应用密钥'

def truncate(q):
    if q is None:
        return None
    size = len(q)
    return q if size <= 20 else q[0:10] + str(size) + q[size-10:size]

def encrypt(signStr):
    hash_algorithm = hashlib.sha256()
    hash_algorithm.update(signStr.encode('utf-8'))
    return hash_algorithm.hexdigest()

def do_request(data):
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    return requests.post(YOUDAO_URL, data=data, headers=headers)

def connect():
    audio_file_path = '音频的路径'
    lang_type = 'en'
    extension = audio_file_path[audio_file_path.rindex('.')+1:]
    if extension != 'wav':
        print '不支持的音频类型'
        sys.exit(1)
    wav_info = wave.open(audio_file_path, 'rb')
    sample_rate = wav_info.getframerate()
    nchannels = wav_info.getnchannels()
    wav_info.close()
    with open(audio_file_path, 'rb') as file_wav:
        q = base64.b64encode(file_wav.read())

    data = {}
    data['text'] = '音频对应的文字'
    curtime = str(int(time.time()))
    data['curtime'] = curtime
    salt = str(uuid.uuid1())
    signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET
    sign = encrypt(signStr)
    data['appKey'] = APP_KEY
    data['q'] = q
    data['salt'] = salt
    data['sign'] = sign
    data['signType'] = "v2"
    data['langType'] = lang_type
    data['rate'] = sample_rate
    data['format'] = 'wav'
    data['channel'] = nchannels
    data['type'] = 1

    response = do_request(data)
    print response.content

if __name__ == '__main__':
    connect()

                
            
                
using System;
using System.IO;
using System.Web;
using System.Net;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;

namespace zhiyun_csharp_demo
{
    class IseV1Demo
    {
        public static void Main()
        {
            String url = "https://openapi.youdao.com/iseapi";
            Dictionary<String, String> dic = new Dictionary<String, String>();

            string q = LoadAsBase64("音频的路径");
            string appKey = "您的应用ID";
            string appSecret = "您的应用密钥";
            string langType = "en";
            string format = "wav";
            string rate = "16000";
            string channel = "1";
            string type = "1";
            string salt = Guid.NewGuid().ToString();
            dic.Add("text", "音频对应的文字");
            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
            long millis = (long) ts.TotalMilliseconds;
            string curtime = Convert.ToString(millis / 1000);
            dic.Add("curtime", curtime);
            string signStr = appKey + Truncate(q) + salt + curtime + appSecret;
            string sign = ComputeHash(signStr, new SHA256CryptoServiceProvider());
            dic.Add("q", System.Web.HttpUtility.UrlEncode(q));
            dic.Add("appKey", appKey);
            dic.Add("langType", langType);
            dic.Add("format", format);
            dic.Add("rate", rate);
            dic.Add("channel", channel);
            dic.Add("type", type);
            dic.Add("salt", salt);
            dic.Add("sign", sign);
            dic.Add("signType", "v2");

            string result = Post(url, dic);
            Console.WriteLine(result);
        }

        protected static string ComputeHash(string input, HashAlgorithm algorithm)
        {
          Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
          Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
          return BitConverter.ToString(hashedBytes).Replace("-", "");
        }

        protected static string Truncate(string q)
        {
            if (q == null)
            {
               return null;
            }
            int len = q.Length;
            return len <= 20 ? q : (q.Substring(0, 10) + len + q.Substring(len - 10, 10));
        }

        protected static string LoadAsBase64(string filename)
        {
            try
            {
                FileStream filestream = new FileStream(filename, FileMode.Open);
                byte[] arr = new byte[filestream.Length];
                filestream.Position = 0;
                filestream.Read(arr, 0, (int)filestream.Length);
                filestream.Close();
                return Convert.ToBase64String(arr);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        protected static string Post(string url, Dictionary<String, String> dic)
        {
            string result = "";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            StringBuilder builder = new StringBuilder();
            int i = 0;
            foreach (var item in dic)
            {
                if (i > 0)
                    builder.Append("&");
                builder.AppendFormat("{0}={1}", item.Key, item.Value);
                i++;
            }
            byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
            req.ContentLength = data.Length;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }
            return result;
        }
    }
}

                
            
                
<?php
define("CURL_TIMEOUT",   2000);
define("URL",            "https://openapi.youdao.com/iseapi");
define("APP_KEY",        "您的应用ID"); // 替换为您的应用ID
define("SEC_KEY",        "您的应用密钥"); // 替换为您的密钥

function do_request($q, $langType, $channel, $rate, $format)
{
    $salt = create_guid();
    $args = array(
        'q' => $q,
        'appKey' => APP_KEY,
        'salt' => $salt,
        'langType' => $langType,
        'channel' => $channel,
        'rate' => $rate,
        'format' => $format,
        'type' => "1",
        'signType' => "v2",
    );
    $args['text'] = '音频对应的文字';
    $curtime = strtotime("now");
    $args['curtime'] = $curtime;
    $signStr = APP_KEY . truncate($q) . $salt . $curtime . SEC_KEY;
    $args['sign'] = hash("sha256", $signStr);
    $ret = call(URL, $args);
    echo $ret;
    $ret = json_decode($ret, true);
    return $ret;
}

// 发起网络请求
function call($url, $args=null, $method="post", $testflag = 0, $timeout = CURL_TIMEOUT, $headers=array())
{
    $ret = false;
    $i = 0;
    while($ret === false)
    {
        if($i > 1)
            break;
        if($i > 0)
        {
            sleep(1);
        }
        $ret = callOnce($url, $args, $method, false, $timeout, $headers);
        $i++;
    }
    return $ret;
}

function callOnce($url, $args=null, $method="post", $withCookie = false, $timeout = CURL_TIMEOUT, $headers=array())
{
    $ch = curl_init();
    if($method == "post")
    {
        $data = convert($args);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_POST, 1);
    }
    else
    {
        $data = convert($args);
        if($data)
        {
            if(stripos($url, "?") > 0)
            {
                $url .= "&$data";
            }
            else
            {
                $url .= "?$data";
            }
        }
    }
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    if(!empty($headers))
    {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    if($withCookie)
    {
        curl_setopt($ch, CURLOPT_COOKIEJAR, $_COOKIE);
    }
    $r = curl_exec($ch);
    curl_close($ch);
    return $r;
}

function convert(&$args)
{
    $data = '';
    if (is_array($args))
    {
        foreach ($args as $key=>$val)
        {
            if (is_array($val))
            {
                foreach ($val as $k=>$v)
                {
                    $data .= $key.'['.$k.']='.rawurlencode($v).'&';
                }
            }
            else
            {
                $data .="$key=".rawurlencode($val)."&";
            }
        }
        return trim($data, "&");
    }
    return $args;
}

// uuid generator
function create_guid(){
    $microTime = microtime();
    list($a_dec, $a_sec) = explode(" ", $microTime);
    $dec_hex = dechex($a_dec* 1000000);
    $sec_hex = dechex($a_sec);
    ensure_length($dec_hex, 5);
    ensure_length($sec_hex, 6);
    $guid = "";
    $guid .= $dec_hex;
    $guid .= create_guid_section(3);
    $guid .= '-';
    $guid .= create_guid_section(4);
    $guid .= '-';
    $guid .= create_guid_section(4);
    $guid .= '-';
    $guid .= create_guid_section(4);
    $guid .= '-';
    $guid .= $sec_hex;
    $guid .= create_guid_section(6);
    return $guid;
}

function truncate($q) {
    $len = strlen($q);
    return $len <= 20 ? $q : (substr($q, 0, 10) . $len . substr($q, $len - 10, $len));
}

function ensure_length(&$string, $length){
    $strlen = strlen($string);
    if($strlen < $length)
    {
        $string = str_pad($string, $length, "0");
    }
    else if($strlen > $length)
    {
        $string = substr($string, 0, $length);
    }
}

function create_guid_section($characters){
    $return = "";
    for($i = 0; $i < $characters; $i++)
    {
        $return .= dechex(mt_rand(0,15));
    }
    return $return;
}

$file = "音频的路径";
$langType = "en";

$fp = fopen($file, "r") or die("Can't open file");

// base64编码
$q = chunk_split(base64_encode(fread($fp, filesize($file))));

fclose($fp);

do_request($q, $langType, "1", 16000, "wav");
?>

                
            
文档是否有帮助解决问题?

如有其它疑问,可在此提交意见和反馈
详细描述(选填)
联系邮箱(选填)
 
有道智云平台介绍
网易有道旗下一个为开发者、企业和政府机构等提供自然语言翻译、文字识别OCR等服务以及行业解决方案的云服务平台,致力于提供安全、可靠和高效的云服务。
联系方式
联系电话:010-8255-8901
商务合作:
投诉反馈:
地址:北京市海淀区西北旺东路10号院 中关村软件园二期西区7号 网易(北京)公司
微信公众号
微信小程序
 
 
 
©2017 网易公司 京ICP证080268号