Android开发之科大讯飞语音合成与播报

Android开发之科大讯飞语音合成与播报

  • 一、效果图
  • 二、打开[讯飞开放平台](https://www.xfyun.cn/),注册登录后,找到我的应用,点击创建新应用。
  • 三、填写相关信息,然后点击提交。
  • 四、点击创建好的应用。
  • 五、可以看到APPID信息。
  • 六、往下滑可以下载SDK。
  • 七、下载到本地后,解压。
  • 八、把刚才解压后的libs中的文件复制到项目中的libs下。
    • **1.此时这个Msc.jar还是不可用的,下面鼠标右键点击它。**
    • 2.点击Add As Library…
    • 3.点击OK,此时你可以看到它可以展开了,就说明你的app模块中已经添加了这个jar的依赖了。
  • 九、复制assets文件夹到项目中。
  • 十、粘贴到main下面,如下图所示。
  • 十一、配置项目,打开build.gradle。
  • 十二、AndroidManifest.xml中配置权限。
  • 十三、新建一个MyApplication类。
    • 1.然后在AndroidManifest.xml中配置
  • 十四、主布局文件(activity_yy)
  • 十五、主java文件(YybbActivity)

今天做一个稍微复杂点的,Android集成科大讯飞实现语音合成与播报功能。
老规矩,直接进入正题。

一、效果图

Android开发之科大讯飞语音合成与播报_第1张图片

二、打开讯飞开放平台,注册登录后,找到我的应用,点击创建新应用。

Android开发之科大讯飞语音合成与播报_第2张图片

三、填写相关信息,然后点击提交。

Android开发之科大讯飞语音合成与播报_第3张图片

四、点击创建好的应用。

Android开发之科大讯飞语音合成与播报_第4张图片

五、可以看到APPID信息。

Android开发之科大讯飞语音合成与播报_第5张图片

六、往下滑可以下载SDK。

Android开发之科大讯飞语音合成与播报_第6张图片

七、下载到本地后,解压。

Android开发之科大讯飞语音合成与播报_第7张图片
这里重点就是这个libs文件夹中的内容了。

八、把刚才解压后的libs中的文件复制到项目中的libs下。

在这里插入图片描述

1.此时这个Msc.jar还是不可用的,下面鼠标右键点击它。

Android开发之科大讯飞语音合成与播报_第8张图片

2.点击Add As Library…

Android开发之科大讯飞语音合成与播报_第9张图片

3.点击OK,此时你可以看到它可以展开了,就说明你的app模块中已经添加了这个jar的依赖了。

Android开发之科大讯飞语音合成与播报_第10张图片

九、复制assets文件夹到项目中。

Android开发之科大讯飞语音合成与播报_第11张图片

十、粘贴到main下面,如下图所示。

Android开发之科大讯飞语音合成与播报_第12张图片

十一、配置项目,打开build.gradle。

	//资源设置
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

十二、AndroidManifest.xml中配置权限。

	<!--连接网络权限,用于执行云端语音能力 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <!--读取网络信息状态 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--获取当前wifi状态 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!--允许程序改变网络连接状态 -->
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
    <!--读取手机信息权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <!--外存储写权限,构建语法需要用到此权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!--外存储读权限,构建语法需要用到此权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

十三、新建一个MyApplication类。

Android开发之科大讯飞语音合成与播报_第13张图片

package com.example;

import android.app.Application;

import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechUtility;
import org.xutils.x;
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        SpeechUtility.createUtility(MyApplication.this, SpeechConstant.APPID +"=\n" +
                "7b6e5ba7");
        super.onCreate();
        x.Ext.init(this);
        x.Ext.setDebug(BuildConfig.DEBUG);  //这个会影响性能
    }
}


1.然后在AndroidManifest.xml中配置

Android开发之科大讯飞语音合成与播报_第14张图片

十四、主布局文件(activity_yy)

Android开发之科大讯飞语音合成与播报_第15张图片


<LinearLayout 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:layout_width="match_parent"
    android:layout_height="750dp"
    android:orientation="vertical">
    <include layout="@layout/main_title_bar"/>
    <EditText
        android:id="@+id/et_text"
        android:gravity="top|left"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.TYLDApp"/>

    <Button
        android:id="@+id/btn_play"
        android:text="开始播放"
        android:layout_width="200dp"
        android:textSize="20dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@drawable/register_selector"
        android:layout_marginLeft="100dp"
        android:textColor="@color/white"/>
    <Button
        android:id="@+id/btn_cancel"
        android:text="取消"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:background="@drawable/register_selector"
        android:layout_marginLeft="100dp"/>

    <Button
        android:id="@+id/btn_pause"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:background="@drawable/register_selector"
        android:layout_marginLeft="100dp"
        android:layout_marginTop="10dp"
        android:text="暂停播放" />

    <Button
        android:id="@+id/btn_resume"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:background="@drawable/register_selector"
        android:layout_marginLeft="100dp"
        android:layout_marginTop="10dp"
        android:text="继续播放" />
    <LinearLayout
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:paddingStart="6dp"
        android:paddingEnd="6dp">

        <View
            android:layout_width="0dp"
            android:layout_height="0.5dp"
            android:layout_weight="1"
            android:background="#000" />

        <TextView
            android:layout_marginStart="6dp"
            android:layout_marginEnd="6dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置"
            android:textColor="#000"
            android:textSize="16sp" />

        <View
            android:layout_width="0dp"
            android:layout_height="0.5dp"
            android:layout_weight="1"
            android:background="#000" />
    LinearLayout>

    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingStart="6dp"
        android:paddingEnd="6dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置发音人:"
            android:textColor="#000"
            android:textSize="16sp" />

        <Spinner
            android:id="@+id/spinner"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1" />
    LinearLayout>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center_vertical"
        android:paddingStart="6dp"
        android:paddingEnd="6dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置语速:"
            android:textColor="#000"
            android:textSize="16sp" />

        <SeekBar
            android:id="@+id/sb_speed"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress="50" />
    LinearLayout>

    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center_vertical"
        android:paddingStart="6dp"
        android:paddingEnd="6dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置音调:"
            android:textColor="#000"
            android:textSize="16sp" />

        <SeekBar
            android:id="@+id/sb_pitch"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress="50" />
    LinearLayout>

    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center_vertical"
        android:paddingStart="6dp"
        android:paddingEnd="6dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置音量:"
            android:textColor="#000"
            android:textSize="16sp" />

        <SeekBar
            android:id="@+id/sb_volume"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress="50" />
    LinearLayout>

LinearLayout>


十五、主java文件(YybbActivity)

package com.example.activity;


import static com.iflytek.cloud.VerifierResult.TAG;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.MemoryFile;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.example.R;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.msc.util.FileUtil;
import com.iflytek.cloud.msc.util.log.DebugLog;

import java.util.Vector;

public class YybbActivity extends AppCompatActivity implements View.OnClickListener,AdapterView.OnItemSelectedListener {
    //语速
    private String speedValue = "50";
    //音调
    private String pitchValue = "50";
    //音量
    private String volumeValue = "50";
    //输入框
    private EditText etText;
    // 语音合成对象
    private SpeechSynthesizer mTts;
    // 默认发音人
    private String voicer = "xiaoyan";
    //发音人名称
    private static final String[] arrayName = {"讯飞小燕", "讯飞许久", "讯飞小萍", "讯飞小婧", "讯飞许小宝"};

    //发音人值
    private static final String[] arrayValue = {"xiaoyan", "aisjiuxu", "aisxping", "aisjinger", "aisbabyxu"};

    //数组适配器
    private ArrayAdapter<String> arrayAdapter;
    // 引擎类型
    private String mEngineType = SpeechConstant.TYPE_CLOUD;
    //播放的文字
    String text = " 属性:昔刘涓子晋末于丹阳郊外照射,忽见一物,高二丈许,射而中之,如雷电声若风雨。其夜不敢前追,诘旦率门徒子弟数人,寻纵至山下,见一小儿提罐,问何往为。";
    private Vector<byte[]> container = new Vector<>();
    //内存文件
    MemoryFile memoryFile;
    //总大小
    public volatile long mTotalSize = 0;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_yy);
         //请求权限
        requestPermissions();
        initView();
        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);
    }
    /**
     * 初始化页面
     */
    private void initView() {
        etText = findViewById(R.id.et_text);
        findViewById(R.id.btn_play).setOnClickListener(this);
        findViewById(R.id.btn_cancel).setOnClickListener(this);
        findViewById(R.id.btn_pause).setOnClickListener(this);
        findViewById(R.id.btn_resume).setOnClickListener(this);
       SeekBar sbSpeed = findViewById(R.id.sb_speed);
        SeekBar sbPitch = findViewById(R.id.sb_pitch);
        SeekBar sbVolume = findViewById(R.id.sb_volume);
        Spinner spinner = findViewById(R.id.spinner);
         //将可选内容与ArrayAdapter连接起来
        arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, arrayName);
        //设置下拉列表的风格
        arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //将adapter 添加到spinner中
        spinner.setAdapter(arrayAdapter);
        //添加事件Spinner事件监听
        spinner.setOnItemSelectedListener(this);

        setSeekBar(sbSpeed, 1);
        setSeekBar(sbPitch, 2);
        setSeekBar(sbVolume, 3);
    }

    /**
     * 请求权限
     */
    private void requestPermissions() {
        try {
            //Android6.0及以上版本
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                int permission = ActivityCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE);
                if (permission != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(this, new String[]
                            {Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                    Manifest.permission.WRITE_SETTINGS,
                                    Manifest.permission.READ_EXTERNAL_STORAGE}, 0x0010);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 权限请求返回结果
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    /**
     * 页面点击事件
     * @param v 控件
     */
    @Override
    public void onClick(View v) {
        if (mTts == null) {
            this.showTip("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
            return;
        }
        switch (v.getId()) {
            case R.id.btn_play://开始合成
                //输入文本
                String etStr = etText.getText().toString().trim();
                if (!etStr.isEmpty()) {
                    text = etStr;
                }
                //设置参数
                setParam();
                //开始合成播放
                int code = mTts.startSpeaking(text, mTtsListener);
                if (code != ErrorCode.SUCCESS) {
                    showTip("语音合成失败,错误码: " + code);
                }
                break;

            case R.id.btn_cancel://取消合成
                mTts.stopSpeaking();
                break;
            case R.id.btn_pause://暂停播放
                mTts.pauseSpeaking();
                break;
            case R.id.btn_resume://继续播放
                mTts.resumeSpeaking();
                break;

            default:
                break;
        }
    }
    /**
     * 初始化监听。
     */
    private InitListener mTtsInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            Log.i(TAG, "InitListener init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showTip("初始化失败,错误码:" + code);
            } else {
                showTip("初始化成功");
            }
        }
    };
    /**
     * Toast提示
     * @param msg
     */
    private void showTip(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
    /**
     * 参数设置
     *
     * @return
     */
    private void setParam() {
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);
        // 根据合成引擎设置相应参数
        if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
            mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
            //支持实时音频返回,仅在synthesizeToUri条件下支持
            mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY, "1");
            // 设置在线合成发音人
            mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);
             //设置语速
            mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);
            //设置音调
            mTts.setParameter(SpeechConstant.PITCH, pitchValue);
            //设置音量
            mTts.setParameter(SpeechConstant.VOLUME, volumeValue);
        } else {
            mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
            mTts.setParameter(SpeechConstant.VOICE_NAME, "");
        }
        // 设置播放合成音频打断音乐播放,默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "false");
        // 设置音频保存路径,保存音频格式支持pcm、wav
        mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "pcm");
        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, getExternalFilesDir(null) + "/msc/tts.pcm");
    }
    /**
     * 合成回调监听。
     */
    private SynthesizerListener mTtsListener = new SynthesizerListener() {
        //开始播放
        @Override
        public void onSpeakBegin() {
            Log.i(TAG, "开始播放");
        }

        //暂停播放
        @Override
        public void onSpeakPaused() {
            Log.i(TAG, "暂停播放");
        }

        //继续播放
        @Override
        public void onSpeakResumed() {
            Log.i(TAG, "继续播放");
        }

        //合成进度
        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos, String info) {
            Log.i(TAG, "合成进度:" + percent + "%");
        }

        //播放进度
        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {
            // 播放进度
            Log.i(TAG, "播放进度:" + percent + "%");
            SpannableStringBuilder style = new SpannableStringBuilder(text);
            style.setSpan(new BackgroundColorSpan(Color.RED), beginPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            etText.setText(style);
        }

        //播放完成
        @Override
        public void onCompleted(SpeechError error) {
            if (error == null) {
                Log.i(TAG, "播放完成," + container.size());
                DebugLog.LogD("播放完成," + container.size());
                for (int i = 0; i < container.size(); i++) {
                    //写入文件
                    writeToFile(container.get(i));
                }
                //保存文件
                FileUtil.saveFile(memoryFile, mTotalSize, getExternalFilesDir(null) + "/1.pcm");
            } else {
                //异常信息
                showTip(error.getPlainDescription(true));
            }
        }
        /**
         * 写入文件
         */
        private void writeToFile(byte[] data) {
            if (data == null || data.length == 0) {
                return;
            }
            try {
                if (memoryFile == null) {
                    Log.i(TAG, "memoryFile is null");
                    String mFilepath = getExternalFilesDir(null) + "/1.pcm";
                    memoryFile = new MemoryFile(mFilepath, 1920000);
                    memoryFile.allowPurging(false);
                }
                memoryFile.writeBytes(data, 0, (int) mTotalSize, data.length);
                mTotalSize += data.length;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //事件
        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            //	 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            //	 若使用本地能力,会话id为null
            if (SpeechEvent.EVENT_SESSION_ID == eventType) {
                String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
                Log.i(TAG, "session id =" + sid);
            }

            //当设置SpeechConstant.TTS_DATA_NOTIFY为1时,抛出buf数据
            if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
                byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
                Log.i(TAG, "bufis =" + buf.length);
                container.add(buf);
            }
        }

    };
/**
     * 选中
     */
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        voicer = arrayValue[position];
    }
    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
    //设置SeekBar
    private void setSeekBar(SeekBar seekBar, final int type) {

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                switch (type) {
                    case 1://设置语速 范围 1~100
                        speedValue = Integer.toString(progress);
                        break;
                    case 2://设置音调  范围 1~100
                        pitchValue = Integer.toString(progress);
                        break;
                    case 3://设置音量  范围 1~100
                        volumeValue = Integer.toString(progress);
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) { }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) { }
        });
    }

}

到这里就结束了,你可以试试哦

你可能感兴趣的:(android,语音识别,人工智能)