搜狗语音云开发入门(二)——使用离线语音识别服务

1 简介

之前在《搜狗语音云开发入门--移动端轻松添加高大上的语音识别》中介绍了使用搜狗语音云为客户端程序添加在线语音识别服务。在线语音服务需要联网使用,但是你不能指望用户拥有完美的环境,事实上大多数情况下用户的外围环境都会有所限制。有的时候没有Wi-Fi、没有流量,还想使用语音识别,如果你给用户一个提示“您没开流量...”只能说你的程序弱爆了。有条件情况下给用户提供完美的服务,没有条件创造条件服务质量依然完美,并且清风徐来了无痕迹,这才是完美应用的体现。你不是用户的亲戚朋友同学战友,不是武藤苍井上原结衣小子玛利亚,不是黎明郭富城刘德华梁朝伟,也不是王朔海岩郭敬明韩寒,这些你统统不是。但你做的应用还是能让人喜欢用,赶都赶不走,那就是能力。不好意思扯远了。

2 提供的服务

离线语音识别服务由两部分组成:搜狗离线语音识别引擎和开发API。不能联网,语音引擎就转到你本地了。而通过调用API,可以操作离线语音识别Service,对离线语音识别Service执行start、bind和unbind等操作。还可以获取结果,通过向Service发请求,获取离线语音识别结果或者出错信息。

3 如何使用

3.1 使用步骤

离线语音识别服务没有快速体验,所以需要使用必须进行服务的常规申请。

登陆搜狗语音云开放平台

如图,首先点击“开发者专区”,选择“离线识别”,然后填写详细的应用信息与开发者信息。这里要注意的是,一定要准确填写你的“应用包名”,否则识别有问题。

申请之后,语音云官方会进行审核,不过这个审核是需要一点时间的,一般是4天左右。有需要的朋友们,还等什么,赶快先申请着再说!

审核过程中,你随时可以点击右上角:账号 - 我的应用,查看审核结果。成功之后会有:

可以看到基本信息列出来了,然后点击“应用信息”:

关键是“appId”与“access-key”这两项,程序调用的时候需要用到,记得保存好。

3.2 调用服务

在调用服务之前,需要先将SDK服务和服务文档下载下来:

分别点击“SDK下载”中的“下载SDK”和“开发文档”,将两份文件下载:

将SDK压缩文件解压后,里面有一个libs文件夹,进入后可以看到里面的文件:

将它们放入你的Android工程的libs里面,并在工程中将sogou-speechapi-offline-v1.0.jar引入Build Path。

下载搜狗离线语音识别引擎。程序中的API正是调用的该引擎中的服务。注意,首次使用或者使用次数达到上限时,需要进行联网认证,其它时候离线即可提供服务。

接下来关注我们的Android工程。修改AndroidManifest.xml,需要确保app具有以下权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><span style="font-family: 宋体; background-color: rgb(255, 255, 255);"> </span>

在Android中添加布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.testyuyinoffline.MainActivity" >

        <RelativeLayout
            android:id="@id/textLayout"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content" >
	        <TextView
	            android:id="@id/statusLabel"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_marginTop="20dip"
	            android:layout_marginLeft="30dip"
	            android:layout_alignParentLeft="true"
	            android:text="@string/statusLabel" />

	        <TextView
	            android:id="@id/statusTextTv"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_marginTop="20dip"
	            android:layout_marginRight="20dip"
	            android:layout_alignParentRight="true"
	            android:text="@string/statusText" />

	        <TextView
	            android:id="@id/toSayLabelTv"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_marginTop="20dip"
	            android:layout_marginLeft="30dip"
	            android:layout_alignParentLeft="true"
	            android:layout_below="@id/statusLabel"
	            android:text="@string/toSayLabel" />

	        <TextView
	            android:id="@id/toSayTextTv"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_marginTop="20dip"
	            android:layout_marginRight="20dip"
	            android:layout_alignParentRight="true"
	            android:layout_below="@id/statusTextTv"
	            android:text="@string/toSayText" />
        </RelativeLayout>

        <Button
            android:id="@id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dip"
            android:layout_centerHorizontal="true"
            android:text="@string/clickMe" />

</RelativeLayout>

布局中,我们放入4个TextView,分别用来标记和显示服务请求的状态、识别内容,然后再放置一个按钮,用来启动识别服务。

下面我们来看看activity中的调用代码:

package com.example.testyuyinoffline;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.sogou.speech.offlinelistener.OutsideCallListener;
import com.sogou.speech.offlineutility.CoreControl;

public class MainActivity extends Activity {

	public static final String MSG_TEXT = "MSG_TEXT";
	CoreControl coreControl;
	TextView statusTextTView;
	TextView toSayTextTvTextView;

	Runnable regThread = new Runnable() {

		@Override
		public void run() {
			coreControl.startListening();
		}
	};

	Handler handler = new Handler() {
		@Override
		public void handleMessage(android.os.Message msg) {
			System.out.println("what=" + msg.what);
			switch (msg.what) {
			// 1.开始识别
			case 0x1:
				statusTextTView.setText("开始识别!");
				break;
			// 2.认证成功
			case 0x2:
				statusTextTView.setText("认证成功,请说话!");
				break;
			// 3.录音结束
			case 0x3:
				statusTextTView.setText("录音结束!");
				break;
			// 4.说话内容
			case 0x4:
				String text = msg.getData().getString(MSG_TEXT);
				toSayTextTvTextView.setText(text);
				break;
			default:
				break;
			}
		}
	};

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();

		if (coreControl != null) {
			coreControl.onDestroyService();
			System.out.println("断开语音service");
		}
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		Button button = (Button) findViewById(R.id.button);
		statusTextTView = (TextView) findViewById(R.id.statusTextTv);
		toSayTextTvTextView = (TextView)findViewById(R.id.toSayTextTv);

		coreControl = new CoreControl(this.getApplicationContext(),
				(TelephonyManager) this.getSystemService(TELEPHONY_SERVICE),
				"<span style="background-color: rgb(255, 0, 0);">appId</span>", "<span style="background-color: rgb(255, 0, 0);">access-key</span>");

		coreControl.setmListener(new OutsideCallListener() {

			@Override
			public void onUpdateVolume(int arg0) {
				// TODO Auto-generated method stub

			}

			// 3.录音结束
			@Override
			public void onSpeechEnd() {
				// TODO Auto-generated method stub
				Bundle bundle = new Bundle();
				bundle.putString(MSG_TEXT, "录音结束");
				Message msg = handler.obtainMessage();
				msg.what = 0x3;
				msg.setData(bundle);
				msg.sendToTarget();

				System.out.println("3.录音结束");
			}

			@Override
			public void onServiceConnected(String arg0) {
				// TODO Auto-generated method stub

			}

			// 4.说话内容
			@Override
			public void onResults(String arg0, boolean arg1) {
				Bundle bundle = new Bundle();
				bundle.putString(MSG_TEXT, arg0);
				Message msg = handler.obtainMessage();
				msg.what = 0x4;
				msg.setData(bundle);
				msg.sendToTarget();

				System.out.println("4.说话内容:" + arg0);
			}

			// 1.开始识别
			@Override
			public void onRecognitionStart() {
				Bundle bundle = new Bundle();
				bundle.putString(MSG_TEXT, "开始识别!");
				Message msg = handler.obtainMessage();
				msg.what = 0x1;
				msg.setData(bundle);
				msg.sendToTarget();

				System.out.println("1.开始识别!");
			}

			// 2.认证成功
			@Override
			public void onPassedValidation() {
				Bundle bundle = new Bundle();
				bundle.putString(MSG_TEXT, "认证成功!");
				Message msg = handler.obtainMessage();
				msg.what = 0x2;
				msg.setData(bundle);
				msg.sendToTarget();

				System.out.println("2.认证成功,请说话!");
			}

			@Override
			public void onFinishInit() {
				// TODO Auto-generated method stub

			}

			@Override
			public void onError(int arg0) {
				System.err.println("错误代码:" + arg0);
			}
		});

		coreControl.onInitializeService();

		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (coreControl != null) {
//					coreControl.startListening();
					handler.post(regThread);
				}
			}
		});

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
}

注意将其中的“appId”和“access-key”换成你申请下来的信息值。

我们的思路是,点击按钮的时候,启动语音识别服务;语音识别的不同状态过程中,将状态情况显示在界面上;识别出说话内容之后,将内容显示在界面上。

在activity中,创建一个线程,线程开启识别服务。

在程序创建的过程中,首先新建一个CoreControl对象,将程序环境信息、appId、access-key等传进去。然后给CoreControl对象设置OutsideCallListener监听。监听中有几个比较重要的回调函数:

1.开始识别

public void onRecognitionStart()

2.认证成功

public void onPassedValidation()

3.录音结束

public void onSpeechEnd()

4.得到说话内容

public void onResults(String arg0, boolean arg1)

在这几个回调函数中,均使用handler向主线程传递状态参数。主线程的handler在其:

public void handleMessage(android.os.Message msg)

这个函数中更改界面状态,并将识别内容显示出来。当退出App时,调用onDestroyService()方法断开与Service的连接:

protected void onDestroy()

在出现异常的回调函数中:

public void onError(int arg0)

可以错误码打印到后台或返回到前端,以便分析错误种类。错误码定义:

很简单不是吗!

3.3 客户端使用

启动后界面:

点击“我要说话”:

对着麦克风说话后:

更详细的内容可以参考搜狗的示例程序及SDK文档。赶快试一试吧!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 22:57:27

搜狗语音云开发入门(二)——使用离线语音识别服务的相关文章

搜狗语音云开发入门--移动端轻松添加高大上的语音识别

1 简介 搜狗语音云基于自主开发.领先业内的语音技术,力求为广大开发者提供最优质的语音服务,开发者只需简单集成语音云控件, 就可以通过API调用搜狗语音云服务,获得搜狗强大的语音技术支持,更加专注于业务需求的开发. 2 提供的服务 在线语音识别技术: 官方语:该技术让计算机可以"听懂"人类语音,通过机器将语音信号转变为相应的文本. 说白了:就是联网解析语音为文本. 离线语音识别技术: 官方语:该技术通过本地离线语音包直接将语音输入识别转变为文字,从而代替云端服务器功能. 说白了:就是离

微信小程序云开发入门到发布上线

初始化项目 起步说明[非小白教程] 适合人群[建议快速看文档,对着写一遍] 看过官方文档,并简单的写过 起步教程 云开发文档 熟悉vue/es6 小程序注册[微信公众平台] 获取appid[微信公众平台-开发-开发设置] 新建小程序云开发项目 新建项目选择一个空目录,填入 AppID(使用云开发能力必须填写 AppID) 勾选创建 "小程序云开发 " 点击新建即可得到一个展示云开发基础能力的示例小程序. 该小程序与普通 QuickStart 小程序有以下不同需注意: 无游客模式.也不可

Node.js开发入门—使用AngularJS内置服务

在上一篇,"AngularJS简单示例"中演示了一个非常简单的使用Angular的小demo,那篇已经太长,原本要介绍的一些内容只好单另开篇了.这些内容,就是如何使用Angular服务. 我们还是基于"AngularJS简单示例"中的示例来改造一下.新的示例,能从Node.js+Express构造的服务器上获取管理菜单.为了实现这个,需要做几部分改造: 服务器提供adminMenu的下载功能,需要修改app.js,处理路由 修改Angular实现的控制器x-cont

JavaWeb开发入门(二)

web应用程序 web应用程序指供浏览器访问的程序,通常也简称为web应用. web应用:例如有a.html .b.html-..多个web资源,这多个web资源用于对外提供邮件服务,此时应把这多个web资源放在一个目录中,以组成一个web应用(或web应用程序). 一个web应用由多个静态web资源和动态web资源组成,如 html.css.js文件 jsp文件.java程序.支持jar包 配置文件 - 组成web应用的这些文件通常我们会使用一个目录组织,这个目录称之为web应用所在目录. T

java web开发入门二(struts)基于eclispe

JavaBean JavaBean,  咖啡豆. JavaBean是一种开发规范,可以说是一种技术. JavaBean就是一个普通的java类.只有符合以下规定才能称之为javabean: 1)必须提供无参数的构造方法 2)类中属性都必须私有化(private) 3)该类提供公开的getter 和 setter方法 getName() setName(String name) 注意: boolean类型的get方法名称叫 isXXX()方法  public boolean isAcitve()

WPF PRISM开发入门二(Unity依赖注入容器使用)

这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点击这里下载. 运行效果如下: 下面将引入Unity类库,使用Unity来生成需要的对象实例. 先查看一下CalculateRelpLoop类, public class CalculateRelpLoop : ICalculateRelpLoop { ICalculateService _calcu

VS开发入门二: VS 里提示图标的含义

VS里面的 我们写代码的过程中,有智能提示可以看到前面的小图标,初学者可以判断是什么意思哟. 1.以下是常用的几个图标 2.其他参考图标:  事件  结构  接口  枚举项  模块  映射项  内部  宏  异常  模板  映射  未知或错误  全局 原文地址:https://www.cnblogs.com/Wilson6/p/8635186.html

云开发初探 —— 更简便的小程序开发模式

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由李成熙heyli发表于云+社区专栏 李成熙,腾讯云高级工程师.2014年度毕业加入腾讯AlloyTeam,先后负责过QQ群.花样直播.腾讯文档等项目.2018年加入腾讯云云开发团队.专注于性能优化.工程化和小程序服务. 小程序诞生以来,业界关注小程序前端的技术演进较多,因此众多小程序前端的框架.工具也应运而生,前端开发效率大大提高,而后台的开发技术则关注不多,痛点不少,具体痛在哪里呢? 小程序后台开发之痛 第一个是脑袋瓜疼,怎么疼

借助云开发实现小程序短信验证码的发送

最近在做小程序验证码登陆时,用到了短信发送验证码的需求,自己也研究了下,用云开发结合云函数来实现验证码短信发送还是很方便的. 老规矩,先看效果图 这是我调用腾讯云的短信平台发送的登陆验证码.核心代码其实只有下面这么多是不是感觉实现起来特别简单,怎么说呢,我们代码调用其实就这么几行,就可以实现短信的发送,但是腾讯云短信模板的审核比较繁琐,还有我们先去申请短信模板,短信模板审核通过后才可以使用.我们就先来说代码实现,然后再带大家简单的学习下短信模板的申请. 一,安装node类库 其实我们这里用到了云