IT科技

HarmonyOS Sample之AI能力应用之报菜名儿

时间:2010-12-5 17:23:32  作者:数据库   来源:数据库  查看:  评论:0
内容摘要:想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com一、介绍小的时候就看过一个节目,就报菜名,一直印象很深刻,“蒸羊羔、蒸熊掌、蒸鹿尾儿、烧花

想了解更多内容,之之报请访问:

和华为官方合作共建的应用鸿蒙技术社区

https://harmonyos.51cto.com

一、介绍

小的菜名时候就看过一个节目,就报菜名,之之报一直印象很深刻,应用“蒸羊羔、菜名蒸熊掌、之之报蒸鹿尾儿、应用烧花鸭、菜名烧雏鸡儿、之之报烧子鹅、应用卤煮咸鸭、菜名酱鸡、之之报腊肉、应用松花、菜名小肚儿”,历历在目。

前几天,家里的小朋友在背诵校园童谣,背古诗,也得帮着儿,就想着可以结合AI能力开发一个小的应用,具备以下2个能力:

支持拍照,然后能提取出照片中的文字。(相机功能+通用文字提取能力) 能把提取的文字朗读出来,最后能通过语音进行控制。(Tts能力+Asr语音识别)

使用过程是这样的云服务器

拍摄照片—>预览照片---->提取文字---->朗读内容---->实现语音控制菜单(可选)

二、效果展示

三、搭建环境

安装DevEco Studio,详情请参考DevEco Studio下载。

设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

下载源码后,

使用DevEco Studio 打开项目,需要在真机上运行,参见 使用远程真机运行应用 。

四、项目结构

五、代码讲解

5.1 拍摄照片介绍(相机功能)

照片拍摄的界面是MainAbilitySlice.java,主要是申请权限的代码,初始化组件然后调用相机工具类实现拍摄功能。相机工具类参考了官方给的AI相机的示例代码,CameraUtil.java 提供了拍摄画面预览、拍照、切换前后摄像头、保存照片的站群服务器基础功能,核心代码如下:

1.初始化相机预览画面

/**  * 初始化屏幕  *  * @param surfaceContainer  */ public void initSurface(Component surfaceContainer) {      HiLog.info(LABEL, "initSurface");     //相机屏幕     surfaceProvider = new SurfaceProvider(slice);     DirectionalLayout.LayoutConfig params =             new DirectionalLayout.LayoutConfig(                     ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);     surfaceProvider.setLayoutConfig(params);     //toTop --指定是否将Surface固定在最上面,值为true表示将Surface放在AGP容器组件的顶层,false表示相反。     surfaceProvider.pinToZTop(true);     surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());     if (surfaceContainer instanceof ComponentContainer) {          ((ComponentContainer) surfaceContainer).addComponent(surfaceProvider);     } } 

2.打开相机预览画面

private void openCamera() {      HiLog.info(LABEL, "openCamera"); 

    //图像帧数据接收处理对象 

    imageReceiver = ImageReceiver.create(SCREEN_WIDTH, SCREEN_HEIGHT, ImageFormat.JPEG, IMAGE_RCV_CAPACITY);     //新图像接收监听     imageReceiver.setImageArrivalListener(this::saveImage);     //获取相机组件实例对象     CameraKit cameraKit = CameraKit.getInstance(slice.getApplicationContext());     if (cameraKit == null) {          // 处理cameraKit获取失败的情况         HiLog.error(LABEL, "CameraKit getInstance error");     }else{          //获取相机id列表         String[] cameraList = cameraKit.getCameraIds();         //获取前/后相机ID         String cameraId = cameraList.length > 1 && isCameraRear ? cameraList[1] : cameraList[0];         //相机状态回调         CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();         //创建相机         cameraKit.createCamera(cameraId, cameraStateCallback, creamEventHandler);     } } /**  * 相机状态回调  * CameraStateCallbackImpl  *  * @since 2021-03-08  */ class CameraStateCallbackImpl extends CameraStateCallback {      CameraStateCallbackImpl() {      }     @Override     public void onCreated(Camera camera) {          HiLog.info(LABEL, "onCreated");         //获取预览         previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();         if (previewSurface == null) {              HiLog.info(LABEL, "create camera filed, preview surface is null");             return;         }         try {              Thread.sleep(SLEEP_TIME);         } catch (InterruptedException exception) {              HiLog.info(LABEL, "Waiting to be interrupted");         }         //提供配置相机的方法,例如添加或移除表面,以及设置相机运行模式。         CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();         //配置预览的Surfac         cameraConfigBuilder.addSurface(previewSurface);         //配置拍照的Surface         cameraConfigBuilder.addSurface(imageReceiver.getRecevingSurface());         //相机设备配置         camera.configure(cameraConfigBuilder.build());         cameraDevice = camera;         //相机已准备好,eventId=2,设置拍照/切换摄像头按钮可用         handler.sendEvent(2);     }     ...  }  /**  * 相机预览画面回调  * 提供为表面操作添加或删除回调的方法。  */ class SurfaceCallBack implements SurfaceOps.Callback {      @Override     public void surfaceCreated(SurfaceOps callbackSurfaceOps) {          if (callbackSurfaceOps != null) {              callbackSurfaceOps                     .setFixedSize(surfaceProvider.getHeight(), surfaceProvider.getWidth());         }         openCamera();     }     @Override     public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {      }     @Override     public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {      } } 

3.实现拍照

/**  * 拍照  */ public void takePicture(Component takePictureImage) {      HiLog.info(LABEL, "takePicture");     if (!takePictureImage.isEnabled()) {          HiLog.info(LABEL, "takePicture return");         return;     }     if (cameraDevice == null || imageReceiver == null) {          return;     }     //添加一个表面作为帧捕获输出。     FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);      //添加图像接收Surface     framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());     //提供用于帧捕获配置、图像处理和图像输出的方法。     FrameConfig pictureFrameConfig = framePictureConfigBuilder.build();     //开始单帧捕捉。     cameraDevice.triggerSingleCapture(pictureFrameConfig); } 

4.保存照片

/**  * 保存照片到存储设备  * 并复制一份到分布式文件系统  *  * @param receiver  */ public void saveImage(ImageReceiver receiver) {      //文件起名     fileName = IMG_FILE_PREFIX + System.currentTimeMillis() + IMG_FILE_TYPE;     //外部存储的文件目录     targetFile = new File(slice.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);     try {          HiLog.info(LABEL, "filePath is " + targetFile.getCanonicalPath());     } catch (IOException e) {          HiLog.error(LABEL, "filePath is error");     }     ohos.media.image.Image image = receiver.readNextImage();     if (image == null) {          return;     }     ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);     bytes = new byte[component.remaining()];     component.read(bytes);     try (FileOutputStream output = new FileOutputStream(targetFile)) {          output.write(bytes);         output.flush();         //保存参数         Map<String, Object> dataMap = new HashMap<>();         dataMap.put("fileName", fileName);         dataMap.put("remaining", bytes);         //发送事件         InnerEvent event = InnerEvent.get(EVENT_IMAGESAVING_PROMTING, 1, dataMap);         handler.sendEvent(event);         //复制图片到分布式文件系统目录         DistributeFileUtil.copyPicToDistributedDir(slice, targetFile, fileName);     } catch (IOException e) {          HiLog.info(LABEL, "IOException, Save image failed");     } } 

5.相机底部缩略图的处理

用到了MyDrawTask.java工具类,它提供了将像素矩阵绘制到image组件的功能,同时处理了缩略图的大小等样式。

**  * 绘制任务  * 绘制一个照片缩略图  * @since 2021-03-08  */ public class MyDrawTask implements Component.DrawTask {      private static final HiLogLabel LABEL = new HiLogLabel(LOG_APP, 0x00204, "=>" + MyDrawTask.class.getName());     private static final int HALF = 2;     private static final int STROKE_WIDTH = 3;     private static final int MAX_SIZE = 66;     private Component component;     private PixelMap pixelMap;     private RectFloat rectSrc;     /**      * MyDrawTask      *      * @param component component      */     public MyDrawTask(Component component) {          HiLog.info(LABEL, "MyDrawTask");         this.component = component;     }     /**      * putPixelMap      * 以像素矩阵的形式提供图像      * @param pm Provides images in forms of pixel matrices      */     public void putPixelMap(PixelMap pm) {          if (pm != null) {              pixelMap = pm;             int halfWidth = pixelMap.getImageInfo().size.width / HALF;             int halfHeight = pixelMap.getImageInfo().size.height / HALF;             int center = Math.min(halfWidth, halfHeight);             rectSrc = new RectFloat(halfWidth - center, halfHeight - center, halfWidth + center, halfHeight + center);             component.invalidate();         }     }     @Override     public void onDraw(Component component1, Canvas canvas) {          int halfWidth = component.getWidth() / HALF;         int halfHeight = component.getHeight() / HALF;         int center = Math.min(halfWidth, halfHeight);         if (center > MAX_SIZE) {              center = MAX_SIZE;         }         int radius = center - STROKE_WIDTH / HALF;         if (pixelMap != null) {              canvas.drawPixelMapHolderCircleShape(new PixelMapHolder(pixelMap), rectSrc, halfWidth, halfHeight, radius);         }         Paint roundPaint = new Paint();         roundPaint.setAntiAlias(true);         roundPaint.setStyle(Paint.Style.STROKE_STYLE);         roundPaint.setStrokeWidth(STROKE_WIDTH);         roundPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);         roundPaint.setColor(Color.WHITE);         canvas.drawCircle(halfWidth, halfHeight, radius, roundPaint);     } } 

工具类中使用 EventHandler对象,实现跨线程通知的目的。

以上需要ohos.permission.CAMERA和ohos.permission.WRITE_MEDIA权限。

5.2 预览照片介绍(PixelMap的亿华云使用)

预览照片的界面是ImageAbilitySlice.java 主要是读取本地存储的照片后并做显示。

/**  * 本地读取照片并显示  *  * @param picPath  */ private void setImage(String picPath) {      HiLog.info(LABEL, "setImage");     if (picPath != null && !picPath.isEmpty()) {          PixelMap pixelMap = PixelMapUtil.getPixelMapByLocalPath(null, picPath, 1);         bigImage.setPixelMap(pixelMap);     } }  /**  * 将图片转换为PixeMap便于使用  */ public static PixelMap getPixelMapByLocalPath(byte[] imageBytes, String imagePath, int rotateCount) {      ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();     sourceOptions.formatHint = "image/jpg";     ImageSource imageSource;     if (imagePath != null && !imagePath.isEmpty()) {          imageSource = ImageSource.create(imagePath, sourceOptions);     } else if (imageBytes != null) {          imageSource = ImageSource.create(imageBytes, sourceOptions);     } else {          return null;     }     ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();     decodingOpts.desiredSize = new Size(0, 0);     //     decodingOpts.rotateDegrees = DEGREES_90 * rotateCount;     decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;     return imageSource.createPixelmap(decodingOpts); } 

5.3 提取文字介绍(通用文字识别能力)

WordRecognition.java //抽取了通用文字识别能力的工具类

TextDetectorAbilitySlice.java //文字识别能力页

1.init方法,传递要识别的图片路径和其他参数

/**  * 设置参数方法  *  * @param context      页面  * @param picturePaths   图片集合  * @param eventHandler MyEventHandle对象  * @since 2021-01-21  */ public void init(Context context, String[] picturePaths, EventHandler eventHandler) {      slice = context;     pictureLists = picturePaths;     handler = eventHandler; } 

2.开始文字识别

/**  * 文字识别方法  *  * @param picPath picPath  * @since 2021-01-21  */ public void wordRecognition(String picPath) {      HiLog.debug(LABEL, "wordRecognition");     photoPath = picPath;     // 实例化ITextDetector接口     textDetector = VisionManager.getTextDetector(slice);     // 实例化VisionImage对象image,并传入待检测图片pixelMap     pixelMap = PixelMapUtil.getPixelMapByLocalPath(null, picPath, 1);     VisionImage image = VisionImage.fromPixelMap(pixelMap);     // 定义VisionCallback<Text>回调,异步模式下用到     VisionCallback<Text> visionCallback = getVisionCallback();     // 定义ConnectionCallback回调,实现连接能力引擎成功与否后的操作     ConnectionCallback connectionCallback = getConnectionCallback(image, visionCallback);     // 建立与能力引擎的连接     VisionManager.init(slice, connectionCallback); } 

3.实现识别结果的回调函数

/**  * 提供接收服务状态变化的回调方法,  * 当服务状态改变时调用该接口。  * @param image  * @param visionCallback  * @return  */ private ConnectionCallback getConnectionCallback(VisionImage image, VisionCallback<Text> visionCallback) {      return new ConnectionCallback() {          @Override         public void onServiceConnect() {              HiLog.debug(LABEL, "onServiceConnect");             //存储给定图像中文本的检测结果。             Text text = new Text();             // 通过TextConfiguration配置textDetector()方法的运行参数             TextConfiguration.Builder builder = new TextConfiguration.Builder();             //MODE_IN模式表示SDK在调用者进程中直接调用OCR函数。             //MODE_OUT模式表示SDK作为客户端向HUAWEI HiAI Engine发送调用请求,由HUAWEI HiAI Engine进行OCR并将结果返回给调用方。             builder.setProcessMode(VisionConfiguration.MODE_IN);             builder.setDetectType(TextDetectType.TYPE_TEXT_DETECT_FOCUS_SHOOT);             builder.setLanguage(TextConfiguration.AUTO);             TextConfiguration config = builder.build();             textDetector.setVisionConfiguration(config);             // 调用ITextDetector的detect()方法             if (IS_SYNC) {                  HiLog.debug(LABEL, "IS_SYNC");                 //result不为0,说明当前OCR能力准备失败                 result = textDetector.detect(image, text, null); // 同步                 HiLog.debug(LABEL, "IS_SYNC,result:" + result);                 //                 sendResult(text.getValue());             } else {                  HiLog.debug(LABEL, "!IS_SYNC");                 //result=700:异步调用请求发送成功                 result = textDetector.detect(image, null, visionCallback); // 异步                 HiLog.debug(LABEL, "!IS_SYNC,result:" + result);             }         }         @Override         public void onServiceDisconnect() {              HiLog.debug(LABEL, "onServiceDisconnect");             // 释放             if ((IS_SYNC && result == 0 && textDetector != null)) {                  textDetector.release();             }             if (pixelMap != null) {                  pixelMap.release();                 pixelMap = null;             }             //断开HUAWEI HiAI Engine服务。             VisionManager.destroy();         }     }; } 

4.异步模式下的回调函数

/**  * 异步模式下回调  *  * @return  */ private VisionCallback<Text> getVisionCallback() {      return new VisionCallback<Text>() {          @Override         public void onResult(Text text) {              HiLog.debug(LABEL, "onResult");             //异步情况下返回识别结果后发送             sendResult(text.getValue());         }         @Override         public void onError(int index) {              HiLog.debug(LABEL, "onError");         }         @Override         public void onProcessing(float value) {              HiLog.debug(LABEL, "onProcessing");         }     }; } 

最后是通过EventHandler对象将识别的结果发送给TextDetectorAbilitySlice.java

进行界面展示。

5.4 朗读内容介绍(Tts能力)

Tts能力封装在TtsUtil.java工具类,核心类包括:

import ohos.ai.tts.TtsClient; // TTS客户端 import ohos.ai.tts.TtsListener; // TTS 监听接口 import ohos.ai.tts.TtsParams; // TTS参数 import ohos.ai.tts.constants.TtsEvent; // TTS事件 import ohos.utils.PacMap; // TTS依赖 

1.初始化参数

/**  * 初始化参数  *  * @param context      Slice对象  * @param eventHandler 事件传递对象  * @since 2021-01-21  */ public void init(Context context, EventHandler eventHandler) {      slice = context;     handler = eventHandler;     //创建Tts客户端     TtsClient.getInstance().create(slice, ttsListener); } 

2.实例化事件监听

/**  * 实例化TTS 事件监听  */ private TtsListener ttsListener = new TtsListener() {      @Override     public void onEvent(int eventType, PacMap pacMap) {          HiLog.info(LABEL, "onEvent...eventType:" + eventType);         // 定义TTS客户端创建成功的回调函数         if (eventType == TtsEvent.CREATE_TTS_CLIENT_SUCCESS) {              TtsParams ttsParams = new TtsParams();             //必填             ttsParams.setDeviceId(UUID.randomUUID().toString());             //语速             //ttsParams.setSpeed(8);             //ttsParams.setSpeaker(SPEAKER_XIAOYI);             //ttsParams.setVolume(4);             //Tts初始化结果             createSucc = TtsClient.getInstance().init(ttsParams);             //发送初始化成功事件             sendResult(createSucc + "", 4);         }     }     @Override     public void onSpeechStart(String utteranceId) {          HiLog.info(LABEL, "onSpeechStart...");         sendResult("开始朗读", 5);     }     @Override     public void onSpeechFinish(String utteranceId) {          HiLog.info(LABEL, "onSpeechFinish...");         sendResult("朗读完成", 6);     }     @Override     public void onStart(String utteranceId) {          HiLog.info(LABEL, "onStart...");     }     @Override     public void onProgress(String utteranceId, byte[] audioData, int progress) {      }     @Override     public void onFinish(String utteranceId) {          HiLog.info(LABEL, "onFinish...");     }     @Override     public void onError(String s, String s1) {          HiLog.info(LABEL, "onError...s:" + s + ",s1:" + s1);     }     @Override     public void onSpeechProgressChanged(String utteranceId, int progress) {      } }; 

5.5 语音控制介绍(Asr能力)

自定义ASR工具类AsrUtil.java ,提供了Asr的相关功能,通过语音识别获取指定菜单指令,然后执行相应动作。Asr核心类如下:

import ohos.ai.asr.AsrIntent; // 提供ASR引擎执行时所需要传入的参数类 import ohos.ai.asr.util.AsrError; // 错误码的定义类 import ohos.ai.asr.AsrListener; // 加载语音识别Listener import ohos.ai.asr.AsrClient; // 提供调用ASR引擎服务接口的类 import ohos.ai.asr.util.AsrResultKey; // ASR回调结果中的关键字封装类 

1.初始化参数

/**  * 初始化参数  *  * @param context      Slice对象  * @param eventHandler 事件传递对象  * @since 2021-01-21  */ public void initAsrClient(Context context, EventHandler eventHandler) {      HiLog.debug(LABEL, "initAsrClient");     slice = context;     handler = eventHandler;     //release();     initAudioCapture();     initAsrClient(); } 

2.实例化TTS 事件监听

//初始化 ASR 引擎时,调用者决定如何实现该接口。 private AsrListener asrListener = new MyAsrListener() {      @Override     public void onInit(PacMap params) {          HiLog.debug(LABEL, "onInit");         super.onInit(params);         //打开录音         if (!isAsrListener) {              HiLog.debug(LABEL, "!isAsrListener");             isAsrListener = true;             //新线程去处理,拾取PCM音频流交给asrClient             poolExecutor.submit(new AudioCaptureRunnable());         }     }     @Override     public void onError(int error) {          super.onError(error);         HiLog.error(LABEL, "error:" + (error == 6 ? "在设定的时间内没有语音输入时,在回调中会返回的结果码" : error));     }     @Override     public void onIntermediateResults(PacMap pacMap) {          super.onIntermediateResults(pacMap);         HiLog.debug(LABEL, "onIntermediateResults");         String result = pacMap.getString(AsrResultKey.RESULTS_INTERMEDIATE);         //发送识别结果         sendResult(result, 6);     }     @Override     public void onResults(PacMap results) {          super.onResults(results);         HiLog.debug(LABEL, "onResults");     }     @Override     public void onEnd() {          super.onEnd();         HiLog.debug(LABEL, "onEnd");         if (!recognizeOver) {              startListening();         }     } }; /**  * 获取 PCM 音频流并在录制过程中将它们发送到 ASR 引擎。  *  * @since 2021-03-08  */ private class AudioCaptureRunnable implements Runnable {      @Override     public void run() {          byte[] buffers = new byte[BYTES_LENGTH];         //录音开始         audioCapturer.start();         HiLog.debug(LABEL, "audioCapturer start!");         while (isAsrListener) {              //读取音频输入             int ret = audioCapturer.read(buffers, 0, BYTES_LENGTH);             if (ret >= 0) {                  //将 PCM 音频流写入字节数组并执行语音识别。                 asrClient.writePcm(buffers, BYTES_LENGTH);             }         }     } } 

3.初始化录音程序

/**  * 初始化录音程序  */ private void initAudioCapture() {      HiLog.debug(LABEL, "initAudioCapture");     //初始化线程池     poolExecutor =             new ThreadPoolExecutor(                     POOL_SIZE,                     POOL_SIZE,                     ALIVE_TIME,                     TimeUnit.SECONDS,                     new LinkedBlockingQueue<>(CAPACITY),                     new ThreadPoolExecutor.DiscardOldestPolicy());     //提供音频流信息     AudioStreamInfo audioStreamInfo =             new AudioStreamInfo.Builder()                     .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT)                     .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_IN_MONO)                     .sampleRate(SAMPLE_RATE)                     .build();     //提供录音所需的参数结构     AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder().audioStreamInfo(audioStreamInfo).build();     //初始化录音程序     audioCapturer = new AudioCapturer(audioCapturerInfo); } 

4.初始化 ASR 引擎服务客户端

/**  * 初始化 ASR 引擎服务客户端  */ private void initAsrClient() {      HiLog.debug(LABEL, "initAsrClient");     //创建一个 AsrClient 实例     asrClient = AsrClient.createAsrClient(slice).orElse(null);     //任务分发器 TODO     TaskDispatcher taskDispatcher = slice.getMainTaskDispatcher();     taskDispatcher.asyncDispatch(             () -> {                  if (asrClient != null) {                      //初始化 ASR 引擎服务。                     asrClient.init(setInitIntent(), asrListener);                 }             }); } //Asr引擎输入参数 private AsrIntent setInitIntent() {      HiLog.debug(LABEL, "setInitIntent");     //提供用于执行 ASR 引擎方法的输入参数。     AsrIntent initIntent = new AsrIntent();     //识别音频流     initIntent.setAudioSourceType(AsrIntent.AsrAudioSrcType.ASR_SRC_TYPE_PCM);     //     initIntent.setEngineType(AsrIntent.AsrEngineType.ASR_ENGINE_TYPE_LOCAL);     return initIntent; } 

5.开始录音和停止语音识别

public void startListening() {      HiLog.debug(LABEL, "startListening");     if (asrClient != null) {          //开始阅读和识别语音数据。         asrClient.startListening(setStartIntent());     }     sendResult("语音控制已开启---->^_^~~", 6);     recognizeOver = false;     isAsrListener = true; } /**  * 停止录音和识别  */ public void stopListening() {      HiLog.debug(LABEL, "stopListening");     if (asrClient != null) {          // 取消识别         asrClient.stopListening();     }     //识别结束     recognizeOver = true;     //isAsrListener = false;     sendResult("语音控制已关闭---->@_@~~", 6); } 

发送事件通知

5.6 NluAbilitySlice.java 代码

/**  * 朗读文本  */ private void speakingText() {      try {          if (initTtsResult) {              HiLog.debug(LABEL, "speakingText,text:" + inputText.getText());             stopSpeaking();             //朗读长文本,文本最大支持长度为100000,speakText最长512个字符             TtsClient.getInstance().speakLongText(inputText.getText(), null);         } else {              new ToastDialog(this).setText("Tts客户端初始化失败").show();         }     } catch (Exception e) {          HiLog.error(LABEL,"ERROR:"+e.getLocalizedMessage());         e.printStackTrace();     } } /**  * 停止朗读  */ private void stopSpeaking() {      TtsClient.getInstance().stopSpeak(); } 

匹配语音指令

//命令关键词 private static final Map<String, Boolean> COMMAND_MAP = new HashMap<>(); static {      COMMAND_MAP.put("朗读菜单", true);     COMMAND_MAP.put("关闭语音控制", true);     COMMAND_MAP.put("停止朗读", true);     COMMAND_MAP.put("获取分词", true);     COMMAND_MAP.put("词性标注", true);     COMMAND_MAP.put("提取关键字", true);     COMMAND_MAP.put("实体识别", true); }  /**  * 匹配指令  *  * @param result  * @return  */ private void matchWords(String result) {      if (result != null && !result.isEmpty()) {          if (result.indexOf({ ) == -1) {              resultText.setText(result);         } else {              JSONObject jsonObject = JSONObject.parseObject(result);             JSONObject resultObject = new JSONObject();             if (jsonObject.getJSONArray("result").get(0) instanceof JSONObject) {                  resultObject = (JSONObject) jsonObject.getJSONArray("result").get(0);             }             String resultWord = resultObject.getString("ori_word").replace(" ", "");             resultText.setText(resultWord);             boolean command = COMMAND_MAP.getOrDefault(resultWord, false);             HiLog.debug(LABEL, "command:" + command);             switch (resultWord) {                  case "朗读菜单":                     HiLog.debug(LABEL, resultWord);                     speakingText();                     break;                 case "停止朗读":                     HiLog.debug(LABEL, resultWord);                     stopSpeaking();                     break;                 case "关闭语音控制":                     HiLog.debug(LABEL, resultWord);                     asrUtil.stopListening();                     break;                 case "获取分词":                     HiLog.debug(LABEL, resultWord);                     //分词能力                     String requestData = "{ \"text\":\"" + inputText.getText() + "\",\"type\":9223372036854775807}";                     nluClientUtil.wordSegment(requestData);                     break;             }         }     } } /**  * 事件Handle  *  * @since 2021-01-15  */ public class MyEventHandler extends EventHandler {      MyEventHandler(EventRunner runner) throws IllegalArgumentException {          super(runner);     }     @Override     protected void processEvent(InnerEvent event) {          super.processEvent(event);         //事件类型         HiLog.debug(LABEL, "processEvent,eventId:" + event.eventId);         switch (event.eventId) {              //分词事件             case 0:                 if (event.object instanceof List) {                      Optional<List<String>> optionalStringList = TypeUtil.castList(event.object, String.class);                     if (optionalStringList.isPresent() && optionalStringList.get().size() > 0                             && (!"no keywords".equals(optionalStringList.get().get(0)))) {                          //获取分词结果列表                         List<String> lists = optionalStringList.get();                         resultText.setText(lists.toString());                     }                 }                 break;             //Tts初始化成功事件             case 4:                 Boolean success = Boolean.valueOf(event.object + "");                 HiLog.debug(LABEL, "processEvent,initTtsResult:" + success);                 initTtsResult = success;                 break;             case 6:                 String audio = String.valueOf(event.object);                 //HiLog.debug(LABEL, "processEvent,audio:" + audio);                 //匹配命令                 matchWords(audio);                 break;             default:                 HiLog.debug(LABEL, "processEvent,String:");                 String res = String.valueOf(event.object);                 HiLog.debug(LABEL, "processEvent,res:" + res);                 resultText.setText(res);                 break;         }     } } 

六、完整代码

附件可以直接下载

https://harmonyos.51cto.com/resource/1539

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap