【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)

█ 【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)


█ 系列文章目录

提示:这里是收集了和音频有关的文章

  • 【安卓学习之MP3】 MP3读取格式
  • 【安卓学习之第三方库】 ZlwAudioRecorder学习:内部流程
  • 【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)

█ 文章目录

  • █ 【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)
  • █ 系列文章目录
  • █ 文章目录
  • █ 读前说明
  • █ 项目UI
  • █ 项目信息
  • █ 核心代码:TextToSpeech
  • █ 核心代码:DefaultModeActivity
  • █ 常见问题
  • █ 附赠1:LeLeTextToVoice-OCR(图片转文字)
  • █ 附赠2:TextToMp3(收费,需要联网)
  • █ 相关资料
  • █ 免责声明


█ 读前说明

  • 本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知
  • 本文只简单罗列相关的代码实现过程
  • 涉及到的逻辑以及说明也只是简单介绍,主要当做笔记,了解过程而已
  • 项目源码:ParrotTongue
  • demo:ParrotTongue文字转语音20210814.zip

█ 项目UI

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第1张图片
【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第2张图片

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第3张图片

█ 项目信息

⚡️ 提交信息:2020 年 2 月 7 日
【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第4张图片

⚡️ 配置信息
 ● 在Project的build.gradle文件中配置:

buildscript {
    repositories {
        google()
        jcenter()  
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'// 升级为 4.1.1
    }
}

● 在Project的gradle-wrapper.properties文件中配置:

#Sun Dec 08 22:42:32 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip// 升级为 6.5

● 在Module的build.gradle文件中添加依赖和属性配置:

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.whn946.parrottongue"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 4
        versionName "2.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}

█ 核心代码:TextToSpeech

⚡️ 相关方法

public String getDefaultEngine() 获取默认引擎
public Locale getDefaultLanguage() 获取默认引擎语言
public String getCurrentEngine() 获取当前引擎(改方法不可见)
public Locale getLanguage() 获取当前引擎语言

⚡️ AudioUtil :读取列表、初始化
封装系统TTS列表数据

小米手机 语言与输入法→文字转语音(TTS)输出→首选引擎→ 小爱语音引擎 tts.getDefaultEngine() com.xiaomi.mibrain.speech
工控设备 语言与输入法→文字转语音(TTS)输出→首选引擎→ Pico TTS tts.getDefaultEngine() com.svox.pico
xxx 语音引擎停用 tts.getDefaultEngine()
tts.getEngines()
null
size() = 0

实例化(注意以下)

引擎 status onInit(int status)
执行时间
tts.getEngines()
执行时间
执行顺序
正常 SUCCESS = 0 560ms
tts不为null
67ms
tts不为null
先执行tts.getEngines(),再执行onInit(int status)
onInit(int status)中,可以正常引用tts,tts已创建成功
被停用 ERROR = -1 55ms
tts为null
56ms
tts不为null
先执行onInit(int status),再执行tts.getEngines()
onInit(int status)中,如果引用tts,未赋值,会报NullPointer异常
public static List<TextToSpeech.EngineInfo> getTtsList(Context context) {
	// Google 文字转语音引擎: 语言分为 英语(美国) eng_USA、中文(中国) zho_CHN、中文(台湾) zho_TWN
	// 以下 xxx 表示当前系统设置的语音引擎的语言
    TextToSpeech  tts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {// 大约需要60ms-500ms
        	// 初始化成功后,默认引擎:com.google.android.tts,语言:xxx (如zho_CHN),默认语言:xxx (如zho_CHN)
        	int supported = mTextToSpeech.setLanguage(Locale.CHINA);// 设置 zh_CN
        	// supported :1,即LANG_COUNTRY_AVAILABLE,说明 语言的国家存在,地区不存在
        	// 修改语言后,默认引擎:com.google.android.tts,语言:zho_CHN,默认语言:xxx (如zho_CHN)
        	// 修改语言后,默认引擎:com.iflytek.speechcloud,语言:zho,默认语言:xxx (如zho_CHN)
        	int supported = mTextToSpeech.setLanguage(Locale.US);// 设置 en_US
        	// supported :1,即LANG_COUNTRY_AVAILABLE,说明 语言的国家存在,地区不存在
        	// 修改语言后,默认引擎:com.google.android.tts,语言:eng_USA,默认语言:xxx (如zho_CHN)
        	// 修改语言后,默认引擎:com.iflytek.speechcloud,语言:eng,默认语言:xxx (如zho_CHN)
        }
    });
    // 此时新建(初始化中...),默认引擎:com.google.android.tts,语言:null,默认引擎语言:null
    List<TextToSpeech.EngineInfo> list = tts.getEngines();
    // [{"icon":0,"label":"Pico TTS","name":"com.svox.pico","priority":0,"system":true},
    // {"icon":2130837536,"label":"Google文字转语音引擎","name":"com.google.android.tts","priority":100,"system":false},
    // {"icon":2130837504,"label":"度秘语音引擎3.0","name":"com.baidu.duersdk.opensdk","priority":0,"system":false},
    // {"icon":2130837527,"label":"科大讯飞语音引擎3.0","name":"com.iflytek.speechcloud","priority":0,"system":false},
    // {"icon":2130837504,"label":"讯飞语音合成","name":"com.iflytek.tts","priority":0,"system":false},
    // {"icon":2131558400,"label":"系统语音引擎","name":"com.xiaomi.mibrain.speech","priority":0,"system":false}]
    // {"icon":2131558400,"label":"Google 文字转语音引擎","name":"com.google.android.tts","priority":100,"system":true}
    // {"icon":2130903040,"label":"小爱语音引擎","name":"com.xiaomi.mibrain.speech","priority":0,"system":false}
    System.out.println(list);
    return tts.getEngines();
}

初始化TTS服务:设置引擎(讯飞语音引擎、小爱语音引擎等)、设置语言

小米手机 语言与输入法→文字转语音(TTS)输出→首选引擎→ 小爱语音引擎 tts2.getDefaultEngine() com.xiaomi.mibrain.speech
工控设备 语言与输入法→文字转语音(TTS)输出→首选引擎→ Pico TTS tts2.getDefaultEngine() com.svox.pico
xxx 语音引擎停用 tts2.getDefaultEngine()
tts2.getEngines()
null
size() = 0
public static TextToSpeech initTTS(final Context context, final String engine) {
    final TextToSpeech tts2= new TextToSpeech(context, new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {// 大约需要60ms
            int supported = 0;
            if (status == TextToSpeech.SUCCESS) {
                SharedPreferences tts_lan = context.getSharedPreferences("tts_lan", Context.MODE_PRIVATE);
                String lan_str = tts_lan.getString("tts_lan", "");// lan_str = CHINA
                //设置朗读语言
                if (lan_str.equals("CHINA")) {
                    supported = mTextToSpeech.setLanguage(Locale.CHINA);
                } else if (lan_str.equals("US")) {
                    supported = mTextToSpeech.setLanguage(Locale.US);
                }
                if ((supported != TextToSpeech.LANG_AVAILABLE) 
                	&& (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
                    Toast.makeText(context, "不支持当前语言!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }, engine);// engine = com.xiaomi.mibrain.speech(按拼音排序,默认为小爱)
	// tts2.setPitch(pitchNum);// 语调设置
	// tts2.setSpeechRate(speechRateNum);// 语速设置
    return tts2;
}

█ 核心代码:DefaultModeActivity

⚡️ 初始化引擎 getTtsListData()

 private TextToSpeech tts22;
public void getTtsListData() {
    //获取原始列表
    List<TextToSpeech.EngineInfo> tts_list = AudioUtil.getTtsList(mc);
    。。。。。。// 按拼音排序引擎,存入 tts_map
    tts22 = AudioUtil.initTTS(this, tts_map.get(0);// 默认取第一个 小爱语音引擎
    tts22.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
            // 朗读中...
        }

        @Override
        public void onDone(String utteranceId) {
            tts22.stop();
            // 循环朗读 处理
            if (isLoop && loopNum > 1) {
                String str = et.getText().toString();
                if (!tts22.isSpeaking()) {
                    tts22.speak(str, TextToSpeech.QUEUE_ADD, null, getString(R.string.app_name));
                }
                loopNum--;
            } else {
                tts22.stop();
            }
        }

        @Override
        public void onError(String utteranceId) {
        }

        @Override
        public void onError(String utteranceId, int errorCode) {
        }
    });
}

⚡️ 修改语音引擎

Spinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        tts22.setEngineByPackageName(tts_map.get(ttsListSp.getSelectedItem().toString()).toString());
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }
});

⚡️ 开始朗读和停止朗读

//开始朗读
speakBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View arg0) {
        tts22.setPitch(pitchNum);
        tts22.setSpeechRate(speechRateNum);
        String str = et.getText().toString();
        if (str.trim().equals("")) {
            sysToolUtil.msgAlert("提示", "朗读内容不能为空!", "好的", mc);
        } else {
            tts22.speak(str, TextToSpeech.QUEUE_FLUSH, null, getString(R.string.app_name));
        }
    }
});
//停止朗读
stopBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View arg0) {
        if (tts22.isSpeaking()) {
            tts22.stop();
        }
    }
});

⚡️ 保存为MP3文件(需要权限申请)

//保存音频
saveBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View arg0) {
        //按下确定键后的事件
        。。。。。。// 文件名为 fileName:xxx.mp3
        HashMap<String, String> myHashRender = new HashMap<String, String>();
        myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, et.getText().toString());// 不能为空
        int r = tts22.synthesizeToFile(et.getText().toString(),myHashRender, fileName);
        // 弹框显示保存结果
        if (r == TextToSpeech.SUCCESS) {
            // 将请求添加到TTS的队列中,合成可能还没有完成
            // setOnUtteranceProgressListener 设置监听查看是否完成转换
            sysToolUtil.msgAlert("保存成功", "文件路径:sdcard/文转音/" + fileName, "OK", mc);
        } else {
            sysToolUtil.msgAlert("保存失败", "输出流异常!", "是", mc);
        }
    }
});

█ 常见问题

⚡️ 安装语音引擎
小米手机,默认已经安装了【小爱语音引擎】

tts = new TextToSpeech(context, OnInitListener);
List list = tts.getEngines();
System.out.println(list);
[{“icon”:2130837527,“label”:“科大讯飞语音引擎3.0”,“name”:“com.iflytek.speechcloud”},
{“icon”:2130903040,“label”:“小爱语音引擎”,“name”:“com.xiaomi.mibrain.speech”}]
引擎 应用名 应用包名 说明
Pico TTS Pico TTS com.svox.pico 国内Android系统自带语音引擎包,不支持中文,支持美国英语、英语英语、法语、意大利语、德文、西班牙语
svox svox classic tts com.svox.classic 不支持中文语音
谷歌文字转语音引擎 Google 文字转语音引擎 (V 3.9.11)
Google 文字转语音引擎 (V 24.9.361717975)
com.google.android.tts 不支持5.0以下系统,大小17.98M,支持中文,支持30种语言
科大讯飞语音合成 讯飞语音合成 com.iflytek.tts 较老,不支持7.0以上系统(会奔溃),大小9M
科大讯飞语音引擎3.0 语音设置 com.iflytek.speechcloud 支持4.0以上系统,大小27.27M,支持粤语、东北话、河南话、湖南话、四川话、台湾话等
新版科大讯飞语音引擎 com.iflytek.speechsuite 2018年开始新版手机一般会内置,如oppo、vivo、华为
度秘语音引擎3.0 语音识别设置 com.baidu.duersdk.opensdk 不支持5.0以下系统,大小11.95M
小爱语音引擎 系统语音引擎(V 1.2.8)
小爱语音引擎(V 1.1.5)
com.xiaomi.mibrain.speech 小米手机一般会内置,导出来的apk(V 1.1.5)会出现异常

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第5张图片

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第6张图片

⚡️ 雷电模拟器 4.0.44,系统自带【谷歌文字转语音引擎】24.5.347911411
【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第7张图片

⚡️将tts 语音引擎 停用,实例化一个TextToSpeech可能会为null,可以检查设备是否具有TTS功能​​

        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
        try {
            startActivityForResult(intent, 1000);
            overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
        } catch (ActivityNotFoundException e) {
            Log.e("onTTSOnInit TTS",e.getMessage());
        }
D/SubSettings: Launching fragment com.android.settings.tts.TextToSpeechSettings
W/ContextImpl: Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1556 android.content.ContextWrapper.bindService:684 android.speech.tts.TextToSpeech.connectToEngine:810 android.speech.tts.TextToSpeech.initTts:780 android.speech.tts.TextToSpeech.<init>:733 
I/ActivityManager: START u0 {act=android.speech.tts.engine.CHECK_TTS_DATA pkg=com.svox.pico cmp=com.svox.pico/.CheckVoiceData} from uid 1000
V/SynthProxy: About to load libttspico.so, applyFilter=true
D/onTTSOnInit TTS: No Activity found to handle Intent { act=android.speech.action.RECOGNIZE_SPEECH (has extras) }

⚡️【科大讯飞语音合成】 在android 7.0设备上 设置会奔溃

2021-08-20 09:51:44.036 4778-4778/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.iflytek.tts, PID: 4778
    java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "BIO_f_cipher" referenced by "/data/app/com.iflytek.tts-9weCz673fGZfpxAffItn3A==/lib/arm/libwrapper.so"...
        at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
        at java.lang.System.loadLibrary(System.java:1657)
        at com.iflytek.tts.SynthProxy.<clinit>(Unknown Source:7)
        at com.iflytek.tts.TtsService.onCreate(Unknown Source:75)
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:3342)
        at android.app.ActivityThread.-wrap4(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1680)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6518)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

⚡️【小爱语音引擎(V 1.1.5)】 使用会奔溃奔溃,应该是缺少小米服务框架,就和【小米天气/MIUI天气】(com.miui.weather2)一样,可以安装,却无法打开
com.xiaomi.mibrain.speech 设置默认引擎时

2021-08-21 16:31:42.008 15516-15516/com.xiaomi.mibrain.speech E/com.xiaomi.ai.b.m: Construction failure. Failed to create folder /storage/emulated/0/MIUI/debug_log/com.xiaomi.mibrain.speech. 
2021-08-21 16:31:42.013 15516-15516/com.xiaomi.mibrain.speech E/MiSpeechSDK:VoiceRecognizeUtils: SocketException
    java.lang.SecurityException: getDeviceId: Neither user 10083 nor current process has android.permission.READ_PHONE_STATE.
        at android.os.Parcel.readException(Parcel.java:1684)
        at android.os.Parcel.readException(Parcel.java:1637)
        at com.android.internal.telephony.ITelephony$Stub$Proxy.getDeviceId(ITelephony.java:4454)
        at android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java:861)
        at com.xiaomi.ai.b.o.b(Unknown Source)
        at com.xiaomi.ai.b.o.a(Unknown Source)
        at com.xiaomi.ai.ak.a(Unknown Source)
        at com.xiaomi.ai.ak.<init>(Unknown Source)
        at com.xiaomi.ai.ae.init(Unknown Source)
        at com.xiaomi.ai.n.createEngine(Unknown Source)
        at com.xiaomi.mibrain.speech.SpeechEngineApplication.onCreate(Unknown Source)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5429)
        at android.app.ActivityThread.-wrap2(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1550)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6145)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
2021-08-21 16:31:42.144 1627-1627/com.android.settings E/TextToSpeechSettings: Failed to get sample text, no activity found for Intent { act=android.speech.tts.engine.GET_SAMPLE_TEXT pkg=com.xiaomi.mibrain.speech (has extras) })

com.xiaomi.mibrain.speech 调用播放接口

2021-08-21 16:36:37.957 19000-19000/com.xiaomi.mibrain.speech E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.xiaomi.mibrain.speech, PID: 19000
    java.lang.NoClassDefFoundError: Failed resolution of: Lmiui/app/AlertDialog$Builder;
        at com.xiaomi.mibrain.speech.CTAActivity.onCreate(Unknown Source)
        at android.app.Activity.performCreate(Activity.java:6698)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2623)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2731)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6145)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "miui.app.AlertDialog$Builder" on path: DexPathList[[zip file "/data/app/com.xiaomi.mibrain.speech-2/base.apk"],nativeLibraryDirectories=[/data/app/com.xiaomi.mibrain.speech-2/lib/arm, /data/app/com.xiaomi.mibrain.speech-2/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.xiaomi.mibrain.speech.CTAActivity.onCreate(Unknown Source) 
        at android.app.Activity.performCreate(Activity.java:6698) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2623) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2731) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6145) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782) 

com.miui.weather2 启动 MIUI天气 v12.5.9.0

021-08-21 16:23:09.487 5088-5088/com.miui.weather2 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.miui.weather2, PID: 5088
    java.lang.NoClassDefFoundError: Failed resolution of: Lmiui/os/Build;
        at com.miui.weather2.tools.ia.c(SourceFile:1)
        at com.miui.weather2.WeatherApplication.onCreate(SourceFile:2)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5429)
        at android.app.ActivityThread.-wrap2(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1550)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6145)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "miui.os.Build" on path: DexPathList[[zip file "/data/app/com.miui.weather2-1/base.apk"],nativeLibraryDirectories=[/data/app/com.miui.weather2-1/lib/arm, /data/app/com.miui.weather2-1/base.apk!/lib/armeabi, /system/lib, /vendor/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.miui.weather2.tools.ia.c(SourceFile:1) 
        at com.miui.weather2.WeatherApplication.onCreate(SourceFile:2) 
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5429) 
        at android.app.ActivityThread.-wrap2(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1550) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6145) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782) 

com.miui.weather2 启动 MIUI天气 v4.0.2

021-08-21 16:23:09.487 5088-5088/com.miui.weather2 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.miui.weather2, PID: 5088
    java.lang.NoClassDefFoundError: Failed resolution of: Lmiui/os/Build;
        at com.miui.weather2.tools.ia.c(SourceFile:1)
        at com.miui.weather2.WeatherApplication.onCreate(SourceFile:2)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5429)
        at android.app.ActivityThread.-wrap2(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1550)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6145)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "miui.os.Build" on path: DexPathList[[zip file "/data/app/com.miui.weather2-1/base.apk"],nativeLibraryDirectories=[/data/app/com.miui.weather2-1/lib/arm, /data/app/com.miui.weather2-1/base.apk!/lib/armeabi, /system/lib, /vendor/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.miui.weather2.tools.ia.c(SourceFile:1) 
        at com.miui.weather2.WeatherApplication.onCreate(SourceFile:2) 
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5429) 
        at android.app.ActivityThread.-wrap2(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1550) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6145) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782) 

⚡️pico不支持中文转换

I/TextToSpeech: Sucessfully bound to com.svox.pico
I/TextToSpeech: Connected to ComponentInfo{com.svox.pico/com.svox.pico.PicoService}
I/TextToSpeech: Set up connection to ComponentInfo{com.svox.pico/com.svox.pico.PicoService}

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第8张图片

⚡️ NullPointerException

将语音引擎停用 tts.getEngines().size()=0 AudioUtil.initTTS(mc, tts_map.get(ttsListSp.getSelectedItem().toString()).toString());报错
2021-08-17 10:56:36.595 4764-4764/com.whn946.parrottongue E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.whn946.parrottongue, PID: 4764
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.whn946.parrottongue/com.whn946.parrottongue.DefaultModeActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2781)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2859)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1592)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6518)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
        at com.whn946.parrottongue.DefaultModeActivity.getTtsListData(DefaultModeActivity.java:432)
        at com.whn946.parrottongue.DefaultModeActivity.init(DefaultModeActivity.java:102)
        at com.whn946.parrottongue.DefaultModeActivity.onCreate(DefaultModeActivity.java:72)

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第9张图片

⚡️ FileNotFoundException

Android Q(10.0)版本 默认开启沙箱模式
非沙盒路径为外置存储下的其他路径,不允许访问
文件读写失败 在manifest application中加上 android:requestLegacyExternalStorage=“true”
021-08-14 17:22:39.914 20241-20241/com.whn946.parrottongue E/TextToSpeech: Opening file /storage/emulated/0/0pcm/11-20210814172239.mp3 failed
    java.io.FileNotFoundException: open failed: EACCES (Permission denied)
        at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:315)
        at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:220)
        at android.speech.tts.TextToSpeech$17.run(TextToSpeech.java:1842)
        at android.speech.tts.TextToSpeech$17.run(TextToSpeech.java:1832)
        at android.speech.tts.TextToSpeech$Connection.runAction(TextToSpeech.java:2312)
        at android.speech.tts.TextToSpeech.runAction(TextToSpeech.java:763)
        at android.speech.tts.TextToSpeech.runAction(TextToSpeech.java:753)
        at android.speech.tts.TextToSpeech.synthesizeToFile(TextToSpeech.java:1832)
        at android.speech.tts.TextToSpeech.synthesizeToFile(TextToSpeech.java:1889)
        at com.whn946.parrottongue.DefaultModeActivity$11$1.onClick(DefaultModeActivity.java:282)
        at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7592)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第10张图片
参考:2020-04-08 关于Android java.io.FileNotFoundException: open failed: EACCES (Permission denied)_zhuhuitao_struggle-CSDN博客
Android Q 默认开启沙箱模式 导致出现文件读写失败,在manifest application中加上 android:requestLegacyExternalStorage=“true”

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第11张图片

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第12张图片

⚡️其他思路

讯飞 百度 腾讯都有,也有免费额度
可以89天的时候 再申请一个,无缝对接,永远免费使用,一年只要申请4次就可以了
用后台接口,就不需要改app,超过免费额度,特定发音人还是需要单独收费
百度 腾讯的免费额度, 不限时间吧
放到服务端转好了,Windows内置有,实现就两行代码
小公司很多不用linux,而用Window的,成本更低
亚马逊有一定的免费额度
思必驰的可以,送一千条免费
试用的话基本不收费,量大的话才会产生费用,需要注册账号,配置appkey
开始会送一个免费的服务套餐,一千次调用
如果是文字转语音,可以用TTS,讯飞有免费的
它还是离线的
云之声
离线功能设置无效
http接口
带上文字http发一个get请求

⚡️

█ 附赠1:LeLeTextToVoice-OCR(图片转文字)

⚡️在Module的build.gradle文件中添加依赖和属性配置:

dependencies {
    implementation 'com.jakewharton.rxbinding:rxbinding:1.0.0'
    implementation 'com.rmtheis:tess-two:6.2.0'
}

⚡️封装工具OCRUtils :

public class OCRUtils {

    private static final String TAG = "OCR";
    @RequiresApi(api = Build.VERSION_CODES.N)
    public static String parseImageToString(Bitmap bitmap) throws IOException {
        if( bitmap == null ){
            return "";
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;
        //图片旋转角度
        int rotate = 0;
        //先获取当前图像的方向,判断是否需要旋转
        //将bitmap转化为input
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        InputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        ExifInterface exif = new ExifInterface(isBm);
        int imageOriention = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        Log.i(TAG, "Current image orientation is " + imageOriention);

        switch (imageOriention){
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
        }

        Log.i(TAG, "Current image rotate is " + rotate);

        //获取当前图片的宽和高
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        //使用Matrix 矩阵对图片进行处理
        Matrix mtx = new Matrix();
        mtx.preRotate(rotate);

        //旋转图片
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

        //开始调用Tess函数进行识别
        TessBaseAPI baseAPI = new TessBaseAPI();
        baseAPI.setDebug(true);

        //使用默认语言初始化BaseApi
        baseAPI.init(Environment.getExternalStorageDirectory().getPath()+"/tesseract/", "eng");
        baseAPI.setImage(bitmap);

        // 获取返回值
        String recognizedText = baseAPI.getUTF8Text();
        Log.i(TAG, "exchanged : " + recognizedText);

        return recognizedText;
    }
}

⚡️使用(图片转文字) :

        RxView.clicks(findViewById(R.id.btn_ocr))
                .throttleFirst(500, TimeUnit.MILLISECONDS)
                .subscribe(new Action1<Void>() {
                    @RequiresApi(api = Build.VERSION_CODES.N)
                    @Override
                    public void call(Void aVoid) {
                        try {
                            String text = OCRUtils.parseImageToString(BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.test));
                            Log.e("MainActivity","text2 ="+text);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });

█ 附赠2:TextToMp3(收费,需要联网)

⚡️TextToMp3工具下载是一款文字转语音的工具,为你制作广告,有声小说,文档,案例。或者做一些自媒体节目。或者上传到有声小说,有声阅读平台都是非常不错的工具,推荐来下载体验。

⚡️需要联网,导出时,需要金币,金币需要充值收费
【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第13张图片

⚡️软件介绍
在这里插入图片描述

软件介绍
一款人气较高的软件。TextTomp3软件是一款文本转语音app,TextToMp3 app可以迅速将文字转化成语音,方便快捷,而且TextToMp3 app还支持外语配音,多语言支持,功能强大。
软件功能
* Text To Mp3支持多语种配音:英语配音、日语配音、韩语配音;
* Text To Mp3支持添加背景音乐;
* Text To Mp3支持录音功能;
* Text To Mp3支持mp3分享和导出;
* Text To Mp3支持文字转语音;
* Text To Mp3支持免费文字转语音(TTS)播放Mp3配音;
* Text To Mp3支持免费语音合成;
软件特色
1、广告配音:商场广告宣传配音,企业宣传配音,电影配音等;
2、语音合成:制作各种配音,小说配音,杂志,教科书阅读等;
3、广播配音:学校,企业,车站,机场和购物中心的广播;
4、多媒体配音:光盘解说、集团彩铃、电信、金融CTI的语音录制。
5、解说配音:企业专题片、建筑动画、工程标书解说等配音解说。
6、教学配音:电子词典、教材、电子图书、各类语音IC系列录制。

【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第14张图片
【安卓学习之开源项目】 ParrotTongue:文字转语音(含LeLeTextToVoice、TextToMp3项目)_第15张图片


█ 相关资料

提示:这里是参考的相关文章

  1. Mr946/ParrotTongue: 文转音-安卓调用系统TTS实现文字转语音并保存为mp3音频文件。
  2. 2020-04-08 关于Android java.io.FileNotFoundException: open failed: EACCES (Permission denied)_zhuhuitao_struggle-CSDN博客
  3. 2020-10-19 Android 10 存储模型->requestLegacyExternalStorage_woai110120130的专栏-CSDN博客_requestlegacyexternalstorage
  4. 2018-08-20 TextToSpeech文字转语音、文字转音频文件并播放 - 灰信网(软件开发博客聚合):文字内容不能超过4000个字,可以分片保存音频
  5. 2018-09-12 android客户端ORC图片识别库tess_two的使用_隔壁小王的博客-CSDN博客
  6. 2016-05-03 文字转语音花费太多时间,而synthesizeToFile Android中 - VoidCC:使用Android内置TTS Engine合成mp3文件,文字转语音花费太多时间,我已经解决了这个问题,将整个文件转换为段落块,并将段落添加到TTS引擎并直接播放。
  7. 2017-02-06 LeLeTextToVoice: 将文字转换为语音:防止重复点击rxbinding、加载动画Android-SpinKit、OCR工具Tess-Two、科大讯飞Msc.jar
  8. TextToMp3工具下载|TextToMp3v2.0.10安卓版下载 - 99安卓游戏
  9. 2018-04-13 科大讯飞语音引擎3.0下载-科大讯飞引擎3.0apk下载v3.0 安卓版-绿色资源网
  10. 官网:离线语音合成 - 语音合成 - 讯飞开放平台
  11. 官网:TextToSpeech - synthesizeToFile | Android 开发者 | Android Developers
  12. 2018-03-17 Android文字转语音引擎(TTS)简单比较及下载_yingchengyou的博客-CSDN博客_com.google.android.tts
  13. 2012-02-03 Android中文语音合成(TTS)各家引擎对比_Yao.GUET-CSDN博客_pico tts
  14. 2021-05-20 Google Text下载2021安卓手机版_手机app免费下载
  15. 2013-06-08 原生安卓系统如何安装小米天气(MIUI天气)?_百度知道
  16. 官网:云知声语音开放平台使用指南]
  17. 2018-06-06 实例化一个新的TextToSpeech给一个NullPointer异常? - 问答 - 云+社区 - 腾讯云

█ 免责声明

博主分享的所有文章内容,部分参考网上教程,引用大神高论,部分亲身实践,记下笔录,内容可能存在诸多不实之处,还望海涵,本内容仅供学习研究使用,切勿用于商业用途,若您是部分内容的作者,不喜欢此内容被分享出来,可联系博主说明相关情况通知删除,感谢您的理解与支持!

提示:转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/119703057

你可能感兴趣的:(#,AS_开源库学习,android,语音识别,java)