AISpeech API ASDK 教程 – 一个口语英语评估应用
在本教程中,我们将学习如何使用 AISpeech API 及其 ASSDK (ActionScript SDK) 创建一个英语口语评估 Flex 应用程序。
引言
在本教程中,我们将学习如何使用 AISpeech API 及其 ASSDK (ActionScript SDK) 创建一个英语口语评估 Flex 应用程序。此演示的源代码位于 github。
背景
向 Ask AI Speech Ltd (发邮件至 api@aispeech.com) 申请一个开发者帐户、应用程序 ID、密钥和 AISpeech API ASSDK (AISpeechLib.swc) 的发布版本。
请注意,此 ASSDK 仅支持 ActionScript 3.0。ActionScript 2.0 版本也可用,但需另行申请。
此演示应用程序需要耳机或麦克风。
目标
我们正在构建一个英语口语评估应用程序。它是一个 Flex 应用程序。该应用程序允许用户阅读一个英语句子。然后它会录制用户的语音,并分别显示每个单词的得分。分数越高,用户的发音越好。
分数图表面板
更新:Flex BarChart
视图组件拒绝显示其垂直轴上重复项的值。例如,如果参考文本是“I have done what I have to do”,则此分数图表将不会显示第二个“I”和“have”的得分。感谢 Little Bridge 的 James 报告了这个问题。我正在考虑为这个演示使用另一个更好的视图组件。
我们从一个分数图表面板开始,它看起来像下面这样:
图 1 分数图表面板
使用 FlexBuilder。新建一个 Flex 项目。分数面板的源代码如下所示:
<!– score panel –>
<s:Panel title=’Scores’ width=’600' height=’100%’ color="0×000000" borderAlpha="0.15">
<s:layout>
<s:HorizontalLayout paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10"/>
</s:layout>
<mx:BarChart id="scoreBar" height="100%" color="0×323232" showDataTips="true" dataProvider="{_scores}">
<mx:verticalAxis>
<mx:CategoryAxis categoryField="Word" />
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:LinearAxis maximum="100" minimum="0" />
</mx:horizontalAxis>
<mx:series>
<mx:BarSeries yField="Word" xField="Score" displayName="Score" />
</mx:series>
</mx:BarChart>
</s:Panel>
分数面板使用 Flex BarChart
组件。其数据提供程序(_scores
)定义如下(在 <fx:script>
部分):
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
// parsed score results to show in the result chart
// each item is like {Word: 'I', Score: '80'}
[Bindable] private var _scores:ArrayCollection = new ArrayCollection();
private function init():void
{
_scores.addItem({Word:'piano', Score:'67'});
_scores.addItem({Word:'play', Score:'34'});
_scores.addItem({Word:'to', Score:'90'});
_scores.addItem({Word:'want', Score:'30'});
_scores.addItem({Word:'I', Score:'80'});
}
]]>
</fx:Script>
将应用程序的 creationComplete
回调设置为 init()
方法,我们在其中硬编码了一些分数项。应用程序现在应该显示如图 1 所示的分数图表。
其他控件
然后我们添加两个按钮(开始和停止)和一个文本区域字段(ID 为 txtRefText
)。使用 HGroup
和 VGroup
来布局组件。最终的应用程序布局将如下所示:
图 2 应用程序布局
导入 AISpeech API SDK
将 AISpeechLib.swc 添加到项目的构建路径。(在 Flash Builder 中,项目 -> 属性 -> Flex 构建路径 -> 库路径 -> 添加 SWC...)
在 <fx:script>
部分,添加以下变量:
private static const RECORDERLIB_PARAMS:Object = {
appKey:"your application ID",
secretKey:"your secret key",
serverList:["rtmp://demo.aispeech.com:443/v2.0/aistream"] // release 2.0
};
private var _coreRequesterParams:Object = {
refText:"past", // this to be updated for each core request
scoreType:100, // ask score in grade 100
rank:100,
coreType:"en.sent.score", // request the English-Senetence core
userId:"xxxxxx",
applicationId:"your application ID" // application ID again
};
private var _recorderLib:RecorderLib; // the recorder.
请注意,RecorderLib
属于 com.aispeech.RecorderLib
。如果 IDE 没有为您自动导入此命名空间,请导入它。
更新上述 init
()
方法以初始化 RecorderLib
实例。(我们已经从 init()
方法中删除了那些设置示例分数项的代码)
private function init():void
{
// init RecorderLib instance
_recorderLib = new RecorderLib();
_recorderLib.init(RECORDERLIB_PARAMS);
}
运行项目。应用程序将弹出一个对话框,请求用户允许应用程序访问麦克风设备,如下所示:
图 3 请求用户权限的对话框
点击“允许”单选按钮并勾选“记住”是安全的。如果您已勾选“记住”,下次运行应用程序时将不会再次显示此提示。您可以选择不勾选“记住”,因为此提示是一个很好的指示,表明 RecorderLib
实例已成功加载。
录制用户语音
录制用户语音就像调用 RecorderLib
的 startRecord()
方法一样简单。此方法需要一个参数,如以下代码所示:
private function startRecord():void
{
_coreRequesterParams.refText = txtRefText.text;
var recorderParams:Object =
{
serverParam:_coreRequesterParams,
recordLength:5000 // ms
};
_recorderLib.startRecord(recorderParams);
}
Blocks of code should be set as style "Formatted"
like this:
开始录音时,我们首先根据用户输入(txtRefText
.text
)更新 _coreRequesterParams
的 refText
值。然后我们设置一个 recorderParams
变量,其中包含两个属性:serverParam
是更新后的 _coreRequestParams
,而 recordLength
设置为 5000 毫秒。录音将在 5 秒后自动停止。
将“开始”按钮的点击回调设置为 startRecord()
方法。运行项目。点击“开始”按钮。如果您听到“叮”声,则表示录音现在工作正常。
以下代码手动停止录音。将其添加到“停止”按钮的点击回调中以使其工作。
_recorderLib.stopRecord();
到目前为止,录制用户语音时似乎什么也没发生。在我们深入研究捕获和解析 API 响应之前,我们首先回放我们的录音。
添加另一个标记为“开始回放”的按钮(我现在已将另外两个按钮分别重命名为“开始录音”和“停止录音”)。将其点击回调设置为:
_recorderLib.startReplay({});
RecorderLib:startReplay()
方法需要一个参数。我们传入一个空对象,要求回放最近的录音。
运行程序。首先点击“开始录音”按钮。听到“叮”声后,对着麦克风说话约 5 秒。然后点击“开始回放”按钮以听到回放。我希望到目前为止一切正常。
捕获 API 响应
是时候了解 AISpeech API 的工作流程了。SDK 将用户语音的音频数据增量发送到 API 的一个节点。API 分析音频数据并返回分数给 SDK。应用程序监听 RecorderLib 的特定事件以捕获这些响应。SDK 和 API 在录制用户语音时交换多个信号和数据。但在此演示中,我们只捕获和解析最终分数结果(通常在录音停止后捕获)。
为了捕获 API 返回的最终分数结果,我们需要监听 RecorderLib
的 CoreRequesterEvent.RESULT
。在 init()
方法中,在调用 RecorderLib::init()
方法之前,我们添加以下行:
_recorderLib.addEventListener(CoreRequesterEvent.RESULT, coreRequesterEventHandler);
如果 IDE 没有为您导入 com.aispeech.events.CoreRequesterEvent
,请导入它。
然后我们实现 coreRequesterEventHandler
方法如下:
private function coreRequesterEventHandler(event:CoreRequesterEvent):void
{
var strResult:String = new JSONEncoder(event.data).getString();
Alert.show(strResult);
}
如果 IDE 没有为您导入 com.adobe.serialization.json.JSONEncoder
和 mx.controls.Alert
,请导入它们。
很明显,API 在 event.data
中返回结果,它反过来是一个键值格式的 ActionScript 对象。为了显示目的,我们将其转换为 JSON 字符串,并使用 Alert.show
方法显示。它看起来像下图:
图 4 显示所有 API 返回
它显示了大量信息,这意味着 API 返回了相当丰富的评估结果。API 返回的数据结构定义良好,但截至本文撰写时,在线文档只有中文版本。对于此演示,我们将仅解析每个单词的分数以进行演示。
解析每个单词的分数
在 coreRequesterEventHandler
方法中设置一个断点,我们将使用 Flash Builder 调试器查看 API 返回。
如图 5 所示,event.data 对象有一个“result
”字段,其中有一个“details
”数组对象。 “details
”数组的每个元素对应于参考文本中的一个单词,在本例中是“I want to play piano.”。因此,我们看到“details
”数组包含五个元素(五个单词)。
图 5 API 返回的数据结构
“details
”数组的每个元素都有一个 char
字段和一个 score
字段,如图 6 所示。我们对这两个字段感兴趣。
图 6 “details”数组元素的数据结构
所以逻辑很简单:我们从“details
”数组的每个元素中提取 char
和 score
,然后将这些结果添加到我们定义的 ArrayCollection
_scores
中。由于 _scores
绑定到分数图表,因此图表将在收到 API 结果后自动更新。
两个实现细节:首先,我们希望在添加新结果之前清除 _scores
;其次,我们以相反的顺序添加结果,以便使单词沿图表的垂直轴从上到下排列。
代码如下:
private function coreRequesterEventHandler(event:CoreRequesterEvent):void
{
_scores.removeAll();
var details:Array = event.data.result.details;
var len:int = details.length;
for (var i:int = len - 1; i >=0; i --)
{
_scores.addItem({Word:details[i].char, Score:details[i].score});
}
}
完成后的应用程序将如下所示:
图 7 完成后的应用程序
结论
此演示到此结束。
但是使用 AISpeech API ASSDK 还有更多细节,例如处理异常和使用其他语音核心(例如语音识别)。请注意,此演示完全不涉及异常处理。因此,在遵循本教程时,如果您遇到任何问题,请随时发表评论。
我正在向 AI Speech Ltd 申请英文在线文档。
此演示的源代码位于 github。
有关 AISpeech API 的更多信息,请访问 blog.aispeech.com
感谢阅读。
历史
这是本文的第一版。