| 知乎专栏 |
目录
// 写入文本
// byte[] content= "你好".getBytes();
// String params = "data_type=text";
// AIUIMessage msg = new AIUIMessage(AIUIConstant.CMD_WRITE, 0, 0, "tag=write_data_1", content);
// mAIUIAgent.sendMessage(msg);
AIUIMessage aiuiMessage = new AIUIMessage(0, 0, 0, "", null);
aiuiMessage.msgType = AIUIConstant.CMD_WRITE;
aiuiMessage.arg1 = 0;
aiuiMessage.arg2 = 0;
// 在输入参数中设置tag,则对应结果中也将携带该tag,可用于关联输入输出
aiuiMessage.params = "data_type=text,tag=text-tag";
aiuiMessage.data = "天气".getBytes(StandardCharsets.UTF_8);
mAIUIAgent.sendMessage(aiuiMessage);
package cn.netkiller.aiui;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.iflytek.aiui.player.common.data.MetaItem;
import com.iflytek.aiui.player.core.AIUIPlayer;
import com.iflytek.aiui.player.core.PlayState;
import com.iflytek.aiui.player.core.PlayerListener;
import com.iflytek.aiui.player.players.KuwoMusicRemote;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function2;
public class MusicSkillComponent {
private static final String TAG = MusicSkillComponent.class.getSimpleName();
private static MusicSkillComponent musicSkillComponent = null;
private static String kuwoParams = null;
private static int playListIndex = 0; //当前播放歌曲序号
private static JSONArray mPlayList = null; //播放列表
private static AIUIPlayer mAIUIPlayer = null;
private static KuwoMusicRemote kuwoRemote = null;
private final Context context;
private final PlayerListener mPlayListener = new PlayerListener() {
@Override
public void onMediaUrl(@NonNull JSONObject jsonObject) {
Log.d(TAG, "onMediaUrl: " + jsonObject);
}
@Override
public void onPlayerReady() {
Log.i(TAG, "onPlayerReady()");
}
@Override
public void onStateChange(@NonNull PlayState state) {
Log.i(TAG, "onStateChange: PlayState is" + state);
switch (state) {
case READY:
Log.d(TAG, "AIUIPlayer 播放准备就绪");
break;
case PLAYING:
Log.d(TAG, "播放");
break;
case PAUSED:
Log.d(TAG, "停止");
break;
case LOADING:
Log.d(TAG, "音乐加载中……");
break;
case COMPLETE:
Log.d(TAG, "继续");
startPlayMusic();
break;
case IDLE:
long currentPosition = mAIUIPlayer.getCurrentPosition();
Log.d(TAG, String.format("CurrentPosition: %l", currentPosition));
break;
case ERROR:
Log.d(TAG, "播放出错");
break;
default:
break;
}
}
@Override
public void onMediaChange(@NonNull MetaItem metaItem) {
String songName = metaItem.getTitle(); //歌名
String author = metaItem.getAuthor(); //作者
playListIndex = getPlayIndex(songName);
Log.d(TAG, "onMediaChange: " + metaItem);
}
@Override
public void onError(int code, @NonNull String info) {
Log.e(TAG, "onError 播放出错:" + code + " ,错误信息为:" + info);
// 真实错误码需要从 info 中解析 "track link failed code: 40006 description:"
if (info.isEmpty()) {
if (code == 200001) {
Log.d(TAG, "歌曲\"" + "" + "\"播放出错: " + code + "\nINFO:产品未通过酷我验收,仅支持获取奇数id资源\n");
if (!mAIUIPlayer.next()) {
}
}
}
}
@Override
public void onPlayerRelease() {
}
};
public MusicSkillComponent(Context context) {
this.context = context;
initSDK();
}
public synchronized static MusicSkillComponent getInstance(Context context) {
if (musicSkillComponent == null) {
musicSkillComponent = new MusicSkillComponent(context);
}
return musicSkillComponent;
}
public boolean previous() {
if (mAIUIPlayer != null) {
return mAIUIPlayer.previous();
}
return false;
}
public boolean next() {
if (mAIUIPlayer != null) {
return mAIUIPlayer.next();
}
return false;
}
public void pause() {
if (mAIUIPlayer == null) {
return;
}
if (mAIUIPlayer.getCurrentState() == PlayState.PLAYING) {
mAIUIPlayer.pause();
}
}
public void resume() {
if (mAIUIPlayer == null) {
return;
}
if (mAIUIPlayer.getCurrentState() == PlayState.PAUSED) {
mAIUIPlayer.resume();
}
}
public boolean play(@NonNull JSONObject object) {
// Log.d(TAG, object.toString());
try {
JSONArray musics = object.getJSONArray("result");
if (null != musics) {
mPlayList = musics;
playListIndex = 0;
}
return startPlayMusic();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
public void initSDK() {
//TODO 开发者需要实现生成sn的代码,参考:https://www.yuque.com/iflyaiui/zzoolv/tgftb5
//注意事项1: sn每台设备需要唯一!!!!WakeupEngine的sn和AIUI的sn要一致
//注意事项2: 获取的值要保持稳定,否则会重复授权,浪费授权量
String serialNumber = "test";
String appId = "c84e1ddb";
String appKey = "7a1583c3190b83fe4d62573ee9cfbfc1";
//TODO 设置酷我音乐SDK设置相关参数,appid和appkey请使用自己的进行开发,并且与aiui.cfg一致
kuwoParams = "appId=" + appId + ",appKey=" + appKey + "," + "serialNumber=" + serialNumber + ",deviceModel=" + serialNumber + ",userId=" + serialNumber;
if (null == kuwoRemote) {
kuwoRemote = new KuwoMusicRemote(kuwoParams);
// 酷我SDK日志开关 :true 打开,false 关闭
kuwoRemote.setDebug(false);
if (null != kuwoRemote) {
Log.i(TAG, "KuwoRemote 初始化成功");
}
}
if (null == mAIUIPlayer) {
mAIUIPlayer = new AIUIPlayer(context, kuwoParams);
// 播放前焦点占用设置
mAIUIPlayer.setParameter("customAudioFocus", "true");
// 回调信息设置
mAIUIPlayer.addListener(mPlayListener);
// AIUIPlayer SDK调试日志设置 :true 打开,false 关闭
mAIUIPlayer.setDebug(false);
// 初始化播放器
mAIUIPlayer.initialize();
Log.i(TAG, "AIUIPlayer 初始化成功");
}
}
public void release() {
mPlayList = null;
if (null != mAIUIPlayer) {
mAIUIPlayer.release();
mAIUIPlayer = null;
}
if (null != kuwoRemote) {
kuwoRemote.destroy();
kuwoRemote = null;
}
}
private void activate() {
// if (isActivated) {
//// showToast("当前设备已激活酷我音乐");
// return;
// }
kuwoRemote.active(() -> {
Log.i(TAG, "激活成功");
return null;
}, (errCode, errInfo) -> {
Log.i(TAG, "激活失败,错误码为:" + errCode + " ,信息为: " + errInfo);
return null;
});
}
private void login() {
//酷我不强制用户登陆,开发者自己实现登陆代码,可参考下方酷狗音乐代码,改一下接口
// Intent intent = new Intent(KuwoDemo.this, LoginActivity.class);
// startActivityForResult(intent, 3);
}
private void logout() {
kuwoRemote.logout(new Function0<Unit>() {
@Override
public Unit invoke() {
Log.i(TAG, "酷我账号退出成功");
// LoginBtn.setText("手机登陆");
return null;
}
}, new Function2<Integer, String, Unit>() {
@Override
public Unit invoke(Integer errCode, String errInfo) {
Log.i(TAG, "酷我账号退出失败,错误码为:" + errCode + " ,信息为: " + errInfo);
return null;
}
});
}
public void stop() {
if (mAIUIPlayer != null) {
mAIUIPlayer.stop();
}
}
private boolean startPlayMusic() {
if (null == mPlayList || mPlayList.length() == 0) {
Log.w(TAG, "播放列表为空");
return false;
}
Log.i(TAG, "mPlayList is: " + mPlayList.toString());
mAIUIPlayer.reset();
return mAIUIPlayer.play(mPlayList, "musicX", "", false, playListIndex);
}
//构建虚假播放信息测试AIUIPlayer SDK播放是否可以正常调用
// private void mockPlayMusic() {
// try {
// JSONArray musiclist = new JSONArray();
// JSONObject music = new JSONObject();
// music.put("source", "kuwo");
// music.put("songname", "天地龙鳞");
// music.put("itemid", "353833243");
// musiclist.put(0, music);
// mPlayList = musiclist;
// } catch (JSONException e) {
// e.printStackTrace();
// }
//
// if (null == mPlayList || mPlayList.length() == 0) {
//// showToast("播放列表为空");
// return;
// }
// Log.i(TAG, "mPlayList is:\n" + mPlayList.toString());
// mAIUIPlayer.reset();
// mAIUIPlayer.play(mPlayList, "musicX", "", false, playListIndex);
// }
// 获取当前播放下标
private int getPlayIndex(String songName) {
if (mPlayList != null) {
try {
String playData = null;
for (int i = 0; i < mPlayList.length(); i++) {
playData = mPlayList.getJSONObject(i).toString();
if (playData.contains(songName)) {
return i;
}
}
} catch (JSONException e) {
e.printStackTrace();
return 0;
}
}
return 0;
}
}
通过 itemId 获取 audio URL
kuwoRemote.getAudioUrl("26383685", "128kmp3", new Function1<AudioUrl, Unit>() {
@Override
public Unit invoke(AudioUrl audioUrl) {
Log.d(TAG, audioUrl.toString());
return null;
}
}, new Function2<Integer, String, Unit>() {
@Override
public Unit invoke(Integer code, String msg) {
Log.d(TAG, "Code: " + code + ", Msg: " + msg);
return null;
}
});
日志输出结果
AudioUrl(expiretime=, itemid=26383685, source=kuwo, audiopath=http://other.player.ri01.sycdn.kuwo.cn/6dcbdb125c72dfff3978fe29ab50fdd4/64eeef6f/resource/n2/27/48/2060696053.mp3)
package cn.netkiller.skill;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import java.text.NumberFormat;
import java.text.ParseException;
public class ControlSkillComponent {
private static final String TAG = ControlSkillComponent.class.getName();
private final Context context;
private MusicSkillComponent musicSkillComponent = null;
public ControlSkillComponent(Context context, JSONObject object) {
this.context = context;
musicSkillComponent = MusicSkillComponent.getInstance(context);
Log.d(TAG, "控制技能: " + object);
String semanticIntent = object.getString("intent");
switch (semanticIntent) {
case "PAUSE":
musicSkillComponent.pause();
break;
case "CHOOSE_NEXT":
musicSkillComponent.next();
break;
case "CHOOSE_PREVIOUS":
musicSkillComponent.previous();
break;
case "VOLUME_MINUS":
this.volume("VOLUME_MINUS");
break;
case "VOLUME_PLUS":
this.volume("VOLUME_PLUS");
break;
case "VOLUME_MIN":
this.volume("VOLUME_MIN");
break;
case "VOLUME_MAX":
this.volume("VOLUME_MAX");
break;
case "MUTE":
this.volume("MUTE");
break;
case "VOLUME_SET":
JSONObject slots = (JSONObject) object.getJSONArray("slots").get(0);
String stringPercent = slots.getString("value");
try {
double doublePercent = (Double) NumberFormat.getPercentInstance().parse(stringPercent);
// int percent = floatPercent.intValue();
this.volume(doublePercent);
Log.d(TAG, String.valueOf(doublePercent));
} catch (ParseException e) {
Log.e(TAG, e.toString());
}
break;
case "SETTING_OPEN":
Log.e(TAG, "设置无线网络");
this.wifi();
break;
case "SHUTDOWN":
break;
case "RESET":
break;
}
}
public void wifi() {
// context.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
Intent intent = new Intent();
intent.setAction("androad.network.wlan");
intent.putExtra("message", "");
context.sendBroadcast(intent);
}
private void volume(String control) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
// int minVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
int minVolume = 10;
int stepVolume = 5;
int currentMusicVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int currentTTSVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
switch (control) {
case "VOLUME_MINUS": //步进减小
currentMusicVolume -= stepVolume;
if (currentMusicVolume < minVolume) {
currentMusicVolume = minVolume;
}
currentTTSVolume -= stepVolume;
if (currentTTSVolume < minVolume) {
currentTTSVolume = minVolume;
}
break;
case "VOLUME_PLUS": //步进累加
currentMusicVolume += stepVolume;
if (currentMusicVolume >= maxVolume) {
currentMusicVolume = maxVolume;
}
currentTTSVolume += stepVolume;
if (currentTTSVolume > maxVolume) {
currentTTSVolume = maxVolume;
}
break;
case "VOLUME_MAX": // 最大
currentMusicVolume = currentTTSVolume = maxVolume;
break;
case "VOLUME_MIN": //最小
currentMusicVolume = currentTTSVolume = minVolume;
break;
case "MUTE": //静音
currentMusicVolume = currentTTSVolume = minVolume;
break;
}
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentMusicVolume, AudioManager.FLAG_SHOW_UI);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, currentTTSVolume, AudioManager.FLAG_PLAY_SOUND);
Log.d(TAG, String.format("volume: currentMusicVolume=%s, currentTTSVolume=%s, maxVolume=%s", currentMusicVolume, currentTTSVolume, maxVolume));
}
private void volume(double percent) {
if (percent < 0.3) {
return;
}
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int currentMusicVolume, currentTTSVolume;
currentMusicVolume = currentTTSVolume = (int) (maxVolume * percent);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentMusicVolume, AudioManager.FLAG_SHOW_UI);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, currentTTSVolume, AudioManager.FLAG_PLAY_SOUND);
Log.d(TAG, String.format("volume: currentMusicVolume=%s, currentTTSVolume=%s, maxVolume=%s", currentMusicVolume, currentTTSVolume, maxVolume));
}
}
implementation 'com.belerweb:pinyin4j:2.5.1'
package cn.netkiller.ai.utils;
import android.util.Log;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public class Pinyin {
private static final String TAG = Pinyin.class.getName();
public static String toPinyin(String hanzi) {
char[] chars = hanzi.trim().toCharArray();
String hanyupinyin = "";
//输出格式设置
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
/**
* 输出大小写设置
*
* LOWERCASE:输出小写
* UPPERCASE:输出大写
*/
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
/**
* 输出音标设置
*
* WITH_TONE_MARK:直接用音标符(必须设置WITH_U_UNICODE,否则会抛出异常)
* WITH_TONE_NUMBER:1-4数字表示音标
* WITHOUT_TONE:没有音标
*/
// defaultFormat.setToneType(HanyuPinyinToneType.WITH_TONE_MARK); // 必须设置WITH_U_UNICODE,否则会抛出异常
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
/**
* 特殊音标ü设置
*
* WITH_V:用v表示ü
* WITH_U_AND_COLON:用"u:"表示ü
* WITH_U_UNICODE:直接用ü
*/
// defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
// 中文的正则表达式
String hanziRegex = "[\\u4E00-\\u9FA5]+";
try {
for (int i = 0; i < chars.length; i++) {
// 判断为中文,则转换为汉语拼音
if (String.valueOf(chars[i]).matches(hanziRegex)) {
hanyupinyin += PinyinHelper
.toHanyuPinyinStringArray(chars[i], defaultFormat)[0];
} else {
// 不为中文,则不转换
hanyupinyin += chars[i];
}
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
Log.e(TAG, "字符不能转成汉语拼音");
}
return hanyupinyin;
}
}
package com.iflytek.mscv5plusdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.widget.Toast;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.speech.setting.TtsSettings;
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
tts();
}
private InitListener initListener = new InitListener() {
@Override
public void onInit(int code) {
Log.d("TAG", "InitListener init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
} else {
// 初始化成功,之后可以调用startSpeaking方法
// 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,
// 正确的做法是将onCreate中的startSpeaking调用移至这里
}
}
};
private SpeechSynthesizer speechSynthesizer;
private void setParam() {
// Log.d("", String.valueOf(speechSynthesizer.isSpeaking()));
// 清空参数
speechSynthesizer.setParameter(SpeechConstant.PARAMS, null);
//设置合成
// if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
//设置使用云端引擎
speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
//设置发音人
speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
// } else if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
// //设置使用本地引擎
// speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
// //设置发音人资源路径
// speechSynthesizer.setParameter(ResourceUtil.TTS_RES_PATH, getResourcePath());
// //设置发音人
// speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, voicerLocal);
// } else {
// speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_XTTS);
// //设置发音人资源路径
// speechSynthesizer.setParameter(ResourceUtil.TTS_RES_PATH, getResourcePath());
// //设置发音人
// speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, voicerXtts);
// }
//mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY,"1");//支持实时音频流抛出,仅在synthesizeToUri条件下支持
//设置合成语速
// speechSynthesizer.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
// //设置合成音调
// speechSynthesizer.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
// //设置合成音量
// speechSynthesizer.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
// //设置播放器音频流类型
// speechSynthesizer.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));
// mTts.setParameter(SpeechConstant.STREAM_TYPE, AudioManager.STREAM_MUSIC+"");
// 设置播放合成音频打断音乐播放,默认为true
speechSynthesizer.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
speechSynthesizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
speechSynthesizer.setParameter(SpeechConstant.TTS_AUDIO_PATH,
getExternalFilesDir("msc").getAbsolutePath() + "/tts.pcm");
}
public void tts() {
speechSynthesizer = SpeechSynthesizer.createSynthesizer(this, initListener);
// 设置参数
// setParam();
// Log.d(TAG, "准备点击: " + System.currentTimeMillis());
String text = "你好小虎";
setParam();
speechSynthesizer.stopSpeaking();
int code = speechSynthesizer.startSpeaking(text, synthesizerListener);
// /**
// * 只保存音频不进行播放接口,调用此接口请注释startSpeaking接口
// * text:要合成的文本,uri:需要保存的音频全路径,listener:回调接口
// */
// String path = getExternalFilesDir("msc").getAbsolutePath() + "/tts.pcm";
// int code = mTts.synthesizeToUri(text, path, mTtsListener);
if (code != ErrorCode.SUCCESS) {
showTip("语音合成失败,错误码: " + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
}
//
//
// mTts.pauseSpeaking();
//
// mTts.resumeSpeaking();
}
SynthesizerListener synthesizerListener = new SynthesizerListener() {
@Override
public void onSpeakBegin() {
showTip("开始播放");
// Log.d(TtsDemo.TAG, "开始播放:" + System.currentTimeMillis());
}
@Override
public void onSpeakPaused() {
showTip("暂停播放");
}
@Override
public void onSpeakResumed() {
showTip("继续播放");
}
@Override
public void onBufferProgress(int percent, int beginPos, int endPos,
String info) {
// 合成进度
// mPercentForBuffering = percent;
// showTip(String.format(getString(R.string.tts_toast_format),mPercentForBuffering, mPercentForPlaying));
}
@Override
public void onSpeakProgress(int percent, int beginPos, int endPos) {
// 播放进度
// mPercentForPlaying = percent;
// showTip(String.format(getString(R.string.tts_toast_format),
// mPercentForBuffering, mPercentForPlaying));
}
@Override
public void onCompleted(SpeechError error) {
if (error == null) {
showTip("播放完成");
} else {
showTip(error.getPlainDescription(true));
}
}
@Override
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
// 若使用本地能力,会话id为null
if (SpeechEvent.EVENT_SESSION_ID == eventType) {
String sid = obj.getString(SpeechEvent.KEY_EVENT_AUDIO_URL);
// Log.d(TAG, "session id =" + sid);
}
//实时音频流输出参考
/*if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
Log.e("MscSpeechLog", "buf is =" + buf);
}*/
}
};
private void showTip(final String str) {
Toast mToast;
// if (mToast != null) {
// mToast.cancel();
// }
mToast = Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT);
mToast.show();
}
}
package cn.netkiller.album.religion.ai;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.iflytek.cloud.RequestListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.VoiceWakeuper;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;
import com.iflytek.cloud.util.ResourceUtil;
import java.nio.charset.StandardCharsets;
import cn.netkiller.album.religion.ContextHolder;
import cn.assets.album.religion.R;
public class Wakeup {
private static final String TAG = Wakeup.class.getSimpleName();
private final int curThresh = 1450;
private final String threshStr = "门限值:";
private final String keep_alive = "1";
private final String ivwNetMode = "0";
private final Context context;
// 查询资源请求回调监听
private final RequestListener requestListener = new RequestListener() {
@Override
public void onEvent(int eventType, Bundle params) {
// 以下代码用于获取查询会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
//if(SpeechEvent.EVENT_SESSION_ID == eventType) {
// Log.d(TAG, "sid:"+params.getString(SpeechEvent.KEY_EVENT_SESSION_ID));
//}
}
@Override
public void onCompleted(SpeechError error) {
if (error != null) {
Log.d(TAG, "error:" + error.getErrorCode());
showTip(error.getPlainDescription(true));
}
}
@Override
public void onBufferReceived(byte[] buffer) {
try {
String resultInfo = new String(buffer, StandardCharsets.UTF_8);
Log.d(TAG, "resultInfo:" + resultInfo);
// JSONTokener tokener = new JSONTokener(resultInfo);
// JSONObject object = new JSONObject(tokener);
//
// int ret = object.getInt("ret");
// if (ret == 0) {
// String uri = object.getString("dlurl");
// String md5 = object.getString("md5");
// Log.d(TAG, "uri:" + uri);
// Log.d(TAG, "md5:" + md5);
// showTip("请求成功");
// }
} catch (Exception e) {
e.printStackTrace();
}
}
};
private VoiceWakeuper voiceWakeuper;
// 唤醒结果内容
private String resultString;
private final WakeuperListener wakeuperListener = new WakeuperListener() {
@Override
public void onResult(WakeuperResult result) {
Log.d(TAG, "onResult");
try {
String text = result.getResultString();
Log.d(TAG, text);
// JSONObject object;
// object = new JSONObject(text);
// StringBuffer buffer = new StringBuffer();
// buffer.append("【RAW】 " + text);
// buffer.append("\n");
// buffer.append("【操作类型】" + object.optString("sst"));
// buffer.append("\n");
// buffer.append("【唤醒词id】" + object.optString("id"));
// buffer.append("\n");
// buffer.append("【得分】" + object.optString("score"));
// buffer.append("\n");
// buffer.append("【前端点】" + object.optString("bos"));
// buffer.append("\n");
// buffer.append("【尾端点】" + object.optString("eos"));
// resultString = buffer.toString();
showTip(text);
} catch (Exception e) {
resultString = "结果解析出错";
e.printStackTrace();
}
}
@Override
public void onError(SpeechError error) {
showTip(error.getPlainDescription(true));
}
@Override
public void onBeginOfSpeech() {
}
@Override
public void onEvent(int eventType, int isLast, int arg2, Bundle obj) {
// EVENT_RECORD_DATA 事件仅在 NOTIFY_RECORD_DATA 参数值为 真 时返回
if (eventType == SpeechEvent.EVENT_RECORD_DATA) {
final byte[] audio = obj.getByteArray(SpeechEvent.KEY_EVENT_RECORD_DATA);
Log.i(TAG, "ivw audio length: " + audio.length);
}
}
@Override
public void onVolumeChanged(int volume) {
}
};
// 设置门限值 : 门限值越低越容易被唤醒
public Wakeup() {
this.context = ContextHolder.getContext();
// String param = "appid=" + context.getString(R.string.app_id) + "," + SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC;
// SpeechUtility.createUtility(context, param);
voiceWakeuper = VoiceWakeuper.createWakeuper(context, null);
if (null == voiceWakeuper) {
// 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
Toast.makeText(context
, "创建对象失败,请确认 libmsc.so 放置正确,\n 且有调用 createUtility 进行初始化"
, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "准备唤醒", Toast.LENGTH_LONG).show();
// 清空参数
voiceWakeuper.setParameter(SpeechConstant.PARAMS, null);
// 唤醒门限值,根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
voiceWakeuper.setParameter(SpeechConstant.IVW_THRESHOLD, "0:1450");
// 设置唤醒模式
voiceWakeuper.setParameter(SpeechConstant.IVW_SST, "wakeup");
// 设置持续进行唤醒
voiceWakeuper.setParameter(SpeechConstant.KEEP_ALIVE, "1");
// 设置闭环优化网络模式
voiceWakeuper.setParameter(SpeechConstant.IVW_NET_MODE, "1");
// 设置唤醒资源路径
voiceWakeuper.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
// 设置唤醒录音保存路径,保存最近一分钟的音频
voiceWakeuper.setParameter(SpeechConstant.IVW_AUDIO_PATH,
context.getExternalFilesDir("msc").getAbsolutePath() + "/ivw.wav");
voiceWakeuper.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
// 如有需要,设置 NOTIFY_RECORD_DATA 以实时通过 onEvent 返回录音音频流字节
//voiceWakeuper.setParameter( SpeechConstant.NOTIFY_RECORD_DATA, "1" );
// 启动唤醒
/* voiceWakeuper.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");*/
}
}
public void startListening(WakeuperListener wakeuperListener) {
//非空判断,防止因空指针使程序崩溃
voiceWakeuper = VoiceWakeuper.getWakeuper();
if (voiceWakeuper != null) {
resultString = "";
voiceWakeuper.startListening(wakeuperListener);
} else {
showTip("唤醒未初始化");
}
}
private void stopListening() {
voiceWakeuper = VoiceWakeuper.getWakeuper();
if (voiceWakeuper != null) {
voiceWakeuper.stopListening();
}
}
public void cancel() {
// 销毁合成对象
voiceWakeuper = VoiceWakeuper.getWakeuper();
if (voiceWakeuper != null) {
voiceWakeuper.cancel();
}
}
public void destroy() {
// 销毁合成对象
voiceWakeuper = VoiceWakeuper.getWakeuper();
if (voiceWakeuper != null) {
voiceWakeuper.destroy();
}
}
private String getResource() {
final String resPath = ResourceUtil.generateResourcePath(context, ResourceUtil.RESOURCE_TYPE.assets, "ivw/" + context.getString(R.string.app_id) + ".jet");
Log.d(TAG, "resPath: " + resPath);
return resPath;
}
/**
* 查询闭环优化唤醒资源
* 请在闭环优化网络模式1或者模式2使用
*/
// public void queryResource() {
// int ret = voiceWakeuper.queryResource(getResource(), requestListener);
// showTip("updateResource ret:" + ret);
// }
private void showTip(final String str) {
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
Toast.makeText(context.getApplicationContext(), str, Toast.LENGTH_SHORT).show();
// }
// });
}
}