tts 初始化
This commit is contained in:
@@ -46,7 +46,7 @@ MOGO_SOCKET_VERSION=1.4.7.65
|
||||
# 数据采集
|
||||
MOGO_REALTIME_VERSION=1.4.7.65
|
||||
# 探路,道路事件发布,获取
|
||||
MOGO_TANLU_VERSION=1.4.7.64
|
||||
MOGO_TANLU_VERSION=1.4.7.65
|
||||
# 直播推流
|
||||
MOGO_LIVE_VERSION=1.4.7.65
|
||||
# 直播拉流
|
||||
|
||||
1
libraries/mogo-tts/app/.gitignore
vendored
Normal file
1
libraries/mogo-tts/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
7
libraries/mogo-tts/app/EB5/a_keystore_make_eb5.sh
Normal file
7
libraries/mogo-tts/app/EB5/a_keystore_make_eb5.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
# 将 platform.pk8 生成 platform.pem
|
||||
openssl pkcs8 -inform DER -nocrypt -in ./platform.pk8 -out ./platform.pem
|
||||
# platform.x509.pe m生成 platform.p12
|
||||
openssl pkcs12 -export -in ./platform.x509.pem -inkey ./platform.pem -out ./platform.p12 -password pass:android -name eb5_system
|
||||
# 使用keytool工具,通过指令生成keystore
|
||||
keytool -importkeystore -deststorepass password -destkeystore ./eb5_system.keystore -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass android
|
||||
|
||||
BIN
libraries/mogo-tts/app/EB5/eb5_system.keystore
Normal file
BIN
libraries/mogo-tts/app/EB5/eb5_system.keystore
Normal file
Binary file not shown.
BIN
libraries/mogo-tts/app/EB5/platform.p12
Normal file
BIN
libraries/mogo-tts/app/EB5/platform.p12
Normal file
Binary file not shown.
28
libraries/mogo-tts/app/EB5/platform.pem
Normal file
28
libraries/mogo-tts/app/EB5/platform.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCceAWSrA1dOBze
|
||||
qmXsyKYAbjZIDG1yB7EgEb5Qhjqr4rVdAJrfcUbW8iAigMfNTXvbJiQ7ioBsJrNL
|
||||
E3UjpJJoIkkE3AFJPnwKzxoFyHT2mwN7YDCdkHTSQoDha60qhzQ2GVHq9ypILQmy
|
||||
BLGHXhKsmMGqdz1oALnq/eVtWL7Y6NoW+aNgCZw3qDSm3+23trRKBJ4Homn8zyxU
|
||||
lvLPNtZN+Qo7jY80o7qrTPUzcasncZs7pYdUrQxT/BTh20XVHiNPu+k8m6Tt+c5U
|
||||
JhNQ7FNWB79pov9KoH219+ogDQmmwbSeIUAvie0RkIk6q1qRgPFS6C+FpFdTz1/B
|
||||
kHHF7sgnAgEDAoIBAGhQA7cdXj4laJRxmUiFxABJeYVdnkwFIMAL1DWu0cfseOir
|
||||
EepLhI9MFWxV2ojeUpIZbX0HAEgZzNy3o20YYZrBhgM9VjDUUrHfZq6Fo08SAlJA
|
||||
IGkK+IwsVeudHhxaIs67i/H6HDAeBnaty6+UDHMQgRxPfkVV0UdT7kjl1JCaMTTc
|
||||
hXxr+oGsH5d5EHCPBfEU4v8BqOBSEgkUFJ1Y6Y5AQqbSe2nSZ6bKZpE8YY27Ipvq
|
||||
BrZEN0j7SKcHKuJDm81DGfLrh3vOmW6U0ZWy7o9qv7INYXNDvtKUMQigXYYANKUp
|
||||
KvveUSgKJ+ixfFP8Ye92j8mp+d/+16i4Wa7Wu5sCgYEAyCd3wu4wsRAu/8q1abL1
|
||||
4/V8M95+dlfhJBl3H9VwUbsH+CP2VRQ9KYkaYdPwOb8hz1h8gqr74ASbEvz+ixMH
|
||||
zI6zel07VDCew+6OUZOBiOxGc8p7SpZuCeDsL+GEZxkOMQ7PXUpDI/p8nx84eEJU
|
||||
ZrHc2kv1VcpdAXLhtrpiicUCgYEAyCA3GDc282T3BXj061vqR2rpFaqhdlRy7S2B
|
||||
tA3BJj2Qrh1bgQGq9agC+YWm3xO3F/lJ+phK2WHoFOpR+m6w7Q0jx/L/BYOlJD+4
|
||||
h1zeZJKhLBQToodM1ZktcLGYFkSzNJeUImt5T1sErj5op9Ex97nZfYswCrl0GtGa
|
||||
NIVKJPsCgYEAhW+lLJ7LILV0qocjm8yj7U5SzT7++Y/rbWZPao5K4SdapW1O42LT
|
||||
cQYRlo1K0SoWijr9rHH9QAMSDKipsgyv3bR3pujSOCBp1/Re4Q0BBfLZoob83GRJ
|
||||
W+tIH+utmhC0ILSKPjGCF/xTFL96+tbi7yE95t1OOTGTVkyWedGXBoMCgYEAhWrP
|
||||
ZXokokNPWPtN8j1G2kdGDnHA+Y2h83OrzV6AxCkLHr49AKvHTnAB+65vP2J6D/uG
|
||||
pxAx5kFFY0bhUZ8gngjChUyqA60YwtUlr5M+7bcWHWK3wa+IjmYeSyEQDth3eGUN
|
||||
bEemNOdYdCmbGot2pSaQ/lzKsdD4EeEReFjcGKcCgYA+JeOt5WFENpv4LT+7P+j1
|
||||
k3xvOZ9sJGuXRXk9HXzsJvRCnc5oScwqku6i5HjzG8gyNVZg1sQGbVbWWmcNtaS8
|
||||
I3XalYAHYQyb8SGxlQP4ctKAN4j2Hbk1OHAMW84dfAQYQwFcBdaJTtMXQlbbX5Rh
|
||||
x90wE4qFuIapx6IKOmDxRw==
|
||||
-----END PRIVATE KEY-----
|
||||
BIN
libraries/mogo-tts/app/EB5/platform.pk8
Normal file
BIN
libraries/mogo-tts/app/EB5/platform.pk8
Normal file
Binary file not shown.
27
libraries/mogo-tts/app/EB5/platform.x509.pem
Normal file
27
libraries/mogo-tts/app/EB5/platform.x509.pem
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqDCCA5CgAwIBAgIJALOZgIbQVs/6MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
|
||||
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
|
||||
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
|
||||
Fw0wODA0MTUyMjQwNTBaFw0zNTA5MDEyMjQwNTBaMIGUMQswCQYDVQQGEwJVUzET
|
||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
|
||||
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
|
||||
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
|
||||
hvcNAQEBBQADggENADCCAQgCggEBAJx4BZKsDV04HN6qZezIpgBuNkgMbXIHsSAR
|
||||
vlCGOqvitV0Amt9xRtbyICKAx81Ne9smJDuKgGwms0sTdSOkkmgiSQTcAUk+fArP
|
||||
GgXIdPabA3tgMJ2QdNJCgOFrrSqHNDYZUer3KkgtCbIEsYdeEqyYwap3PWgAuer9
|
||||
5W1Yvtjo2hb5o2AJnDeoNKbf7be2tEoEngeiafzPLFSW8s821k35CjuNjzSjuqtM
|
||||
9TNxqydxmzulh1StDFP8FOHbRdUeI0+76TybpO35zlQmE1DsU1YHv2mi/0qgfbX3
|
||||
6iANCabBtJ4hQC+J7RGQiTqrWpGA8VLoL4WkV1PPX8GQccXuyCcCAQOjgfwwgfkw
|
||||
HQYDVR0OBBYEFE/koLPdnLop9x1yh8Tnw48ghsKZMIHJBgNVHSMEgcEwgb6AFE/k
|
||||
oLPdnLop9x1yh8Tnw48ghsKZoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
|
||||
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
|
||||
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
|
||||
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJALOZgIbQVs/6MAwGA1Ud
|
||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAFclUbjZOh9z3g9tRp+G2tZwFAAp
|
||||
PIigzXzXeLc9r8wZf6t25iEuVsHHYc/EL9cz3lLFCuCIFM78CjtaGkNGBU2Cnx2C
|
||||
tCsgSL+ItdFJKe+F9g7dEtctVWV+IuPoXQTIMdYT0Zk4u4mCJH+jISVroS0dao+S
|
||||
6h2xw3Mxe6DAN/DRr/ZFrvIkl5+6bnoUvAJccbmBOM7z3fwFlhfPJIRc97QNY4L3
|
||||
J17XOElatuWTG5QhdlxJG3L7aOCA29tYwgKdNHyLMozkPvaosVUz7fvpib1qSN1L
|
||||
IC7alMarjdW4OZID2q4u1EYjLk/pvZYTlMYwDlE448/Shebk5INTjLixs1c=
|
||||
-----END CERTIFICATE-----
|
||||
128
libraries/mogo-tts/app/build.gradle
Normal file
128
libraries/mogo-tts/app/build.gradle
Normal file
@@ -0,0 +1,128 @@
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
|
||||
signingConfigs {
|
||||
releaseEB5 {
|
||||
keyAlias = 'eb5_system'
|
||||
storeFile file('./EB5/eb5_system.keystore')
|
||||
storePassword 'password'
|
||||
keyPassword 'password'
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.mogo.tts"
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
zipAlignEnabled true
|
||||
shrinkResources false
|
||||
signingConfig signingConfigs.releaseEB5
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
release {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
zipAlignEnabled true
|
||||
shrinkResources false
|
||||
signingConfig signingConfigs.releaseEB5
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||
implementation 'androidx.annotation:annotation:1.2.0'
|
||||
implementation 'androidx.core:core-ktx:1.5.0'
|
||||
|
||||
implementation 'com.blankj:utilcodex:1.30.0'
|
||||
implementation "com.bytedance.boost_multidex:boost_multidex:1.0.1"
|
||||
|
||||
implementation(project(":libraries:mogo-tts:tts-iflytek-offline"))
|
||||
implementation(project(":libraries:mogo-tts:tts-base"))
|
||||
|
||||
// ======================集成 Bugly================================================================
|
||||
implementation 'com.tencent.bugly:crashreport:4.1.9.2'
|
||||
// implementation 'androidx.activity:activity:1.13.0'
|
||||
// ======================集成 Bugly================================================================
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//// 打包出来的应用文件名称
|
||||
//android.applicationVariants.all { variant ->
|
||||
// def buildTime = new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+08:00"))
|
||||
// def flavor = variant.productFlavors.collect { it.name }.join('-')
|
||||
//
|
||||
// variant.outputs.all { output ->
|
||||
// outputFileName = ["MoGoTTS",
|
||||
// "v${variant.versionName}",
|
||||
// getWorkingBranchName(),
|
||||
// getWorkingBranchHash(),
|
||||
// buildTime,
|
||||
// flavor.length() > 0 ? "[${flavor}]" : "",
|
||||
// variant.buildType.name].findAll { it.length() > 0 }.join('_') << ".apk"
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// 获取当前分支名称
|
||||
//def getWorkingBranchName() {
|
||||
// def workingBranchName = ""
|
||||
// def proc = "git rev-parse --abbrev-ref HEAD".execute()
|
||||
// proc.in.eachLine { line -> workingBranchName = line }
|
||||
// proc.err.eachLine { line -> println line }
|
||||
// proc.waitFor()
|
||||
// println "Working branch name: " + workingBranchName
|
||||
// return workingBranchName
|
||||
//}
|
||||
//
|
||||
//// 获取当前分支hash
|
||||
//def getWorkingBranchHash() {
|
||||
// def workingBranchHash = ""
|
||||
// def proc = "git log -n1 --format=format:%h".execute()
|
||||
// proc.in.eachLine { line -> workingBranchHash = line }
|
||||
// proc.err.eachLine { line -> println line }
|
||||
// proc.waitFor()
|
||||
// println "Working branch hash: " + workingBranchHash
|
||||
// return workingBranchHash
|
||||
//}
|
||||
//
|
||||
//// 当前构建时间
|
||||
//static def getBuildTime() {
|
||||
// def buildTimeFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
// //设置时间格式
|
||||
// SimpleDateFormat formatter = new SimpleDateFormat(buildTimeFormat, Locale.getDefault())
|
||||
// //获取当前时间
|
||||
// Date curDate = new Date(System.currentTimeMillis())
|
||||
// def buildTime = formatter.format(curDate)
|
||||
// return "\"${buildTime}\""
|
||||
//}
|
||||
|
||||
33
libraries/mogo-tts/app/proguard-rules.pro
vendored
Normal file
33
libraries/mogo-tts/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /projects/android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# This renames the file name on stack traces from "UnknownSource" to "SourceFile"
|
||||
-renamesourcefileattribute SourceFile
|
||||
# This values are kept on stack traces to debug any issue easily
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# Rules recommended for Huawei PushKit
|
||||
-ignorewarnings
|
||||
-keepattributes *Annotation*
|
||||
-keepattributes Exceptions
|
||||
-keepattributes InnerClasses
|
||||
-keepattributes Signature
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
-keep class com.hianalytics.android.**{*;}
|
||||
-keep class com.huawei.updatesdk.**{*;}
|
||||
-keep class com.huawei.hms.**{*;}
|
||||
6
libraries/mogo-tts/app/readme.md
Normal file
6
libraries/mogo-tts/app/readme.md
Normal file
@@ -0,0 +1,6 @@
|
||||
### Sample Android app for demo
|
||||
|
||||
This is an example app that sends data to a remote Countly server.
|
||||
|
||||
In order to build and run this application, just open up the project in Android Studio and hit run with an appropriate application.
|
||||
|
||||
35
libraries/mogo-tts/app/src/main/AndroidManifest.xml
Normal file
35
libraries/mogo-tts/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.tts">
|
||||
<!-- 允许后台启动服务 -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.RESTART_PACKAGES" /> <!-- 系统级权限:绕过后台服务限制 -->
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- 关键:允许后台启动 Service & 前台服务 -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_*" /> <!-- 系统签名专用:豁免后台限制 -->
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
|
||||
<application
|
||||
android:name=".MoGoApplication"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/icon"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:persistent="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.mogo.tts
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.AppCompatButton
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.mogo.tts.common.TtsManager
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
|
||||
findViewById<AppCompatButton>(R.id.actv_test_tts1).setOnClickListener {
|
||||
TtsManager.speakTTSVoice("此时每个单兵要负责自己的一个视线防区")
|
||||
}
|
||||
findViewById<AppCompatButton>(R.id.actv_test_tts2).setOnClickListener {
|
||||
TtsManager.stopTTS()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.mogo.tts
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.blankj.utilcode.util.DeviceUtils
|
||||
import com.blankj.utilcode.util.FileIOUtils
|
||||
import com.blankj.utilcode.util.PathUtils
|
||||
import com.blankj.utilcode.util.TimeUtils
|
||||
import com.bytedance.boost_multidex.BoostMultiDex
|
||||
import com.mogo.tts.common.TtsManager
|
||||
import com.mogo.tts.iflytek.offline.IFlyTekOfflineTts
|
||||
import com.mogo.tts.utils.PhoneUtilsExtend
|
||||
import com.tencent.bugly.crashreport.CrashReport
|
||||
import com.tencent.bugly.crashreport.CrashReport.CrashHandleCallback
|
||||
import com.tencent.bugly.crashreport.CrashReport.UserStrategy
|
||||
|
||||
class MoGoApplication : Application() {
|
||||
val TAG = "MoGoApplication"
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base)
|
||||
Log.d(TAG, "--->>>MoGo APP :attachBaseContext")
|
||||
BoostMultiDex.install(base)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Log.d(TAG, "--->>>MoGo APP 应用商店启动:onCreate")
|
||||
initBugly()
|
||||
initTts()
|
||||
}
|
||||
|
||||
private fun initTts() {
|
||||
TtsManager.init(this)
|
||||
}
|
||||
|
||||
|
||||
private fun initBugly() {
|
||||
val strategy = UserStrategy(this)
|
||||
// 通过UserStrategy设置
|
||||
strategy.deviceID = PhoneUtilsExtend.getDevicesSn()
|
||||
// 通过UserStrategy设置
|
||||
strategy.deviceModel = DeviceUtils.getModel()
|
||||
|
||||
// 最新版SDK支持trace文件采集和anr过程中的主线程堆栈信息采集,由于抓取堆栈的系统接口 Thread.getStackTrace 可能造成crash,建议只对少量用户开启
|
||||
// 这里只对Debug模式下的开启
|
||||
if (BuildConfig.DEBUG) {
|
||||
strategy.appChannel = "MoGo_Debug"
|
||||
// 设置anr时是否获取系统trace文件,默认为false
|
||||
strategy.isEnableCatchAnrTrace = true
|
||||
// 设置是否获取anr过程中的主线程堆栈,默认为true
|
||||
strategy.isEnableRecordAnrMainStack = false
|
||||
} else {
|
||||
strategy.appChannel = "MoGo_Debug"
|
||||
}
|
||||
|
||||
// 设置Crash回调,将日志信息本地存储
|
||||
strategy.setCrashHandleCallback(object : CrashHandleCallback() {
|
||||
override fun onCrashHandleStart(
|
||||
crashType: Int, errorType: String,
|
||||
errorMessage: String, errorStack: String
|
||||
): Map<String, String> {
|
||||
val map = LinkedHashMap<String, String>()
|
||||
map["device_sn"] = PhoneUtilsExtend.getDevicesSn()
|
||||
FileIOUtils.writeFileFromString(
|
||||
PathUtils.getExternalAppFilesPath() + "/crash/" + TimeUtils.getNowString() + ".log",
|
||||
"crashType = $crashType \nerrorType = $errorType \nerrorMessage = $errorMessage \nerrorStack = $errorStack"
|
||||
)
|
||||
return map
|
||||
}
|
||||
|
||||
override fun onCrashHandleStart2GetExtraDatas(
|
||||
crashType: Int, errorType: String,
|
||||
errorMessage: String, errorStack: String
|
||||
): ByteArray? {
|
||||
return try {
|
||||
"Extra data.".toByteArray(charset("UTF-8"))
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
CrashReport.initCrashReport(this, strategy)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.mogo.tts.receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
|
||||
|
||||
/**
|
||||
* 监听系统启动
|
||||
*/
|
||||
class BootReceiver : BroadcastReceiver() {
|
||||
private val TAG = "BootReceiver"
|
||||
|
||||
private val TARGET_PKG: String = "com.mogo.launcher.f"
|
||||
private val mHandler = Handler(Looper.getMainLooper())
|
||||
private var mRetryCount = 0
|
||||
private val MAX_RETRY: Int = 20 // 最多重试 20 次
|
||||
private val DELAY: Int = 500 // 每 500ms 查一次
|
||||
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (Intent.ACTION_BOOT_COMPLETED == intent.action||Intent.ACTION_LOCKED_BOOT_COMPLETED == intent.action) { //接收BOOT_COMPLETED广播
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.tts.utils
|
||||
|
||||
import android.os.Build
|
||||
|
||||
/**
|
||||
* 对PhoneUtils扩展一些方法,获取系统的参数
|
||||
*/
|
||||
object PhoneUtilsExtend {
|
||||
|
||||
fun getDevicesSn(): String {
|
||||
return Build.getSerial()
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
BIN
libraries/mogo-tts/app/src/main/res/drawable-hdpi/ic_message.png
Normal file
BIN
libraries/mogo-tts/app/src/main/res/drawable-hdpi/ic_message.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 B |
BIN
libraries/mogo-tts/app/src/main/res/drawable/ic_message.png
Normal file
BIN
libraries/mogo-tts/app/src/main/res/drawable/ic_message.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 B |
26
libraries/mogo-tts/app/src/main/res/layout/activity_main.xml
Normal file
26
libraries/mogo-tts/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/actv_test_tts1"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="开始播放"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/actv_test_tts2"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/actv_test_tts1"
|
||||
android:text="停止播放"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
BIN
libraries/mogo-tts/app/src/main/res/mipmap-hdpi/icon.png
Normal file
BIN
libraries/mogo-tts/app/src/main/res/mipmap-hdpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
@@ -0,0 +1,6 @@
|
||||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
||||
6
libraries/mogo-tts/app/src/main/res/values/dimens.xml
Normal file
6
libraries/mogo-tts/app/src/main/res/values/dimens.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
</resources>
|
||||
10
libraries/mogo-tts/app/src/main/res/values/strings.xml
Normal file
10
libraries/mogo-tts/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">TTS Demo</string>
|
||||
<string name="deep_link">Deep Link Test</string>
|
||||
<string name="countly_hannel_name">General Notifications</string>
|
||||
<string name="countly_channel_description"><![CDATA[News & announcements]]></string>
|
||||
<string name="title_activity_another">AnotherActivity</string>
|
||||
<string name="another_activity_text">Another Activity</string>
|
||||
</resources>
|
||||
17
libraries/mogo-tts/app/src/main/res/values/styles.xml
Normal file
17
libraries/mogo-tts/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
||||
0
libraries/mogo-tts/readme.md
Normal file
0
libraries/mogo-tts/readme.md
Normal file
1
libraries/mogo-tts/tts-base/.gitignore
vendored
Normal file
1
libraries/mogo-tts/tts-base/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
67
libraries/mogo-tts/tts-base/README.md
Normal file
67
libraries/mogo-tts/tts-base/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
### 换肤SDK,
|
||||
#### 使用方式
|
||||
```java
|
||||
public class MoGoApplication extends MultiDexApplication {
|
||||
private static final String TAG = "MoGoApplication";
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// 初始化动态换肤SDK
|
||||
SkinManager.init(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
##### 基础控件0改动完成资源替换,只需要保持使用的「资源文件:drawable、string、color等」皮肤包与APP中保持一致即可
|
||||
TextView 控件的静态文字一定要用string.xml 的方式引用文字显示
|
||||
例如:
|
||||
```xml
|
||||
<TextView
|
||||
android:id="@+id/tvDevicesId"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:text="@string/devicesId"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:textSize="20dp" />
|
||||
```
|
||||
##### 如果代码中动态控制了 ImageView 的 src、background 一定要在 XML 中替换成 SkinImageView.java
|
||||
|
||||
##### 代码中动态获取资源设置:图片、文字、颜色
|
||||
```java
|
||||
// 获取颜色
|
||||
SkinResources.getInstance().getColor(resId);
|
||||
|
||||
// 获取图片
|
||||
SkinResources.getInstance().getDrawable(resId);
|
||||
|
||||
// 获取文字
|
||||
SkinResources.getInstance().getString(resId);
|
||||
|
||||
// 获取指定的资源id
|
||||
SkinResources.getInstance().getIdentifier(resId);
|
||||
|
||||
// 获取指定的Raw资源 InputStream
|
||||
SkinResources.getInstance().getRawInputStream(resId);
|
||||
|
||||
// 获取指定的Raw资源的byte[]
|
||||
SkinResources.getInstance().getRawResourceBytes(resId);
|
||||
|
||||
```
|
||||
|
||||
#### 手动控制切换皮肤
|
||||
```java
|
||||
Skin skin = new Skin(
|
||||
// 皮肤包 MD5 用于文件损坏校验的
|
||||
"d5493244467d3970834e42dc1a6f07c9",
|
||||
// 皮肤文件名称
|
||||
"app-skin-debug.skin",
|
||||
// 外网可访问的文件服务器地址
|
||||
"https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/app-skin-debug.skin");
|
||||
|
||||
// 换肤
|
||||
SkinManager.getInstance().selectSkin(this, skin);
|
||||
|
||||
// 还原
|
||||
SkinManager.getInstance().loadSkin("");
|
||||
```
|
||||
39
libraries/mogo-tts/tts-base/build.gradle
Normal file
39
libraries/mogo-tts/tts-base/build.gradle
Normal file
@@ -0,0 +1,39 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
|
||||
versionCode 1
|
||||
versionName "${MOGO_REALTIME_VERSION}"
|
||||
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
|
||||
api "com.elegant.utils:common-utils:1.0.58"
|
||||
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
0
libraries/mogo-tts/tts-base/consumer-rules.pro
Normal file
0
libraries/mogo-tts/tts-base/consumer-rules.pro
Normal file
4
libraries/mogo-tts/tts-base/gradle.properties
Normal file
4
libraries/mogo-tts/tts-base/gradle.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
GROUP=com.mogo.cloud
|
||||
POM_ARTIFACT_ID=tts-base
|
||||
VERSION_CODE=1
|
||||
VERSION_NAME=1.0.1-SNAPSHOT
|
||||
21
libraries/mogo-tts/tts-base/proguard-rules.pro
vendored
Normal file
21
libraries/mogo-tts/tts-base/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
9
libraries/mogo-tts/tts-base/src/main/AndroidManifest.xml
Normal file
9
libraries/mogo-tts/tts-base/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.tts.common">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.mogo.tts.common
|
||||
|
||||
interface IGlobalTtsCallback {
|
||||
fun onTtsSpeakStart()
|
||||
|
||||
fun onTtsSpeakEnd()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.mogo.tts.common;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/10/12
|
||||
*
|
||||
* 语音抽象
|
||||
*/
|
||||
interface IMogoTTS {
|
||||
|
||||
void initTts(Context context);
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
void release();
|
||||
|
||||
void speakTTSVoice(String tts);
|
||||
|
||||
void speakTTSVoice(String tts, IMogoTTSCallback callBack);
|
||||
|
||||
void speakTTSVoice(LangTtsEntity ttsEntity, IMogoTTSCallback callBack);
|
||||
|
||||
void stopTts();
|
||||
|
||||
void registerTtsListener(IGlobalTtsCallback callback);
|
||||
|
||||
default void clearTTSCallback(String tts) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.mogo.tts.common;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/10/12
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
interface IMogoTTSCallback {
|
||||
|
||||
/**
|
||||
* 新SDK接口
|
||||
*
|
||||
* @param ttsId
|
||||
* @param tts
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTTSStart( String ttsId, String tts ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 新SDK接口
|
||||
*
|
||||
* @param ttsId
|
||||
* @param tts
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTTSEnd( String ttsId, String tts ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 新SDK接口
|
||||
*
|
||||
* @param ttsId
|
||||
* @param tts
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTTSError( String ttsId, String tts ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 免唤醒命令响应回调
|
||||
*
|
||||
* @param cmd
|
||||
*/
|
||||
default void onCmdSelected( String cmd ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音播报临时免唤醒“确定”命令
|
||||
*
|
||||
* @param speakText 播报内容
|
||||
*/
|
||||
default void onCmdAction( String speakText ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音播报临时免唤醒“取消”命令
|
||||
*
|
||||
* @param speakText 播报内容
|
||||
*/
|
||||
default void onCmdCancel( String speakText ) {
|
||||
}
|
||||
|
||||
default void onSpeakStart( String speakText ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音播报完毕
|
||||
*
|
||||
* @param speakText 播报内容
|
||||
*/
|
||||
default void onSpeakEnd( String speakText ) {
|
||||
}
|
||||
|
||||
default void onStopTts( String speakText ) {
|
||||
}
|
||||
|
||||
default void onSpeakError( String speakText, String errorMsg) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音播报完临时命令选择超时
|
||||
*
|
||||
* @param speakText 播报内容
|
||||
*/
|
||||
default void onSpeakSelectTimeOut( String speakText ) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.mogo.tts.common
|
||||
|
||||
enum class LanguageType(val langName: String) {
|
||||
CHINESE("chinese"),
|
||||
ENGLISH("english"),
|
||||
KOREAN("korean")
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.mogo.tts.common
|
||||
|
||||
data class MultiLangTtsEntity(
|
||||
private var ttsList: List<LangTtsEntity>
|
||||
) {
|
||||
companion object {
|
||||
private const val TIMEOUT_MILLIS = 60000
|
||||
}
|
||||
|
||||
private val stringBuffer by lazy {
|
||||
StringBuffer()
|
||||
}
|
||||
|
||||
private var ttsIndex = 0
|
||||
private var timeStamp: Long = 0
|
||||
|
||||
fun ttsNext(): LangTtsEntity? {
|
||||
return if (ttsIndex in ttsList.indices) {
|
||||
ttsList[ttsIndex++]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun markTime() {
|
||||
timeStamp = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
fun isTimeout():Boolean {
|
||||
return timeStamp > 0 && System.currentTimeMillis() - timeStamp >= TIMEOUT_MILLIS
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return stringBuffer.let {
|
||||
it.setLength(0)
|
||||
ttsList.forEachIndexed { index, langTtsEntity ->
|
||||
if (index != ttsList.size - 1) {
|
||||
it.append("${langTtsEntity};")
|
||||
} else {
|
||||
it.append(langTtsEntity)
|
||||
}
|
||||
}
|
||||
it.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class LangTtsEntity(
|
||||
var ttsContent: String,
|
||||
var language: LanguageType
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "ttsContent is:$ttsContent,language is:${language.langName}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mogo.tts.common;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/10/12
|
||||
*
|
||||
* 语音打算类型
|
||||
*/
|
||||
enum PreemptType {
|
||||
|
||||
/**
|
||||
* 不打断
|
||||
*/
|
||||
PREEMPT_TYPE_NONE,
|
||||
/**
|
||||
* 立即打断,取消当前的tts插队播放
|
||||
*/
|
||||
PREEMPT_TYPE_IMMEDIATELY,
|
||||
/**
|
||||
* 下一个插入,不取消当前的tts,插队下一个播放
|
||||
*/
|
||||
PREEMPT_TYPE_NEXT,
|
||||
/**
|
||||
* 清空队列
|
||||
*/
|
||||
PREEMPT_TYPE_FLUSH,
|
||||
/**
|
||||
* 立即打断,不取消当前tts
|
||||
*/
|
||||
PREEMPT_TYPE_IMMEDIATELY_WITHOUT_CANCEL
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.mogo.tts.common
|
||||
|
||||
import android.content.Context
|
||||
import com.mogo.tts.common.log.TtsLogManager
|
||||
|
||||
object TtsManager {
|
||||
|
||||
private const val TAG = "TtsManager"
|
||||
|
||||
private var mTTS: IMogoTTS? = null
|
||||
|
||||
fun init(context: Context){
|
||||
try {
|
||||
// 暂时换成反射,解决死锁问题
|
||||
var clazz1: Class<*>? = null
|
||||
try {
|
||||
clazz1 = Class.forName("com.mogo.tts.iflytek.offline.IFlyTekOfflineTts")
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
if (clazz1 != null) {
|
||||
mTTS = clazz1.getConstructor().newInstance() as IMogoTTS
|
||||
}
|
||||
mTTS?.initTts(context)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
TtsLogManager.d(TAG,"TTS 模块初始化异常")
|
||||
}
|
||||
}
|
||||
|
||||
fun speakTTSVoice(tts:String){
|
||||
mTTS?.speakTTSVoice(tts)
|
||||
}
|
||||
|
||||
fun stopTTS(){
|
||||
mTTS?.stopTts()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.mogo.tts.common.log;
|
||||
|
||||
public enum LogLevel {
|
||||
info,warn,debug,error
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.mogo.tts.common.log;
|
||||
|
||||
public interface LogListener {
|
||||
void writeLog(LogLevel logLevel,String tag,String message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.mogo.tts.common.log
|
||||
|
||||
import android.util.Log
|
||||
|
||||
object TtsLogManager {
|
||||
|
||||
private var isDebug = true
|
||||
|
||||
private var logListener:LogListener? = null
|
||||
|
||||
fun setDebug(isDebug:Boolean){
|
||||
this.isDebug = isDebug
|
||||
}
|
||||
|
||||
fun setLogListener(logListener: LogListener){
|
||||
this.logListener = logListener
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun d(tag: String, message: String) {
|
||||
if(isDebug) {
|
||||
Log.d(tag, message);
|
||||
}
|
||||
logListener?.writeLog(LogLevel.debug,tag,message)
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun i(tag: String, message: String) {
|
||||
if(isDebug) {
|
||||
Log.i(tag, message)
|
||||
}
|
||||
logListener?.writeLog(LogLevel.info,tag,message)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun w(tag: String, message: String) {
|
||||
if(isDebug) {
|
||||
Log.w(tag, message)
|
||||
}
|
||||
logListener?.writeLog(LogLevel.warn,tag,message)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun e(tag: String, message: String) {
|
||||
if(isDebug) {
|
||||
Log.e(tag, message)
|
||||
}
|
||||
logListener?.writeLog(LogLevel.error,tag,message)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.mogo.tts.common.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class FileUtils {
|
||||
public static void copyAssetsToLocal(Context context, String assetDir, String localDir) throws IOException {
|
||||
// 获取assets目录下的所有文件和目录
|
||||
String[] files = context.getAssets().list(assetDir);
|
||||
if (files == null || files.length == 0) {
|
||||
return;
|
||||
}
|
||||
// 创建本地目标目录
|
||||
File localDirFile = new File(localDir);
|
||||
if (!localDirFile.exists()) {
|
||||
localDirFile.mkdirs();
|
||||
}
|
||||
for (String fileName : files) {
|
||||
String assetPath = assetDir + File.separator + fileName;
|
||||
String localPath = localDir + File.separator + fileName;
|
||||
// 如果是文件夹,递归调用
|
||||
if (isDirectory(context, assetPath)) {
|
||||
copyAssetsToLocal(context, assetPath, localPath);
|
||||
} else {
|
||||
try (InputStream in = context.getAssets().open(assetPath);
|
||||
FileOutputStream out = new FileOutputStream(localPath)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断 assets 中的路径是否是文件夹
|
||||
public static boolean isDirectory(Context context, String path) throws IOException {
|
||||
String[] files = context.getAssets().list(path);
|
||||
return files != null && files.length > 0;
|
||||
}
|
||||
|
||||
public static void writeFile(String path, byte[] bytes) {
|
||||
boolean append = false;
|
||||
try {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
append = true;
|
||||
}else {
|
||||
file.createNewFile();
|
||||
}
|
||||
FileOutputStream out = new FileOutputStream(path,true);//指定写到哪个路径中
|
||||
FileChannel fileChannel = out.getChannel();
|
||||
fileChannel.write(ByteBuffer.wrap(bytes)); //将字节流写入文件中
|
||||
fileChannel.force(true);//强制刷新
|
||||
fileChannel.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="skinTypeface" format="string" />
|
||||
<!--防止大面积误伤原生View,这里做一个手动开启换肤的开关,来控制是否要在这个控件上使用-->
|
||||
<attr name="isUseSkin" format="boolean" />
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">skin-core2</string>
|
||||
</resources>
|
||||
1
libraries/mogo-tts/tts-iflytek-offline/.gitignore
vendored
Normal file
1
libraries/mogo-tts/tts-iflytek-offline/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
67
libraries/mogo-tts/tts-iflytek-offline/README.md
Normal file
67
libraries/mogo-tts/tts-iflytek-offline/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
### 换肤SDK,
|
||||
#### 使用方式
|
||||
```java
|
||||
public class MoGoApplication extends MultiDexApplication {
|
||||
private static final String TAG = "MoGoApplication";
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// 初始化动态换肤SDK
|
||||
SkinManager.init(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
##### 基础控件0改动完成资源替换,只需要保持使用的「资源文件:drawable、string、color等」皮肤包与APP中保持一致即可
|
||||
TextView 控件的静态文字一定要用string.xml 的方式引用文字显示
|
||||
例如:
|
||||
```xml
|
||||
<TextView
|
||||
android:id="@+id/tvDevicesId"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:text="@string/devicesId"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:textSize="20dp" />
|
||||
```
|
||||
##### 如果代码中动态控制了 ImageView 的 src、background 一定要在 XML 中替换成 SkinImageView.java
|
||||
|
||||
##### 代码中动态获取资源设置:图片、文字、颜色
|
||||
```java
|
||||
// 获取颜色
|
||||
SkinResources.getInstance().getColor(resId);
|
||||
|
||||
// 获取图片
|
||||
SkinResources.getInstance().getDrawable(resId);
|
||||
|
||||
// 获取文字
|
||||
SkinResources.getInstance().getString(resId);
|
||||
|
||||
// 获取指定的资源id
|
||||
SkinResources.getInstance().getIdentifier(resId);
|
||||
|
||||
// 获取指定的Raw资源 InputStream
|
||||
SkinResources.getInstance().getRawInputStream(resId);
|
||||
|
||||
// 获取指定的Raw资源的byte[]
|
||||
SkinResources.getInstance().getRawResourceBytes(resId);
|
||||
|
||||
```
|
||||
|
||||
#### 手动控制切换皮肤
|
||||
```java
|
||||
Skin skin = new Skin(
|
||||
// 皮肤包 MD5 用于文件损坏校验的
|
||||
"d5493244467d3970834e42dc1a6f07c9",
|
||||
// 皮肤文件名称
|
||||
"app-skin-debug.skin",
|
||||
// 外网可访问的文件服务器地址
|
||||
"https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/app-skin-debug.skin");
|
||||
|
||||
// 换肤
|
||||
SkinManager.getInstance().selectSkin(this, skin);
|
||||
|
||||
// 还原
|
||||
SkinManager.getInstance().loadSkin("");
|
||||
```
|
||||
39
libraries/mogo-tts/tts-iflytek-offline/build.gradle
Normal file
39
libraries/mogo-tts/tts-iflytek-offline/build.gradle
Normal file
@@ -0,0 +1,39 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
|
||||
versionCode 1
|
||||
versionName "${MOGO_REALTIME_VERSION}"
|
||||
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation project(":libraries:mogo-tts:tts-base")
|
||||
implementation files('libs/AIKit.aar')
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
4
libraries/mogo-tts/tts-iflytek-offline/gradle.properties
Normal file
4
libraries/mogo-tts/tts-iflytek-offline/gradle.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
GROUP=com.mogo.cloud
|
||||
POM_ARTIFACT_ID=tts-iflytek-offline
|
||||
VERSION_CODE=1
|
||||
VERSION_NAME=1.0.1-SNAPSHOT
|
||||
BIN
libraries/mogo-tts/tts-iflytek-offline/libs/AIKit.aar
Normal file
BIN
libraries/mogo-tts/tts-iflytek-offline/libs/AIKit.aar
Normal file
Binary file not shown.
21
libraries/mogo-tts/tts-iflytek-offline/proguard-rules.pro
vendored
Normal file
21
libraries/mogo-tts/tts-iflytek-offline/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.tts.iflytek.offline">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
</manifest>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,229 @@
|
||||
package com.mogo.tts.iflytek.offline
|
||||
|
||||
import android.media.AudioFormat
|
||||
import android.media.AudioManager
|
||||
import android.media.AudioRecord
|
||||
import android.media.AudioTrack
|
||||
import android.os.Process
|
||||
import java.io.DataInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
class AudioTrackManager {
|
||||
private var mAudioTrack: AudioTrack? = null
|
||||
private var mDis: DataInputStream? = null //播放文件的数据流
|
||||
private var mRecordThread: Thread? = null
|
||||
private var isStart = false
|
||||
|
||||
//指定缓冲区大小。调用AudioRecord类的getMinBufferSize方法可以获得。
|
||||
private var mMinBufferSize = 0
|
||||
private var mSampleRate = 16000
|
||||
|
||||
private var listener: OnCompleteListener? = null
|
||||
|
||||
enum class sampleRateType {
|
||||
SAMPLE_RATE_16k,
|
||||
SAMPLE_RATE_24k
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
//根据采样率,采样精度,单双声道来得到frame的大小。
|
||||
mMinBufferSize =
|
||||
AudioTrack.getMinBufferSize(mSampleRate, mChannelConfig, mAudioFormat) //计算最小缓冲区
|
||||
//注意,按照数字音频的知识,这个算出来的是一秒钟buffer的大小。
|
||||
//创建AudioTrack
|
||||
mAudioTrack = AudioTrack(
|
||||
mStreamType, mSampleRate, mChannelConfig,
|
||||
mAudioFormat, mMinBufferSize, mMode
|
||||
)
|
||||
}
|
||||
|
||||
fun setListener(listener: OnCompleteListener) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
fun setSampleRate(sampleRate: sampleRateType?) {
|
||||
when (sampleRate) {
|
||||
sampleRateType.SAMPLE_RATE_16k -> mSampleRate = mSampleRateIn16KHz
|
||||
sampleRateType.SAMPLE_RATE_24k -> mSampleRate = mSampleRateIn24KHz
|
||||
else -> {
|
||||
mSampleRate = mSampleRateIn24KHz
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁线程方法
|
||||
*/
|
||||
private fun destroyThread() {
|
||||
try {
|
||||
isStart = false
|
||||
if (null != mRecordThread && Thread.State.RUNNABLE == mRecordThread!!.state) {
|
||||
try {
|
||||
Thread.sleep(500)
|
||||
mRecordThread!!.interrupt()
|
||||
} catch (e: Exception) {
|
||||
mRecordThread = null
|
||||
}
|
||||
}
|
||||
mRecordThread = null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
mRecordThread = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动播放线程
|
||||
*/
|
||||
private fun startThread() {
|
||||
destroyThread()
|
||||
isStart = true
|
||||
if (mRecordThread == null) {
|
||||
mRecordThread = Thread(playRunnable)
|
||||
mRecordThread!!.start()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放线程
|
||||
*/
|
||||
var playRunnable: Runnable = Runnable {
|
||||
try {
|
||||
//设置线程的优先级
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)
|
||||
val tempBuffer = ByteArray(mMinBufferSize)
|
||||
var readCount = 0
|
||||
while (mDis!!.available() > 0) {
|
||||
readCount = mDis!!.read(tempBuffer)
|
||||
if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
|
||||
continue
|
||||
}
|
||||
if (readCount != 0 && readCount != -1) { //一边播放一边写入语音数据
|
||||
//判断AudioTrack未初始化,停止播放的时候释放了,状态就为STATE_UNINITIALIZED
|
||||
if (mAudioTrack!!.state == AudioTrack.STATE_UNINITIALIZED) {
|
||||
initData()
|
||||
}
|
||||
mAudioTrack!!.play()
|
||||
mAudioTrack!!.write(tempBuffer, 0, readCount)
|
||||
}
|
||||
}
|
||||
stopPlay() //播放完就停止播放
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
listener?.onComplete()
|
||||
}
|
||||
|
||||
init {
|
||||
initData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放文件
|
||||
* @param path
|
||||
* @throws Exception
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
private fun setPath(path: String) {
|
||||
val file = File(path)
|
||||
mDis = DataInputStream(FileInputStream(file))
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动播放
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
fun startPlay(path: String) {
|
||||
try {
|
||||
// //AudioTrack未初始化
|
||||
// if(mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED){
|
||||
// throw new RuntimeException("The AudioTrack is not uninitialized");
|
||||
// }//AudioRecord.getMinBufferSize的参数是否支持当前的硬件设备
|
||||
// else if (AudioTrack.ERROR_BAD_VALUE == mMinBufferSize || AudioTrack.ERROR == mMinBufferSize) {
|
||||
// throw new RuntimeException("AudioTrack Unable to getMinBufferSize");
|
||||
// }else{
|
||||
setPath(path)
|
||||
startThread()
|
||||
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止播放
|
||||
*/
|
||||
fun stopPlay() {
|
||||
try {
|
||||
destroyThread() //销毁线程
|
||||
if (mAudioTrack != null) {
|
||||
if (mAudioTrack!!.state == AudioRecord.STATE_INITIALIZED) { //初始化成功
|
||||
mAudioTrack!!.stop() //停止播放
|
||||
}
|
||||
if (mAudioTrack != null) {
|
||||
mAudioTrack!!.release() //释放audioTrack资源
|
||||
}
|
||||
}
|
||||
if (mDis != null) {
|
||||
mDis!!.close() //关闭数据输入流
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
val playState: Int
|
||||
get() {
|
||||
if (mAudioTrack != null) {
|
||||
return mAudioTrack!!.playState
|
||||
}
|
||||
return AudioTrack.PLAYSTATE_STOPPED
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var mInstance: AudioTrackManager? = null
|
||||
|
||||
//音频流类型
|
||||
private const val mStreamType = AudioManager.STREAM_MUSIC
|
||||
|
||||
//指定采样率 (MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100,目前为常用的采样率,官方文档表示这个值可以兼容所有的设置)
|
||||
const val mSampleRateIn16KHz: Int = 16000
|
||||
const val mSampleRateIn24KHz: Int = 24000
|
||||
|
||||
//指定捕获音频的声道数目。在AudioFormat类中指定用于此的常量
|
||||
private const val mChannelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO //单声道
|
||||
|
||||
//指定音频量化位数 ,在AudioFormaat类中指定了以下各种可能的常量。通常我们选择ENCODING_PCM_16BIT和ENCODING_PCM_8BIT PCM代表的是脉冲编码调制,它实际上是原始音频样本。
|
||||
//因此可以设置每个样本的分辨率为16位或者8位,16位将占用更多的空间和处理能力,表示的音频也更加接近真实。
|
||||
private const val mAudioFormat = AudioFormat.ENCODING_PCM_16BIT
|
||||
|
||||
//STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。这个和我们在socket中发送数据一样,
|
||||
// 应用层从某个地方获取数据,例如通过编解码得到PCM数据,然后write到audiotrack。
|
||||
private const val mMode = AudioTrack.MODE_STREAM
|
||||
val instance: AudioTrackManager?
|
||||
/**
|
||||
* 获取单例引用
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
get() {
|
||||
if (mInstance == null) {
|
||||
synchronized(AudioTrackManager::class.java) {
|
||||
if (mInstance == null) {
|
||||
mInstance = AudioTrackManager()
|
||||
}
|
||||
}
|
||||
}
|
||||
return mInstance
|
||||
}
|
||||
}
|
||||
|
||||
interface OnCompleteListener {
|
||||
fun onComplete()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
package com.mogo.tts.iflytek.offline
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Looper
|
||||
import androidx.annotation.Keep
|
||||
import com.elegant.utils.ResourcesHelper
|
||||
import com.elegant.utils.ThreadPoolService
|
||||
import com.elegant.utils.UiThreadHandler
|
||||
import com.iflytek.aikit.core.AeeEvent
|
||||
import com.iflytek.aikit.core.AiHandle
|
||||
import com.iflytek.aikit.core.AiHelper
|
||||
import com.iflytek.aikit.core.AiInput
|
||||
import com.iflytek.aikit.core.AiListener
|
||||
import com.iflytek.aikit.core.AiRequest
|
||||
import com.iflytek.aikit.core.AiResponse
|
||||
import com.iflytek.aikit.core.AiText
|
||||
import com.iflytek.aikit.core.BaseLibrary
|
||||
import com.iflytek.aikit.core.CoreListener
|
||||
import com.iflytek.aikit.core.ErrType
|
||||
import com.mogo.tts.common.IGlobalTtsCallback
|
||||
import com.mogo.tts.common.IMogoTTS
|
||||
import com.mogo.tts.common.IMogoTTSCallback
|
||||
import com.mogo.tts.common.LangTtsEntity
|
||||
import com.mogo.tts.common.log.TtsLogManager
|
||||
import com.mogo.tts.common.LanguageType
|
||||
import com.mogo.tts.common.utils.FileUtils
|
||||
import java.io.File
|
||||
|
||||
@Keep
|
||||
class IFlyTekOfflineTts : IMogoTTS {
|
||||
companion object {
|
||||
const val TAG = "IFlyTekTts"
|
||||
}
|
||||
|
||||
private var context: Context? = null
|
||||
|
||||
private var aiHandle: AiHandle? = null
|
||||
private var OUTPUT_DIR :String = ""
|
||||
private val ABILITYID by lazy {
|
||||
"e2e44feff"
|
||||
}
|
||||
|
||||
// 由于主动打断不会有回调事件,所以主动打断时清掉map中被打断的text和callback
|
||||
@Volatile
|
||||
private var curTtsContent = ""
|
||||
@Volatile
|
||||
private var curTtsEntity: LangTtsEntity? = null
|
||||
|
||||
private val speakVoiceMap by lazy {
|
||||
HashMap<String, IMogoTTSCallback>()
|
||||
}
|
||||
|
||||
private var mGlobalTtsCallback: IGlobalTtsCallback? = null
|
||||
|
||||
override fun initTts(context: Context) {
|
||||
this.context = context
|
||||
initSDK()
|
||||
}
|
||||
|
||||
private fun initSDK() {
|
||||
context?.let {
|
||||
val workPath = it.filesDir.absolutePath+File.separator+"aikit"+File.separator+"xtts"
|
||||
OUTPUT_DIR = workPath+File.separator+"output"
|
||||
val file = File("$workPath/e3fe94474_1.0.0_xTTS_CnCn_xiaoyan_2018_arm.irf")
|
||||
if (!file.exists() || file.length() == 0L) {
|
||||
ThreadPoolService.execute {
|
||||
FileUtils.copyAssetsToLocal(context, "xTTS", workPath)
|
||||
initEngine(workPath)
|
||||
}
|
||||
} else {
|
||||
ThreadPoolService.execute {
|
||||
initEngine(workPath)
|
||||
}
|
||||
}
|
||||
AiHelper.getInst().registerListener(coreListener)
|
||||
AiHelper.getInst().registerListener(ABILITYID, aiRespListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun initEngine(workPath: String) {
|
||||
val params = BaseLibrary.Params.builder()
|
||||
.appId("0c498b42")
|
||||
.apiKey("8579f566eb7f3c4f4a07148ad9e2408c")
|
||||
.apiSecret("NTRmMmI5MWI4NzIzZTIxN2Q5N2FjMWVl")
|
||||
.ability("e2e44feff;e867a88f2")
|
||||
.workDir(workPath)
|
||||
.build()
|
||||
AiHelper.getInst().init(context, params)
|
||||
AudioTrackManager.instance?.setSampleRate(AudioTrackManager.sampleRateType.SAMPLE_RATE_16k)
|
||||
AudioTrackManager.instance?.setListener(completeListener)
|
||||
}
|
||||
|
||||
private val coreListener = CoreListener { type, code ->
|
||||
when (type) {
|
||||
ErrType.AUTH -> {
|
||||
if (code == 0) {
|
||||
// SDK授权成功
|
||||
TtsLogManager.d(TAG, "科大讯飞离线语音合成授权成功!")
|
||||
} else {
|
||||
// SDK授权失败,授权码为:code
|
||||
TtsLogManager.d(TAG, "科大讯飞离线语音合成授权失败码:$code")
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
// SDK状态为:type, code
|
||||
TtsLogManager.d(TAG, "type:$type, code:$code")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val completeListener = object : AudioTrackManager.OnCompleteListener {
|
||||
override fun onComplete() {
|
||||
onCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
if (Thread.currentThread() != Looper.getMainLooper().thread) {
|
||||
UiThreadHandler.post {
|
||||
AiHelper.getInst().unInit()
|
||||
}
|
||||
} else {
|
||||
AiHelper.getInst().unInit()
|
||||
}
|
||||
}
|
||||
|
||||
override fun speakTTSVoice(tts: String?) {
|
||||
speakTTSVoice(tts, null)
|
||||
}
|
||||
|
||||
override fun speakTTSVoice(tts: String?, callBack: IMogoTTSCallback?) {
|
||||
if (tts.isNullOrEmpty()) return
|
||||
speakTTSVoice(LangTtsEntity(tts, LanguageType.CHINESE), callBack)
|
||||
}
|
||||
|
||||
override fun speakTTSVoice(ttsEntity: LangTtsEntity, callBack: IMogoTTSCallback?) {
|
||||
if (Thread.currentThread() != Looper.getMainLooper().thread) {
|
||||
UiThreadHandler.post {
|
||||
if (callBack != null) {
|
||||
speakVoiceMap[ttsEntity.toString()] = callBack
|
||||
}
|
||||
speakMultiLangTTS(ttsEntity)
|
||||
}
|
||||
} else {
|
||||
if (callBack != null) {
|
||||
speakVoiceMap[ttsEntity.toString()] = callBack
|
||||
}
|
||||
speakMultiLangTTS(ttsEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun stopTts() {
|
||||
if (Thread.currentThread() != Looper.getMainLooper().thread) {
|
||||
UiThreadHandler.post {
|
||||
realStop()
|
||||
}
|
||||
} else {
|
||||
realStop()
|
||||
}
|
||||
}
|
||||
|
||||
private fun realStop() {
|
||||
TtsLogManager.d(TAG,"停止tts")
|
||||
curTtsEntity?.let {
|
||||
val string = it.toString()
|
||||
if (speakVoiceMap.containsKey(string)) {
|
||||
speakVoiceMap.remove(string)?.onStopTts(string)
|
||||
}
|
||||
curTtsEntity = null
|
||||
}
|
||||
curTtsContent = ""
|
||||
AudioTrackManager.instance?.stopPlay()
|
||||
if (aiHandle == null || aiHandle?.isSuccess == false) {
|
||||
return
|
||||
}
|
||||
val end = AiHelper.getInst().end(aiHandle)
|
||||
aiHandle = null
|
||||
TtsLogManager.d(TAG,"停止tts:${end}")
|
||||
}
|
||||
|
||||
|
||||
override fun registerTtsListener(callback: IGlobalTtsCallback?) {
|
||||
mGlobalTtsCallback = callback
|
||||
}
|
||||
|
||||
private fun speakMultiLangTTS(ttsEntity: LangTtsEntity) {
|
||||
curTtsEntity = ttsEntity
|
||||
// 合成并播放
|
||||
TtsLogManager.d(TAG, "tts准备合成:$ttsEntity")
|
||||
stopTts()
|
||||
startSpeak(ttsEntity)
|
||||
}
|
||||
|
||||
private fun startSpeak(langTtsEntity: LangTtsEntity?) {
|
||||
langTtsEntity?.let {
|
||||
curTtsContent = it.ttsContent
|
||||
realSpeak(it.ttsContent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1:中文, 2:英文, 3:法语, 5:日语, 6:俄语, 9:德语, 15:意大利语, 16:韩语, 23:西班牙语, 12:粤语, 8:印地语, 27:泰语
|
||||
*/
|
||||
private fun realSpeak(content: String) {
|
||||
deleteAllOutPutDir()
|
||||
|
||||
// 开启会话
|
||||
val builder = AiInput.builder()
|
||||
builder.param("vcn", "xiaoyan")
|
||||
builder.param("language", 1)
|
||||
builder.param("textEncoding", "UTF-8")
|
||||
builder.param("pitch", 50)
|
||||
builder.param("volume", 50)
|
||||
builder.param("speed", 50)
|
||||
aiHandle = AiHelper.getInst().start(ABILITYID, builder.build(), null)
|
||||
if (!aiHandle!!.isSuccess) {
|
||||
// handleErrorEvent("开启会话报错:${aiHandle!!.code}")
|
||||
val errorInfo = ResourcesHelper.getString(context, R.string.module_tts_start_ai_handle_error)
|
||||
handleErrorEvent("${errorInfo}${aiHandle!!.code}")
|
||||
AiHelper.getInst().end(aiHandle)
|
||||
aiHandle = null
|
||||
return
|
||||
}
|
||||
// 开始写入
|
||||
val dataBuilder = AiRequest.Builder()
|
||||
val input = AiText.get("text").data(content).valid()
|
||||
dataBuilder.payload(input)
|
||||
val ret = AiHelper.getInst().write(dataBuilder.build(), aiHandle)
|
||||
if (ret != 0) {
|
||||
// handleErrorEvent("写能力输入数据失败")
|
||||
val errorInfo = ResourcesHelper.getString(context, R.string.module_tts_write_ai_handle_error)
|
||||
handleErrorEvent(errorInfo)
|
||||
AiHelper.getInst().end(aiHandle)
|
||||
aiHandle = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteAllOutPutDir() {
|
||||
val dir = File(OUTPUT_DIR)
|
||||
if (!dir.exists() || !dir.isDirectory || dir.listFiles() == null) return
|
||||
for (file in dir.listFiles()!!) {
|
||||
if (file.isFile) file.delete() // 删除所有文件
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCompleteEvent() {
|
||||
mGlobalTtsCallback?.onTtsSpeakEnd()
|
||||
speakVoiceMap.remove(curTtsContent)?.onSpeakEnd(curTtsContent)
|
||||
curTtsContent = ""
|
||||
}
|
||||
|
||||
private fun handleErrorEvent(error: String) {
|
||||
if (curTtsEntity != null) {
|
||||
speakVoiceMap.remove(curTtsEntity.toString())
|
||||
?.onSpeakError(
|
||||
curTtsEntity.toString(),
|
||||
error
|
||||
)
|
||||
} else {
|
||||
speakVoiceMap.remove(curTtsContent)?.onSpeakError(
|
||||
curTtsContent,
|
||||
error
|
||||
)
|
||||
}
|
||||
curTtsEntity = null
|
||||
curTtsContent = ""
|
||||
}
|
||||
|
||||
private val aiRespListener = object : AiListener {
|
||||
override fun onResult(handleID: Int, list: MutableList<AiResponse>?, usrCxt: Any?) {
|
||||
if (null != list && list.size > 0) {
|
||||
val dir = File(OUTPUT_DIR)
|
||||
var bytes: ByteArray?
|
||||
for (i in list.indices) {
|
||||
bytes = list[i].value ?: continue
|
||||
TtsLogManager.d(TAG, "onResult:handleID:" + handleID + ":" + list[i].key)
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
}
|
||||
FileUtils.writeFile("${OUTPUT_DIR}/OutPut_mogo.pcm", bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEvent(
|
||||
handleID: Int,
|
||||
event: Int,
|
||||
eventData: MutableList<AiResponse>?,
|
||||
usrCxt: Any?
|
||||
) {
|
||||
when (event) {
|
||||
AeeEvent.AEE_EVENT_UNKNOWN.value -> {
|
||||
TtsLogManager.d(TAG, "未知错误")
|
||||
// handleErrorEvent("未知错误")
|
||||
aiHandle?.let {
|
||||
val ret = AiHelper.getInst().end(it)
|
||||
aiHandle = null
|
||||
TtsLogManager.d(TAG, "AIKit_End:$ret")
|
||||
}
|
||||
val errorInfo = ResourcesHelper.getString(context, R.string.module_tts_unknown_error)
|
||||
handleErrorEvent(errorInfo)
|
||||
}
|
||||
AeeEvent.AEE_EVENT_TIMEOUT.value->{
|
||||
TtsLogManager.d(TAG, "超时错误")
|
||||
// handleErrorEvent("未知错误")
|
||||
aiHandle?.let {
|
||||
val ret = AiHelper.getInst().end(it)
|
||||
aiHandle = null
|
||||
TtsLogManager.d(TAG, "AIKit_End:$ret")
|
||||
}
|
||||
val errorInfo = ResourcesHelper.getString(context, R.string.module_tts_unknown_error)
|
||||
handleErrorEvent(errorInfo)
|
||||
}
|
||||
AeeEvent.AEE_EVENT_START.value->{
|
||||
|
||||
}
|
||||
|
||||
AeeEvent.AEE_EVENT_END.value -> {
|
||||
aiHandle?.let {
|
||||
val ret = AiHelper.getInst().end(it)
|
||||
aiHandle = null
|
||||
TtsLogManager.d(TAG, "AIKit_End:$ret")
|
||||
}
|
||||
onSpeakBegin()
|
||||
AudioTrackManager.instance?.startPlay("${OUTPUT_DIR}/OutPut_mogo.pcm")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(handleID: Int, err: Int, msg: String?, usrCxt: Any?) {
|
||||
TtsLogManager.d(TAG, "错误码:$err,错误信息:$msg")
|
||||
// handleErrorEvent("错误码:$err,错误信息:$msg")
|
||||
val errorInfo = ResourcesHelper.getResources(context)
|
||||
.getString(R.string.module_tts_ai_handle_error_code, err, msg)
|
||||
handleErrorEvent(errorInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSpeakBegin() {
|
||||
mGlobalTtsCallback?.onTtsSpeakStart()
|
||||
if (Thread.currentThread() == Looper.getMainLooper().thread) {
|
||||
curTtsEntity?.let {
|
||||
speakVoiceMap[it.toString()]?.onSpeakStart(it.toString())
|
||||
}
|
||||
} else {
|
||||
UiThreadHandler.post {
|
||||
curTtsEntity?.let {
|
||||
speakVoiceMap[it.toString()]?.onSpeakStart(it.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCompleted() {
|
||||
if (Thread.currentThread() == Looper.getMainLooper().thread) {
|
||||
handleCompleteEvent()
|
||||
} else {
|
||||
UiThreadHandler.post {
|
||||
handleCompleteEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="module_tts_start_ai_handle_error">Failed to start session:</string>
|
||||
<string name="module_tts_write_ai_handle_error">Failed to write capability input data</string>
|
||||
<string name="module_tts_ai_handle_error_code">Error code: %d, Error message: %s</string>
|
||||
<string name="module_tts_unknown_error">Unknown error</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="module_tts_start_ai_handle_error">开启会话报错:</string>
|
||||
<string name="module_tts_write_ai_handle_error">写能力输入数据失败</string>
|
||||
<string name="module_tts_ai_handle_error_code">错误码:%d,错误信息:%s</string>
|
||||
<string name="module_tts_unknown_error">未知错误</string>
|
||||
</resources>
|
||||
1
libraries/mogo-tts/tts-mogo/.gitignore
vendored
Normal file
1
libraries/mogo-tts/tts-mogo/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
67
libraries/mogo-tts/tts-mogo/README.md
Normal file
67
libraries/mogo-tts/tts-mogo/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
### 换肤SDK,
|
||||
#### 使用方式
|
||||
```java
|
||||
public class MoGoApplication extends MultiDexApplication {
|
||||
private static final String TAG = "MoGoApplication";
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// 初始化动态换肤SDK
|
||||
SkinManager.init(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
##### 基础控件0改动完成资源替换,只需要保持使用的「资源文件:drawable、string、color等」皮肤包与APP中保持一致即可
|
||||
TextView 控件的静态文字一定要用string.xml 的方式引用文字显示
|
||||
例如:
|
||||
```xml
|
||||
<TextView
|
||||
android:id="@+id/tvDevicesId"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:text="@string/devicesId"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:textSize="20dp" />
|
||||
```
|
||||
##### 如果代码中动态控制了 ImageView 的 src、background 一定要在 XML 中替换成 SkinImageView.java
|
||||
|
||||
##### 代码中动态获取资源设置:图片、文字、颜色
|
||||
```java
|
||||
// 获取颜色
|
||||
SkinResources.getInstance().getColor(resId);
|
||||
|
||||
// 获取图片
|
||||
SkinResources.getInstance().getDrawable(resId);
|
||||
|
||||
// 获取文字
|
||||
SkinResources.getInstance().getString(resId);
|
||||
|
||||
// 获取指定的资源id
|
||||
SkinResources.getInstance().getIdentifier(resId);
|
||||
|
||||
// 获取指定的Raw资源 InputStream
|
||||
SkinResources.getInstance().getRawInputStream(resId);
|
||||
|
||||
// 获取指定的Raw资源的byte[]
|
||||
SkinResources.getInstance().getRawResourceBytes(resId);
|
||||
|
||||
```
|
||||
|
||||
#### 手动控制切换皮肤
|
||||
```java
|
||||
Skin skin = new Skin(
|
||||
// 皮肤包 MD5 用于文件损坏校验的
|
||||
"d5493244467d3970834e42dc1a6f07c9",
|
||||
// 皮肤文件名称
|
||||
"app-skin-debug.skin",
|
||||
// 外网可访问的文件服务器地址
|
||||
"https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/app-skin-debug.skin");
|
||||
|
||||
// 换肤
|
||||
SkinManager.getInstance().selectSkin(this, skin);
|
||||
|
||||
// 还原
|
||||
SkinManager.getInstance().loadSkin("");
|
||||
```
|
||||
37
libraries/mogo-tts/tts-mogo/build.gradle
Normal file
37
libraries/mogo-tts/tts-mogo/build.gradle
Normal file
@@ -0,0 +1,37 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
|
||||
versionCode 1
|
||||
versionName "${MOGO_REALTIME_VERSION}"
|
||||
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
0
libraries/mogo-tts/tts-mogo/consumer-rules.pro
Normal file
0
libraries/mogo-tts/tts-mogo/consumer-rules.pro
Normal file
4
libraries/mogo-tts/tts-mogo/gradle.properties
Normal file
4
libraries/mogo-tts/tts-mogo/gradle.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
GROUP=com.mogo.cloud
|
||||
POM_ARTIFACT_ID=tts-mogo
|
||||
VERSION_CODE=1
|
||||
VERSION_NAME=1.0.1-SNAPSHOT
|
||||
21
libraries/mogo-tts/tts-mogo/proguard-rules.pro
vendored
Normal file
21
libraries/mogo-tts/tts-mogo/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
5
libraries/mogo-tts/tts-mogo/src/main/AndroidManifest.xml
Normal file
5
libraries/mogo-tts/tts-mogo/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.tts.offline">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,34 @@
|
||||
# Introduction
|
||||
|
||||
Model files are from
|
||||
https://modelscope.cn/models/dengcunqin/matcha_tts_zh_en_20251010/summary
|
||||
|
||||
Note that you have to use
|
||||
vocos-16khz-univ.onnx
|
||||
|
||||
You can download it from
|
||||
https://modelscope.cn/models/dengcunqin/matcha_tts_zh_en_20251010/resolve/master/vocos-16khz-univ.onnx
|
||||
or
|
||||
https://github.com/k2-fsa/sherpa-onnx/releases/download/vocoder-models/vocos-16khz-univ.onnx
|
||||
|
||||
```
|
||||
{'am': './model-steps-3.onnx', 'vocoder': './vocos-16khz-univ.onnx', 'tokens': './tokens.txt', 'lexicon': './lexicon.txt', 'text': '中英文合成测试. It supports both English 和中文合成', 'out_wav': 'generated.wav'}
|
||||
|
||||
{'use_eos_bos': '1', 'modelscope_url': 'https://modelscope.cn/models/dengcunqin/matcha_tts_zh_en_20251010', 'sample_rate': '16000', 'language': 'chinese English', 'model_type': 'matcha-tts', 'n_speakers': '1', 'model_author': 'dengcunqin', 'version': '1', 'pad_id': '0', 'voice': 'zh en-us', 'demo_url': 'https://www.tulingyun.com/tts.html', 'num_ode_steps': '3'}
|
||||
|
||||
NodeArg(name='x', type='tensor(int64)', shape=['N', 'L'])
|
||||
NodeArg(name='x_length', type='tensor(int64)', shape=['N'])
|
||||
NodeArg(name='noise_scale', type='tensor(float)', shape=[1])
|
||||
NodeArg(name='length_scale', type='tensor(float)', shape=[1])
|
||||
-----
|
||||
NodeArg(name='mel', type='tensor(float)', shape=['N', 80, 'L'])
|
||||
|
||||
vocos {'modelscope_url': 'https://modelscope.cn/models/dengcunqin/matcha_tts_zh_en_20251010', 'use_eos_bos': '1', 'n_speakers': '1', 'sample_rate': '16000', 'pad_id': '0', 'language': 'chinese English', 'model_type': 'matcha-tts vocos', 'voice': 'zh en-us', 'version': '1', 'demo_url': 'https://www.tulingyun.com/tts.html', 'model_author': 'dengcunqin'}
|
||||
|
||||
----------vocos----------
|
||||
NodeArg(name='mels', type='tensor(float)', shape=['batch_size', 80, 'time'])
|
||||
-----
|
||||
NodeArg(name='mag', type='tensor(float)', shape=['batch_size', 'Clipmag_dim_1', 'time'])
|
||||
NodeArg(name='x', type='tensor(float)', shape=['batch_size', 'Cosx_dim_1', 'time'])
|
||||
NodeArg(name='y', type='tensor(float)', shape=['batch_size', 'Cosx_dim_1', 'time'])
|
||||
```
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user