语音播报(播报本地音频文件)实现收款金额的播报
最近项目需要实现语音播报收款金额,本来要使用百度AL开发平台的语音合成进行语音播报,虽然这个是可以完美实现,但是这个在免费的情况下有这播放条数的限制,所以最终决定使用播放本地语音的方式进行实现。不多说,直接贴代码,代码也都进行了注释:
一、FileUtils文件读取工具类
public class FileUtils {public static AssetFileDescriptor getAssetFileDescription(String filename) throws IOException {AssetManager manager = CardDoctorApplication.getContext().getAssets();return manager.openFd(filename);}
}
CardDoctorApplication是自己的application类,就不贴出来了。
二、音频播放类
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 音频播放类* Created by Administrator on 2018/10/9.*/public class VoiceSpeaker {private static VoiceSpeaker sInstance;private ExecutorService service;//线程池private VoiceSpeaker() {service = Executors.newCachedThreadPool();}/*** 获取音频播放对象* @return*/public static synchronized VoiceSpeaker getInstance() {if (sInstance == null) {sInstance = new VoiceSpeaker();}return sInstance;}/*** 播放前检查* @param list*/public void speak(final List<String> list){if (service != null){service.execute(new Runnable() {@Overridepublic void run() {start(list);}});}}/*** 开始播放* @param list*/private void start(final List<String> list) {synchronized (this) {final CountDownLatch latch = new CountDownLatch(1);//并发MediaPlayer player = new MediaPlayer();/*** 遍历音频模板集合,按顺序播放音频文件*/if (list != null && list.size() > 0) {final int[] counter = {0};/*** format方法使用占位符进行格式化* %s中的 s 代表 字符串类型** path是音频文件的路径,通过格式化之后匹配到对应的音频文件*/String path = String.format("sound/tts_%s.mp3", list.get(counter[0]));AssetFileDescriptor fd = null;try {fd = FileUtils.getAssetFileDescription(path);/*** 设置要使用的数据源(FileDescriptor)。FileDescriptor必须是可搜索的(注意,LocalSocket不可搜索)。调用者有责任关闭文件描述符。* 参数说明:* 第一个参数:FileDescriptor:您要播放的文件的FileDescriptor* 第二个参数:long:要播放的数据开始的文件的偏移量,以字节为单位* 第三个参数:long:要播放的数据的字节长度*/player.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(),fd.getLength());/*** 准备播放器以异步方式播放。设置数据源和显示表面后,您需要调用prepare()或prepareAsync()。* 对于流,您应该调用prepareAsync(),它会立即返回,而不是阻塞,直到缓冲了足够的数据。*/player.prepareAsync();/*** 注册媒体源准备播放时要调用的回调。*/player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {mp.start();}});/*** 注册在回放期间到达媒体源末尾时要调用的回调。*/player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {/*** 将MediaPlayer重置为未初始化状态。调用此方法后,您必须通过设置数据源并调用prepare()再次初始化它。*/mp.reset();counter[0]++;if (counter[0] < list.size()) {try {AssetFileDescriptor fileDescriptor = FileUtils.getAssetFileDescription(String.format("sound/tts_%s.mp3", list.get(counter[0])));mp.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getLength());mp.prepare();} catch (IOException e) {e.printStackTrace();latch.countDown();//完成预期工作,发出完成信号...}} else {/*** 是否MediaPlayer资源*/mp.release();latch.countDown();//完成预期工作,发出完成信号...}}});} catch (IOException e) {e.printStackTrace();latch.countDown();//完成预期工作,发出完成信号...}finally {if (fd != null){try {fd.close();//关闭文件操作} catch (IOException e) {e.printStackTrace();}}}}try {latch.await();等待主线程执行完毕,获得开始执行信号...this.notifyAll();} catch (InterruptedException e) {e.printStackTrace();}}}
}
三、音频播放模板处理类
import android.text.TextUtils;import com.yunkahui.datacubeper.common.utils.LogUtils;import java.util.ArrayList;
import java.util.List;/*** 音频播放模板处理类* Created by Administrator on 2018/10/9.*/public class VoiceTemplate {private static final String DOT = ".";private String numString;private String prefix;//收款成功音频private String suffix;//元的音频public VoiceTemplate() {}/*** 获取播放的音频文件顺序集合** @param money* @return*/public static List<String> getDefaultTemplate(String money) {return new VoiceTemplate().prefix("success").numString(money).suffix("yuan").gen();}public String getPrefix() {return prefix;}public VoiceTemplate prefix(String prefix) {this.prefix = prefix;return this;}public String getSuffix() {return suffix;}public VoiceTemplate suffix(String suffix) {this.suffix = suffix;return this;}public String getNumString() {return numString;}public VoiceTemplate numString(String numString) {this.numString = numString;return this;}public List<String> gen() {return genVoiceList();}private List<String> createReadableNumList(String numString) {List<String> result = new ArrayList<>();if (!TextUtils.isEmpty(numString)) {int len = numString.length();for (int i = 0; i < len; i++) {if ('.' == numString.charAt(i)) {result.add("dot");} else {result.add(String.valueOf(numString.charAt(i)));}}}return result;}/*** 播放音频文件顺序** @return*/private List<String> genVoiceList() {List<String> result = new ArrayList<>();if (!TextUtils.isEmpty(prefix)) {result.add(prefix);}if (!TextUtils.isEmpty(numString)) {result.addAll(genReadableMoney(numString));}if (!TextUtils.isEmpty(suffix)) {result.add(suffix);}return result;}/*** 拆分金额成一个集合,以对应音频文件** @param numString* @return*/private List<String> genReadableMoney(String numString) {List<String> result = new ArrayList<>();if (!TextUtils.isEmpty(numString)) {/*** contains()返回TRUE时,该字符串中存在该字符* 此处判断字符串是否包含小数点*/if (numString.contains(DOT)) {String integerPart = numString.split("\\.")[0];String decimalPart = numString.split("\\.")[1];//整数部分List<String> intList = readIntPart(integerPart);//小数点之后的部分List<String> decimalList = readDecimalPart(decimalPart);result.addAll(intList);if (!decimalList.isEmpty()) {result.add("dot");result.addAll(decimalList);}} else {//intresult.addAll(readIntPart(numString));}}return result;}/*** 拆分小数点后面字符串** @param decimalPart* @return*/private List<String> readDecimalPart(String decimalPart) {List<String> result = new ArrayList<>();if (!"00".equals(decimalPart)) {char[] chars = decimalPart.toCharArray();for (char ch : chars) {result.add(String.valueOf(ch));}}return result;}/*** 当金额为整数时,直接拆分,拆分成** @param integerPart* @return*/private List<String> readIntPart(String integerPart) {List<String> result = new ArrayList<>();String intString = readLong(Long.parseLong(integerPart));int len = intString.length();for (int i = 0; i < len; i++) {char current = intString.charAt(i);if (current == '拾') {result.add("ten");} else if (current == '佰') {result.add("hundred");} else if (current == '仟') {result.add("thousand");} else if (current == '万') {result.add("ten_thousand");} else if (current == '亿') {result.add("ten_million");} else {result.add(String.valueOf(current));}}return result;}private static final char[] NUM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};private static final char[] CHINESE_UNIT = {'元', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟'};/*** 返回关于钱的中文式大写数字,支仅持到亿,超过亿则需要使用长整型long*/public static String readLong(long moneyNum) {long mMoneyNum = moneyNum;String res = "";int i = 0;if (moneyNum == 0) {return "0";}if (moneyNum == 10) {return "拾";}if (moneyNum > 10 && moneyNum < 20) {return "拾" + moneyNum % 10;}while (moneyNum > 0) {res = CHINESE_UNIT[i++] + res;res = NUM[(int) (moneyNum % 10)] + res;moneyNum /= 10;}/*** replaceAll() 方法使用给定的参数 replacement 替换字符串所有匹配给定的正则表达式的子字符串。* 参数* 第一个参数:regex -- 匹配此字符串的正则表达式。* 第二个参数:newChar -- 用来替换每个匹配项的字符串。* 成功则返回替换的字符串,失败则返回原始字符串。*/if (mMoneyNum >= 100000000) {//整亿if (mMoneyNum % 100000000 == 0) {return res.replaceAll("0[拾佰仟万]", "0").replaceAll("0+亿", "亿").replaceAll("0+万", "万").replaceAll("0+元", "元").replaceAll("0+", "0").replace("元", "");} else {//非整亿,有万位或者千位(这里万位包括万、十万、百万、千万位)String a = String.valueOf(mMoneyNum);LogUtils.e("原始数据--》" + a);LogUtils.e("截取万位--》" + a.substring(a.length() - 8, a.length() - 4));if (Long.parseLong(String.valueOf(mMoneyNum).substring(String.valueOf(mMoneyNum).length() - 8, String.valueOf(mMoneyNum).length() - 4)) == 0) {//万位为全部为0的情况,例如 1500002000.00 此情况不需要读出 万,直接读一十五亿零二千元return res.replaceAll("0[拾佰仟]", "0").replaceAll("0+亿", "亿").replaceAll("0+万", "0").replaceAll("0+元", "元").replaceAll("0+", "0").replace("元", "");} else {//万位为不为0的情况,例如 1520002000.00 此情况需要读出 万,读一十五亿二千万二千元return res.replaceAll("0[拾佰仟]", "0").replaceAll("0+亿", "亿").replaceAll("0+万", "万").replaceAll("0+元", "元").replaceAll("0+", "0").replace("元", "");}}} else {//小于一亿return res.replaceAll("0[拾佰仟]", "0").replaceAll("0+亿", "亿").replaceAll("0+万", "万").replaceAll("0+元", "元").replaceAll("0+", "0").replace("元", "");}}}
四、新建assets文件夹,把音频文件放在assets目录下
此demo可支持到千亿播放,对播放的语序也进行了一些处理,但是可能还有些许情况没有考虑到,需要使用的朋友可以按自己的需求自行添加
新添加内容:
最近接到反馈,说语音播报的速度太慢,跟一个老大爷一样,所以在处方面做了优化。此处没有使用Android自带的播放器,而是使用Google支持的第三方的播放器ExoPlayer ,需要了解ExoPlayer 可到这个网址了解,https://google.github.io/ExoPlayer/
ExoPlayer gitgub地址https://github.com/google/ExoPlayer
下面直接贴出代码,新的代码只是一个方法,替换之前的播报方法即可,或者根据需求使用两者中的其中一个即可。
private ConcatenatingMediaSource mConcatenatingMediaSource;private List<MediaSource> mMediaSourceList;
private void exoPlayerStart(final List<String> list) {synchronized (this){if (mMediaSourceList == null) {mMediaSourceList = new ArrayList<>();}mMediaSourceList.clear();final CountDownLatch latch = new CountDownLatch(1);//并发DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(CardDoctorApplication.getInstance().getContext(),Util.getUserAgent(CardDoctorApplication.getInstance().getContext(), "CardDoctor"));final SimpleExoPlayer mPlayer = ExoPlayerFactory.newSimpleInstance(CardDoctorApplication.getInstance().getContext());for (int i = 0; i < list.size(); i++) {MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(FileUtils.getAssetsPath(String.format("sound/tts_%s.mp3", list.get(i)))));mMediaSourceList.add(mediaSource);}switch (mMediaSourceList.size()) {case 1:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0));break;case 2:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1));break;case 3:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2));break;case 4:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3));break;case 5:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4));break;case 6:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5));break;case 7:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6));break;case 8:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7));break;case 9:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8));break;case 10:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9));break;case 11:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10));break;case 12:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11));break;case 13:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12));break;case 14:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13));break;case 15:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14));break;case 16:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15));break;case 17:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16));break;case 18:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17));break;case 19:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18));break;case 20:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19));break;case 21:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19),mMediaSourceList.get(20));break;case 22:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19), mMediaSourceList.get(20),mMediaSourceList.get(21));break;case 23:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19), mMediaSourceList.get(20), mMediaSourceList.get(21),mMediaSourceList.get(22));break;case 24:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19),mMediaSourceList.get(20), mMediaSourceList.get(21),mMediaSourceList.get(22), mMediaSourceList.get(23));break;case 25:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19),mMediaSourceList.get(20), mMediaSourceList.get(21),mMediaSourceList.get(22), mMediaSourceList.get(23),mMediaSourceList.get(24));break;case 26:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19),mMediaSourceList.get(20), mMediaSourceList.get(21),mMediaSourceList.get(22), mMediaSourceList.get(23),mMediaSourceList.get(24),mMediaSourceList.get(25));break;case 27:mConcatenatingMediaSource = new ConcatenatingMediaSource(mMediaSourceList.get(0), mMediaSourceList.get(1), mMediaSourceList.get(2), mMediaSourceList.get(3),mMediaSourceList.get(4), mMediaSourceList.get(5), mMediaSourceList.get(6), mMediaSourceList.get(7), mMediaSourceList.get(8), mMediaSourceList.get(9),mMediaSourceList.get(10), mMediaSourceList.get(11), mMediaSourceList.get(12), mMediaSourceList.get(13), mMediaSourceList.get(14), mMediaSourceList.get(15),mMediaSourceList.get(16), mMediaSourceList.get(17), mMediaSourceList.get(18), mMediaSourceList.get(19),mMediaSourceList.get(20), mMediaSourceList.get(21),mMediaSourceList.get(22), mMediaSourceList.get(23),mMediaSourceList.get(24),mMediaSourceList.get(25),mMediaSourceList.get(26));break;default:break;}mPlayer.addListener(new Player.EventListener() {@Overridepublic void onPlayerStateChanged(boolean playWhenReady, int playbackState) {if (playbackState == 4) {mPlayer.release();latch.countDown();}}@Overridepublic void onPlayerError(ExoPlaybackException error) {mPlayer.release();latch.countDown();}});mPlayer.prepare(mConcatenatingMediaSource);mPlayer.setPlayWhenReady(true);try {latch.await();this.notifyAll();} catch (InterruptedException e) {e.printStackTrace();}}}
最后附上播放的音频文件与以上代码https://download.csdn.net/download/freak_csh/10786233
github 项目https://github.com/freakcsh/VoiceDemo.git 此项目还接入了百度语音的demo,还有极光推送,但是极光被我干掉了,使用不了。
语音播报(播报本地音频文件)实现收款金额的播报相关推荐
- TextToSpeech文字转语音、文字转音频文件并播放
TextToSpeech文字转语音.文字转音频文件并播放 前段时间遇到了语音读网页的需求,特地在网上找了一些资料.学习完毕后跟大家分享一下.这里是我从项目中抽取出来的代码,大家应该也基本能看清楚流程了 ...
- iOS 用 AVPlayer 播放一个本地音频文件
iOS 用 AVPlayer 播放一个本地音频文件 步骤 第一步:在 Project - TARGETS - Project名 - Build Phases - Link Binary With Li ...
- iOS Dev (21) 用 AVPlayer 播放一个本地音频文件
iOS Dev (21) 用 AVPlayer 播放一个本地音频文件 作者:CSDN 大锐哥 博客:http://blog.csdn.net/prevention 前言 这篇文章与上一篇极其相似,要注 ...
- 语音转文字和音频文件转文字应该如何完成
手机自带的语音转文字功能,目前只能支持实时语音转文字,app相对比较全面,还支持音频文件转文字.那么,音频转文字如果操作呢? 1) 首先我们在手机应用市场找到:录音转文字助手,部份手机需要在百度浏览器 ...
- android 微信播放语音文件,如何将微信语音导出为MP3音频文件-Android平台
本文对于安卓用户,提供了一种相对快捷的方法. ---------以下为图文,请在本文最后点击"阅读原文"查看视频教程-------- ios平台下,导出微信语音只需要两个步骤:使用 ...
- Android播放本地音频文件
准备 音频文件置于res/raw文件夹下: 实现 /** * 监听系统静音模式 * @param mContext */ private void modeIndicater(Context mCon ...
- 将本地音频文件上传到微信公众号服务器获得文件media_id
第一步:获得微信的实时令牌token 我是通过spring cloud微服务通过注册中心映射到微信项目获得的token @FeignClient(value = "weixin-token- ...
- ajax上传本地音频文件,使用ajax将音频blob上传到文件夹中
我正在构建一个录音项目,我想通过blob将音频上传到文件夹(上传). 这是我迄今取得的成就: var url = URL.createObjectURL(blob); var li = documen ...
- js处理本地.bin音频文件和node.js的fs模块处理本地.bin音频区别
1.js处理本地.bin文件 <body><input type="file" name="" id="fileInput" ...
最新文章
- struts练习-表单提交
- linux ftp 怎么验证,Linux编译安装vsftpd服务器(本地用户验证方式)
- python插入排序_从Python看排序:插入排序
- C# 控件双缓冲控制 ControlStyles 枚举详解
- comsol 多物理场仿真流程-以开关柜为例
- java servlet 配置_servlet与javabean配置
- raft算法_学习分布式一致性协议:自己实现一个Raft算法
- 如何攻克 Android 调试难题?| 技术头条
- 嵌入式软件设计第11次实验报告
- 给model模型传数组参数
- 实例讲解木马的分析方法
- PCAN监测can总线状态设置
- JavaOOP项目 - 嗖嗖移动业务大厅
- 机器视觉1:图像预处理与瑕疵检测
- 查看电脑重启日志_win10中查看开关机时间及查看admin的RID的方法
- 当上技术领导以后才明白的事情
- 视频的编码与传输过程
- 如何配置SQL AgentMail与SQL Mail收发邮件
- java lang ClassCastException java lang Integer cannot be ca
- 阿里云对象存储OSS标准型(LRS)存储包详解
热门文章
- 贪吃蛇c语言经典程序下载,C语言实现贪吃蛇游戏(单人版)
- 项目中JS脚本的执行方式
- 佳能Canon PIXMA iP6000D 打印机驱动
- 关于STM32软硬件兼容性相关的知识
- 阿里妈妈技术质量再度重磅开源:国内首个智能化功能测试开源平台Markov
- YouTube图片幻灯片分享技巧
- java毕业设计软件源代码]springMVC+mysql实现进销存系统仓库管理系统
- bcd 初始化库系统卷失败_U盘多系统启动制作教程 教你做多U盘系统启动盘
- 关于S32K148LQFP144时钟配置的问题
- 微信内置浏览器的JsAPI(WeixinJSBridge续)