定制模型Android SDK
下载安装
SDK及示例demo下载地址: https://github.com/data-baker/BakerAndroidSdks
Android Studio集成SDK(参考demo)
-
在工程下的build.gradle文件中添加以下代码。
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
- 在主model下build.gradle文件中添加以下代码。建议使用此方式。
dependencies { implementation 'com.github.data-baker.BakerAndroidSdks:engravelib:2.0.13' implementation 'com.squareup.okhttp3:okhttp:4.2.2' implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.kailashdabhi:om-recorder:1.1.5' }
或者将.jar/.aar包添加至工程module下,lib文件夹里。
2021年6月,标贝计划开源sdk源码,所以也可以直接集成源码model。
注意:SDK内使用了okhttp、gson所以需要开发者添加以这两个库,若工程内已存在,无需重复添加。okhttp请使用4.x版本,以免出现版本兼容bug。
-
在主 Module 的
AndroidManifest.xml文件中添加网络权限。安卓6.0及以上系统版本在使用声音复刻SDK的时候,必须要申请RECORD_AUDIO和WRITE_EXTERNAL_STORAGE权限。
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- 在主Module的AndroidManifest.xml文件中的application节点添加以下属性。
android:usesCleartextTraffic="true" android:requestLegacyExternalStorage="true"
Eclipse环境也遵循相关集成jar包的方式即可。
- 关于混淆。
SDK中用到了okhttp和gson,所以需要将这两个包的混淆代码添加上。具体混淆代码可以去官方文档上查阅。如果项目中已经有这两个包的混淆代码,不必重复添加。请加上我们SDK其他类的混淆代码,如下:
-keep class com.baker.engrave.lib.bean.** { *; } -keep public class com.baker.engrave.lib.BakerVoiceEngraver{*;} -keep public class com.baker.engrave.lib.util.HLogger{*;} -keep public class com.baker.engrave.lib.net.WebSocketClient{*;} -keep public class com.baker.engrave.lib.callback.DetectCallback{*;} -keep public class com.baker.engrave.lib.callback.PlayListener{*;} -keep public class com.baker.engrave.lib.callback.InitListener{*;} -keep public class com.baker.engrave.lib.callback.MouldCallback{*;} -keep public class com.baker.engrave.lib.callback.RecordCallback{*;} -keep public class com.baker.engrave.lib.callback.UploadRecordsCallback{*;} -keep public class com.baker.engrave.lib.callback.ContentTextCallback{*;} -keep public class com.baker.engrave.lib.callback.BaseMouldCallback{*;}
背景及核心流程介绍
- 整个复刻体验闭环包含两个模块,一个模块是录音上传服务器进行声音模型训练,产出声音模型ID,另一个模块是根据声音模型ID去合成服务器合成,产出声音文件,播放声音文件完成体验。
-
此(复刻)SDK仅支持第一个模块的功能,即②③④⑤⑥⑦等功能。第二个体验的模块⑧,我们提供2种集成方式供选择,以便实现实际项目中的需求。
第一种集成方式如Demo中所示,用声音模型ID + RestAPI的形式,合成MP3声音文件,进行播放。这种合成方式适用于单次不超过250字文本长度的文本合成。
另一种方式则是声音模型ID + TTS合成SDK,具体集成方式可参考我们TTS合成SDK的接入文档。这种方式无文本长度限制,实时合成流式返回,TTS合成SDK中也有播放器功能,集成使用很方便。
SDK关键类
- BakerVoiceEngraver:声音复刻SDK关键业务处理类,SDK中单例存在。可通过BakerVoiceEngraver.getInstance()获得该实例。
- DetectCallback:环境噪音检测回调类。开启环境检测后,检测结果会实时通过回调方法返回,最终结果以及错误信息都会通过此类的回调方法返回。
- ContentTextCallback:录音文本内容信息获取回调类。文本内容以及错误信息会通过回调方法返回。
- RecordCallback:录音及录音文件上传相关业务回调类。录音状态、文件上传识别、识别结果、错误信息等都会通过回调方法返回。录音过程中会实时将声音分贝值返回。
- UploadRecordsCallback:录音完成后开启声音模型训练的回调类。提交结果、声音模型ID、错误信息等都会通过回调方法返回。
- MouldCallback:查询声音模型信息回调类。可以通过模型ID查询单个模型的训练信息,可以通过queryId分页查询该Id下所有模型的训练信息。
-
Mould:声音模型的实体类。属性如下:
String modelId; //模型ID
int modelStatus;//模型状态
1=默认状态,2=录制中,3=启动训练失败,4=训练中,5=训练失败,6=训练成功。
String statusName;//模型状态中文(值)
调用说明
- 本SDK调用过程可能会发生在多个页面,所以我们将各功能实现拆细了,同时伴随着细分的多个回调。这样做的目的是方便灵活调用。
第一步需要初始化。
- 可通过调用BakerVoiceEngraver.getInstance().initSDK(Context context, String clientId, String clientSecret, String queryID)实现初始化。前三个参数是必传参数,clientId和clientSecret是授权信息。第四个参数queryID可传空。这个queryID的作用是与当前训练的声音模型ID关联,存储备份在标贝服务器。以备后期可通过queryId查询到与此管理的所有声音模型信息。
- 如果在初始化时未上传queryId,也可以调用BakerVoiceEngraver.getInstance().setQueryId(String queryID)方法设置queryID,但设置queryID一定要在调用getVoiceMouldId()方法之前调用,即第4步之前设置。在产出声音模型ID时,就需要将queryId与声音模型ID关联存储。
环境噪音检测
- 在此步之前,请务必申请到Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE 这2个权限。SDK中也做了权限检测,无权限检测会上报错误信息。
- BakerVoiceEngraver.getInstance().setDetectCallback(DetectCallback callback);设置噪音检测的回调。检测过程中会将实时分贝数据、检测最终结果、错误信息等通过回调接口中的方法返回。DetectCallback接口的具体信息请参考xxx。
- 调用BakerVoiceEngraver.getInstance().startDBDetection();方法开启噪音检测。检测时长是3秒。
- 噪音检测通过固定算法得出环境声音分贝值作为检测终值,如果终值大于70分贝,是不允许进行后续步骤的,因为环境太嘈杂,会直接影响训练出来的声音的品质。可以参考demo中对于返回结果的提示以及逻辑处理,如果噪音检测不通过,可以换环境在相对安静的空间内重新检测。重新检测也是调用BakerVoiceEngraver.getInstance().startDBDetection();方法。
- 理论上是环境越安静,录音效果越好,训练出来的声音品质会越好。所以对这个噪音的限制,SDK只做不能超过70分贝的最大值限制。使用SDK的亲们可以在自己的应用中灵活做二次限制。
获取录音文本,并录音上传。
- 在此步也请一定确保申请到Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE 这2个权限。SDK中也做了权限检测,无权限检测会上报错误信息。
- BakerVoiceEngraver.getInstance().setContentTextCallback(ContentTextCallback callback);设置获取录音文本的回调。文本信息或错误信息都将通过回调方法返回。
- BakerVoiceEngraver.getInstance().setRecordCallback(RecordCallback callback);设置录音、上传、识别检测、错误信息等接口方法的回调。
- BakerVoiceEngraver.getInstance().getTextList();调用此方法获取录音文本信息。参考demo,将返回的文本信息列表分条展示,供用户完成录音流程。
- BakerVoiceEngraver.getInstance().getVoiceMouldId();调用此方法申请此次声音训练的相关资源。在开始录音上传之前,必须调用此方法。
- BakerVoiceEngraver.getInstance().startRecord(String contentText);调用此方法开启录音。此方法会返回一个int值,该值的意义分别是:0=mouldId为空,1=无权限,2=开启成功。
- BakerVoiceEngraver.getInstance().uploadRecords(String contentText);本小段朗读完成后,调用此方法停止录音,并开始上传识别。此方法会返回一个int值,该值的意义分别是:0=mouldId为空, 1=结束成功,开始上传识别。
- 若结束录音后上传过程中出现错误,可以通过调用以下方法BakerVoiceEngraver.getInstance().reUploadRecords(String contentText);重新上传本段录音。
- 若因各种原因,在录音过程中需要退出录制,或者放弃当前任务,请调用BakerVoiceEngraver.getInstance().recordInterrupt();这个方法通知SDK中止录音。若在异常退出录制的过程中调用此方法,可以即时释放声音复刻名额以及停止录音。否则未中止录音可能会产生非常大的录音文件,占用用户设备存储资源。
- 此步中我们将录音的顺序及录音总数的维护交给了SDK接入方来维护。理论上应当一段一段录制,当检测到都录制完成后,就开启声音模型训练了。
开启声音模型训练
- BakerVoiceEngraver.getInstance().setUploadRecordsCallback(UploadRecordsCallback callback);通过此方法设置开启模型训练结果的回调。开启训练的结果、声音模型ID、错误信息等都将通过此回调接口方法返回。
- BakerVoiceEngraver.getInstance().finishRecords(String phone, String notifyUrl);调用此方法开启模型训练。这个方法中的两个参数都是选填的。第一个参数是手机号,如果上传后,可以通过手机短信收到训练进度通知,但短信中带有标贝公司签名信息,所以不建议在正式项目中上传该手机号。第二个参数是提供一个接收异步训练进度回调的服务器接口地址,建议SDK接入方设置该回调地址。标贝科技的异步训练服务器将训练结果以推送方式通知接入方,该地址必须为外网可访问的url,不能携带参数。(文档最后附了示例回调接口的代码,提供参考)目前主要包括开启训练通知和训练完成时通知。
- 开启模型训练成功后,此步回调方法中返回的mouldId建议SDK接入方自行将其存储维护起来,此mouldId应当与用户一一对应。在声音合成体验时,要用到这个mouldId。
- 如果需要再次发起新声音模型训练,可以重复第3-5步
查询模型信息
- BakerVoiceEngraver.getInstance().setMouldCallback(MouldCallback callback)设置查询结果回调。声音模型相关信息、错误信息等会通过回调方法返回。
- BakerVoiceEngraver.getInstance().getMouldList(int page, int limit, String queryId)根据queryId分页查询此queryId下的所有声音模型信息。Page从1开始。
- BakerVoiceEngraver.getInstance().getMouldInfo(String mouldId);根据模型Id查询模型信息。
体验合成声音
- 第一种方式类似Demo所示,通过restAPI形式,拼接MP3链接,然后请求播放。这个地方需要token信息,这个token信息可以通过BakerVoiceEngraver.getInstance().getToken();实时获取。Token其实是用sdk初始化时提供的clientId和clientSecret获取的,且有过期时效,所以不建议保存,使用时实时获取即可。相关介绍可以参考标贝公司官网:https://www.data-baker.com/specs/file/tts_api_restful
- 第二种方式是集成声音合成的SDK,这种方式接入的相关链接:https://www.data-baker.com/specs/file/reprint_sdk_android SDK采用实时合成流式返回,响应速度很快。SDK也集成了播放器功能,集成使用很方便。
API说明
BakerVoiceEngraver类说明
方法名 作用 说明 getInstance() 获取单实例 获取BakerVoiceEngraver类单实例。 initSDK() 初始化SDK initSDK(Context context, String clientId, String clientSecret, String queryID,InitListener listener)初始化SDK。前三个参数是必传参数,clientId和clientSecret是授权信息。第四个参数queryID可传空。这个queryID的作用是与当前训练的声音模型ID关联,存储备份在标贝服务器。以备后期可通过queryId查询到与此管理的所有声音模型信息。InitListener见调用说明.8。 setQueryId() 设置queryId 如果在初始化时未上传queryId,也可以调用setQueryId(String queryID)方法设置queryID,但设置queryID一定要在调用getVoiceMouldId()方法之前调用,即SDK关键类.4步之前设置。 getTextList() 获取录音文本信息 调用此方法获取录音文本信息。参考demo,将返回的文本信息列表分条展示,供用户完成录音流程。 startDBDetection() 开启噪音检测 噪音检测通过固定算法得出环境声音分贝值作为检测终值,如果终值大于70分贝,是不允许进行后续步骤的,因为环境太嘈杂,会直接影响训练出来的声音的品质。可以参考demo中对于返回结果的提示以及逻辑处理,如果噪音检测不通过,可以换环境在相对安静的空间内重新检测。重新检测也是调用此方法。 getVoiceMouldId() 申请声音模型训练资源 调用startRecord(String contentText)方法开启录音。参数中contentText是此条录音的文本信息(必传)。此方法会返回一个int值,该值的意义分别是:0=mouldId为空,1=无权限,2=开启成功。 startRecord() 开始录音 调用startRecord(String contentText)方法开启录音。参数中contentText是此条录音的文本信息(必传)。此方法会返回一个int值,该值的意义分别是:0=mouldId为空,1=无权限,2=开启成功。 uploadRecords() 停止录音上传识别 每小段朗读完成后,调用uploadRecords(String contentText)方法停止录音,并开始上传识别。参数中contentText是此条录音的文本信息(必传)。此方法会返回一个int值,该值的意义分别是:0=mouldId为空, 1=结束成功,开始上传识别。 reUploadRecords() 重新上传本段录音 若结束单段录音后上传过程中出现错误,可以通过调用以下方法reUploadRecords(String contentText);重新上传本段录音。参数中contentText是此条录音的文本信息(必传)。此方法会返回一个int值,该值的意义分别是:0=mouldId为空, 1=结束成功,开始上传识别。 recordInterrupt() 异常中断(退出)此次录音任务 若因各种原因,在录音过程中需要退出录制,或者放弃当前任务,请调用recordInterrupt()方法通知SDK中止录音。若在异常退出录制的过程中调用此方法,可以即时释放声音复刻名额以及停止录音。否则未中止录音可能会产生非常大的录音文件,占用用户设备存储资源。 finishRecords() 完成录音开启训练 调用此方法开启模型训练。这个方法中的两个参数都是选填的。第一个参数是手机号,如果上传后,可以通过手机短信收到训练进度通知,但短信中带有标贝公司签名信息,所以不建议在正式项目中上传该手机号。第二个参数是训练进度回调的服务器接口地址,建议SDK接入方设置该回调地址,这样我们服务器在模型训练过程中的进度变更时通知该地址,以便及时通知用户。目前主要包括开启训练通知和训练完成时通知。 getMouldList() 获取模型信息列表 getMouldList(int page, int limit, String queryId)根据queryId分页查询此queryId下的所有声音模型信息。Page从1开始。 getMouldInfo() 获取单个模型信息 getMouldInfo(String mouldId);根据模型Id查询模型信息。 getToken() 获取token信息 getToken()实时获取Token。Token其实是用sdk初始化时提供的clientId和clientSecret获取的,且有过期时效,所以不建议保存,使用时实时获取即可。 setContentTextCallback() 设置获取录音文本的回调 setContentTextCallback(ContentTextCallback callback)设置获取录音文本的回调。文本信息或错误信息都将通过回调方法返回。 setDetectCallback() 设置噪音检测的回调 setDetectCallback(DetectCallback callback)设置噪音检测的回调。参数需要接入方自己实例化DetectCallback,可参考demo的方式。检测过程中会将实时分贝数据、检测最终结果、错误信息等通过回调接口中的方法返回。DetectCallback接口的具体信息请参考xxx。 setRecordCallback() 设置录音上传相关回调 setRecordCallback(RecordCallback callback)设置录音、上传、识别检测、错误信息等接口方法的回调。 setUploadRecordsCallback() 设置开启模型训练结果的回调。 setUploadRecordsCallback(UploadRecordsCallback callback)通过此方法设置开启模型训练结果的回调。开启训练的结果、声音模型ID、错误信息等都将通过此回调接口方法返回。 setMouldCallback() 设置查询声音模型信息的回调。 setMouldCallback(MouldCallback callback)设置查询结果回调。声音模型相关信息、错误信息等会通过回调方法返回。 startPlay() 播放录音 第一个参数是试听第几个录音,从0开始。
第二个参数是个回调,详见调用说明.7。stopPlay() 停止播放 停止播放已经开始的录音 isRecord(int index) 判断是否录制成功 index从0开始。x从0开始。 如果录制成功返回true。 如果录制失败返回false。 DetectCallback环境检测回调接口方法说明
接口方法名 作用 说明 dbDetecting 环境检测中结果反馈 dbDetecting(int value);回调方法的参数是实时返回的声音分贝检测值。使用方式参考demo。 dbDetectionResult 环境检测最终结果反馈 dbDetectionResult(boolean result, int value);参数result=true,表示检测通过。value是检测通过的分贝值。result=false,表示检测未通过。value是检测未通过的分贝值。使用方式参考demo。 onDetectError 错误信息回调 onDetectError(int errorCode, String message);错误信息回调,errorCode是错误code码,message是详细错误信息。使用方式参考demo。 ContentTextCallback获取录音文本回调接口方法说明
接口方法名 作用 说明 contentTextList 获取录音文本回调 contentTextList(String[] strList);获取录音文本回调,返回的参数是此次录音需要的录音文本,以字符串数组形式返回。可参考demo维护和使用该数据。 onContentTextError 错误信息回调 onContentTextError(int errorCode, String message);错误信息回调,errorCode是错误code码,message是详细错误信息。使用方式参考demo。 RecordCallback录音上传识别回调接口方法说明
接口方法名 作用 说明 recordsResult 录音中、识别中、识别结果回调。 recordsResult(int typeCode, int recognizeResult);录音中、识别中、识别结果回调。参数typeCode 1=录音中, 2=识别中,3=最终结果。recognizeResult是识别率,取值0-100. 使用方式参考demo,非常建议单段录音识别通过后才开启下一段录制。所有段录音完成录制,识别通过才开启模型训练,否则会影响最终声音的品质。 recordVolume 录音过程中实时返回声音分贝信息。 recordVolume(int volume);录音过程中,会将声音分贝值实时返回。volume是分贝值。具体使用方式参考demo。 onRecordError 错误信息回调 onRecordError(int errorCode, String message);错误信息回调,errorCode是错误code码,message是详细错误信息。使用方式参考demo。 UploadRecordsCallback开启模型训练回调接口方法说明
接口方法名 作用 说明 uploadRecordsResult 模型开启训练成功回调 uploadRecordsResult(boolean result, String mouldId);参数result true=成功,false=失败。参数mouldId是声音模型的ID,此mouldId建议SDK接入方自行将其存储维护起来,此mouldId应当与用户一一对应。在声音合成体验时,要用到这个mouldId。 使用方式参考demo。 onUploadError 错误信息回调 onUploadError(int errorCode, String message);错误信息回调,errorCode是错误code码,message是详细错误信息。使用方式参考demo。提交不成功,可以再次提交。 MouldCallback查询声音模型相关回调接口方法说明
接口方法名 作用 说明 mouldInfo 根据mouldId查询mould信息回调 mouldInfo(Mould mould);根据mouldId查询mould信息回调,方法的参数是返回的声音模型信息。若需要此回调方法,需要手动复写该方法。使用方式参考demo。 mouldList 根据queryId分页查询mould信息回调 mouldList(List<Mould> list);根据queryId分页查询mould信息回调。参数list是声音模型信息的列表。使用方式参考demo。 onMouldError 错误信息回调 onMouldError(int errorCode, String message);错误信息回调,errorCode是错误code码,message是详细错误信息。使用方式参考demo。 PlayListener,录音试听回调
接口方法名 作用 说明 playStart 试听开始 当开始播放的时候回调此方法 playEnd 试听结束 当播放结束的时候回调此方法 playError 试听报错 当播放过程中出现错误的时候回调此方法时候回调此方法 InitListener,初始化结果回调
接口方法名 作用 说明 onInitSuccess 初始化成功 当初始化成功的时候回调此方法 onInitError(Exception e) 初始化失败 当初始化识别的回收回调此方法
错误码
错误码 | 含义 |
---|---|
90000 | 接口正常,正确返回的识别码 |
90001 | 请求token失败 |
90002 | Token过期 |
90003 | 参数值为空或不正确 |
90004 | 网络请求错误 |
90005 | 网络请求返回data值为空 |
90006 | 服务器返回错误的代码 |
90007 | 解析response出错 |
90008 | 当前上传的录音的mouldId与录制的录音的mouldId不一致 |
90009 | 当前上传的录音的contentText与录制的录音的contentText不一致 |
90010 | 停止录音出错 |
90011 | 停止检测噪音出错 |
90012 | 创建录音文件时异常 |
90013 | 因音频焦点丢失或电话等异常中断录音 |
99999 | 服务器系统异常 |
00011 | Token校验失败,请核查! |
10003 | 参数错误 |
10004 | 上传文件失败,请选择正确的文件格式 |
10005 | 上传文件不能为空 |
10008 | 模型id不合法,请重试 |
10009 | 模型正在过程录制中,其他客户端不能同时录制! |
10010 | 识别语音超时! |
40002 | 提交次数已达到最大限制 |
40003 | 接口请在有效期内使用 |
40004 | 接口签名不合法 |
40005 | 请填写正确的手机号! |
附:服务器端异步回调接口
@ApiOperation(value = "模型训练结果回调接口,仅作为示例", notes = "该链接通过参数notifyUrl设置,如果链接无法访问,将无法接收到回调的push信息。") @PostMapping("/notify") public void mouldInformationNotify(HttpServletRequest request, HttpServletResponse response) { LogUtils.printStartTag(request.getRequestURI()); String resXml = ""; InputStream inStream; try { inStream = request.getInputStream(); ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } // 获取 模型训练方 调用notifyUrl时携带的返回信息 String result = new String(outSteam.toByteArray(), "utf-8"); log.info("dataBaker:模型训练返回结果 ----result---- =" + result); // 关闭流 outSteam.close(); inStream.close(); // String转换为json对象,然后业务处理 JSONObject jsonObject = StringUtils.isNotEmpty(result) ? JSON.parseObject(result) : null; //该参数表示模型id String mouldId = jsonObject == null ? "" : jsonObject.getString("mouldId"); //该参数表示模型当前状态:可能的值为0、1、2、3 String mouldStatus = jsonObject == null ? "" : jsonObject.getString("mouldStatus"); //该参数表示状态的说明(文案可能会有变动),0:训练任务已启动 1:训练任务启动失败 2:训练任务启动成功但训练失败 3:训练成功 String statusName = jsonObject == null ? "" : jsonObject.getString("statusName"); //具体业务处理,例如自行通知用户、存储模型id和状态信息等(可先返回结果,然后异步去完成业务逻辑) //todo //根据情况,向结果中赋值:正常情况下,选择下面的resSuccess;如果选择resFail,将会视为推送失败,标贝服务端将重新推送一次相同的内容 // * 返回成功xml // */ // String resSuccess = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; // /** // * 返回失败xml // */ // String resFail = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; resXml = Constant.resSuccess; //记录日志 log.info("dataBaker:模型训练回调返回模型 {} 的状态为:--->{}", mouldId, statusName); } catch (Exception e) { log.error("dataBaker:模型训练回调异常:", e); } finally { try { // 处理业务完毕 BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); } catch (IOException e) { log.error("dataBaker:模型训练回调异常:out:", e); } } }