请忽略本文工地散装英语:cry:
我只是一个会点rn
的前端,在安卓开发和ios开发上属于编写边学程度,所以可能会有很多bug,请酌情使用
- 云知音官方
SDK
我只发现了32位的,并没有文档里所说的64位的,联系他们也联系不上,有64位的可以联系我。There are only 32-bit SDK - 由于只是用了32位的
SDK
所以你的项目打包不应该包含64位的,所以你需要修改项目根目录/android/app/build.greadle
。You should edit the file:project_root_dir/android/app/build.greadle
like flow to avoid mixed 32bit and 64bit sdks - 由于我不是很懂原生开发,有可能下面的并不是最佳配置,你可以使用自己的配置,并告知我
Because I'm good at native development,you can use your own configuration and tell me
......
......
splits {
abi {
reset()
// set enableSeparateBuildPerCPUArchitecture = true
// 将enableSeparateBuildPerCPUArchitecture设置为true
enable enableSeparateBuildPerCPUArchitecture
universalApk false
// delete others and "armeabi-v7a" only
// 删除其他的 只保留64位的这个
include "armeabi-v7a"
}
}
.....
.....
// 建议直接赋值粘贴这段
applicationVariants.all { variant ->
// 注意这里each改成了all
variant.outputs.all { output ->
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) {
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
// rename apk,
// 这一段是为了将分离打包的文件重新命名 不然使用
// react-native run-android 会出错 因为它只认识app-debug
if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {
File outputDirectory = new File(output.outputFile.parent);
def fileName
if (variant.buildType.name == "release") {
// release name
outputFileName = "app-release.apk"
} else {
// debug name
outputFileName = "app-debug.apk"
}
}
}
}
- 如果你有其他的库只能在64位上运行,你只能转用其他的库,这个库也就免费这一点还不错。
- TODO
$ npm install react-native-xf-speech --save
or
$ yarn add react-native-xf-speech
$ react-native link react-native-xf-speech
- In XCode, in the project navigator, right click
Libraries
➜Add Files to [your project's name]
- Go to
node_modules
➜react-native-xf-speech
and addRNXfSpeech.xcodeproj
- In XCode, in the project navigator, select your project. Add
libRNXfSpeech.a
to your project'sBuild Phases
➜Link Binary With Libraries
- Run your project (
Cmd+R
)<
- Open up
android/app/src/main/java/[...]/MainActivity.java
- Add
import com.xh.speech.RNXfSpeechPackage;
to the imports at the top of the file - Add
new RNXfSpeechPackage()
to the list returned by thegetPackages()
method
- Append the following lines to
android/settings.gradle
:include ':react-native-xf-speech' project(':react-native-xf-speech').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-xf-speech/android')
- Insert the following lines inside the dependencies block in
android/app/build.gradle
:compile project(':react-native-xf-speech')
- 在
你的项目根目录/android/app/src/main/
下面创建目录assets\tts
create a folderassets\tts
inproject_root_dir/android/app/src/main/
- 移动仓库中model文件夹两个文件(
backend_lzl
和frontend_model
)至assets\tts
move files in this_repository/model toassets\tss
you made - 添加权限 add permission
在项目根目录/android/app/src/main/AndroidManifest.xml
中添添加
add follow code inproject_root_dir/android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
请注意READ_PHONE_STATE
这个权限在高版本安卓中需要动态获取,虽然此项目会替你申请,但是你最好还是自己在合适的地方申请权限
you should ask the permission READ_PHONE_STATE
by your self in the right place although we did this
1. initEngine() 初始化
2. setInitEngineListener() 设置初始化监听
3. playText() 朗读文字
4. stopPlay() 停止朗读
5. pause() 暂停播放
6. resume() 恢复播放
7. utils 辅助函数
7.1 getVolume() 获取当前系统音量
7.2 getMaxVolume() 获取当前系统最大音量
7.3 setVolume() 设置音量
8. setPlayStartListener() 开始播放事件
9. setPlayEndListener() 播放结束事件
10. setPauseListener() 暂停事件
11. setStopListener() 停止事件
12. setResumeListener() 恢复事件
13. setReleaseListener() 释放资源事件
14. setErrorListener() 合成错误事件
function initEngine(appkey:string, secret: string, options?: Options): Promise<void>
options 可选Optional
// 音频输出流类型
// audio output stream type
streamType: STREAM_TYPE,
// 0 ~ 100 不是系统音量 是合成的语音音量 感觉没什么效果 默认100
// not system volume, is speech synthesis volume, defualt 100
volume: number,
// 0 ~ 100 语音音调 不建议调 其他的音调都很怪 就是变声器那种哈哈哈哈哈 默认50
// defualt 50
pitch: number,
// 0 ~ 100 语速 默认52
// defualt 52
speed: number,
STREAM_TYPE
// 我也没搞清楚区别 详情可以百度`安卓audio stream type`默认MUSIC
// 大概区别就是`MUSIC`对应媒体音量 其他的基本上就是铃声,闹钟,通知
// 设置这个的目的是有的输出流声音比较小,还有插耳机和不插耳机的区别,但是我没有测试过插耳机的情况
// 请自己测试
enum STREAM_TYPE {
// 系统默认
SYSTEM,
// 铃声
RING,
// 媒体
MUSIC,
// 闹钟
ALARM,
// 通知
NOTIFICATION
}
import tts from 'react-native-xf-speech';
// initial
const options = {
streamType: tts.STREAM_TYPE.MUSIC,
volume: 100,
pitch: 50,
speed: 52
}
await tts.initEngine("app_key","app_secret", options)
这一步非常重要,所有的操作都应该在初始化之后,除了初始化监听函数
app_key
和app_secret
随便填好像都可以用,如果提示错误,请移步云知音官网自己申请。
Operation must be performed after initialization, except listener function
you can use any strings apply to app_key
and app_secret
,if there are any problems you need to get key and secret by yourself 云知音hompage
申请注意
- 申请通用解决方案,同时勾选离线语音合成
- 下载完成后将
USCDemo\libs\armeabi
中的文件替换掉本仓库android/libs
中的文件- 将下载完成的sdk
USCDemo\assets\OfflineTTSModels
中的文件复制替换掉上面前面创建的assets\tts
文件夹中的文件
- 初始化需要加载模型,需要将
assets\tts
的文件复制到存储中,所以需要几秒的时间,期间会导致app
卡顿(因为没有用单独的线程加载),所以建议使用监听函数做相应的提示
because there are no separate threads, when excuse theinitEngine
function may cause application to jam. you should use initial listener- 再次提醒,一定要在初始化之后进行其他操作,不然会报错
function setInitEngineListener(callback: (event: InitEvent) => any): void
InitEvent 事件参数
{
// 初始化大部分工作就是复制文件至内存 只会做一次
// Most of the initialization work is to copy files to memory, only once
// 文件复制进度
progress: number,
// 文件个数
fileCount: number,
// 初始化状态
initState: INIT_ENGINE_STATE
}
INIT_ENGINE_STATE 初始化状态
enum INIT_ENGINE_STATE {
// 刚开始 萨摩耶没做
START,
// 正在初始化
PROGRESS,
// 完成
FINISH,
// 文件未找到 请检查model是否复制正确
SDK_NOT_FOUND_ERROR,
// 文件操作失败 检查存储空间或其他错误
SDK_COPY_ERROR
}
初始化带监听
async function init() {
// 注册监听函数一定要在initEngine之前 不然没有效果
// must set listener before initEngine
tts.setInitEngineListener(({progress, fileCount, initState}) => {
console.log(`正在复制第${fileCount}个文件`, `当前进度${progress}`)
if(initState == tts.INIT_ENGINE_STATE.FINISH) {
}else {
}
})
await tts.initEngine("123","123")
}
function playText(text: string): void
text 需要朗读的文本
tts.playText(`啊啊啊啊嗯嗯嗯啊啊啊啊啊嗯啊啊啊啊`)
function stopPlay(): void
function pause(): void
function resume(): void
function release(): void
释放后需要重新初始化
function getVolume(): Promise<number>
function getMaxVolume(): Promise<number>
function setVolume(value: number, flag: VOLUME_FLAGS): void
value 设定值
flag 设定音量的一些反馈
enum VOLUME_FLAGS {
// 输出流是ring时有效
ALLOW_RINGER_MODES,
// 输出流是铃声之类的才有效
PLAY_SOUND,
// 不知道什么意思
REMOVE_SOUND_AND_VIBRATE,
// 展示音量ui
SHOW_UI,
// 震动 有的输出流不生效
VIBRATE
}
async function setAndShowUI() => {
const volume = await tts.utils.getVolume()
tts.utils.setVolume(volume, tts.VOLUME_FLAGS.SHOW_UI)
}
function setPlayStartListener(callback: () => any): void
function setPlayEndListener(callback: () => any): void
function setPauseListener(callback: () => any): void
function setStopListener(callback: () => any): void
function setResumeListener(callback: () => any): void
function setReleaseListener(callback: () => any): void
function setErrorListener(callback: (event: ErrorEvent) => any): void
ErrorEvent
{
msg: string
}
TODO....