鸿蒙5 AI语音备忘录开发实战:语音转写与多设备同步 原创

进修的泡芙
发布于 2025-6-20 13:58
浏览
0收藏

鸿蒙5 AI语音备忘录开发实战:语音转写与多设备同步

一、项目概述与架构设计

本AI语音备忘录基于鸿蒙5的AI语音识别和分布式能力实现,主要功能包括:
实时语音转文字记录

备忘录内容多设备同步

语音指令控制

智能分类与搜索

技术架构图

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
手机设备 │ │ 平板设备 │ │ 手表设备 │

┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │

│ 语音输入 │─┼───▶│ │ 文本显示 │ │ │ │ 快速查看 │ │

└────────┘ │ │ └────────┘ │ │ └────────┘ │

└───────┬─────┘ └───────┬─────┘ └───────┬─────┘
│ │

    └─────────┬────────┴─────────┬────────┘

      ┌───────▼───────┐   ┌───────▼───────┐

分布式数据服务 │ │ AI语音服务 │

      └───────────────┘   └───────────────┘

二、核心代码实现
语音识别服务封装

// VoiceService.ets
import asr from ‘@ohos.ai.asr’;
import distributedData from ‘@ohos.data.distributedData’;

export class VoiceService {
private asrEngine: asr.AsrEngine;
private kvStore: distributedData.KVStore;
private readonly STORE_ID = ‘voice_memo_store’;

async init() {
// 初始化语音识别引擎
const config: asr.AsrConfig = {
language: ‘zh-CN’,
feature: asr.AsrFeature.FEATURE_WORD_FLUX,
audioFormat: {
sampleRate: 16000,
channelCount: 1,
sampleFormat: asr.AudioSampleFormat.SAMPLE_FORMAT_S16LE
};

this.asrEngine = await asr.createAsrEngine(config);

// 初始化分布式数据
const kvManager = await distributedData.createKVManager({
  bundleName: 'com.example.voicememo'
});
this.kvStore = await kvManager.getKVStore(this.STORE_ID, {
  createIfMissing: true,
  autoSync: true
});

async startRecording(callback: (text: string) => void) {

// 设置识别结果回调
this.asrEngine.on('result', (result: asr.AsrResult) => {
  if (result.text) {
    callback(result.text);
    this.syncTranscript(result.text);

});

await this.asrEngine.start();

async stopRecording() {

await this.asrEngine.stop();

private async syncTranscript(text: string) {

try {
  await this.kvStore.put(memo_${Date.now()}, JSON.stringify({
    text,
    deviceId: deviceInfo.deviceId,
    timestamp: new Date().getTime()
  }));

catch (err) {

  console.error('同步备忘录失败:', err);

}

subscribeTranscriptChanges(callback: (text: string) => void) {
this.kvStore.on(‘dataChange’, distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, (changes) => {
changes.forEach(change => {
if (change.key.startsWith(‘memo_’)) {
const data = JSON.parse(change.value);
if (data.deviceId !== deviceInfo.deviceId) {
callback(data.text);
}

  });
});

}

备忘录数据模型

// MemoModel.ets
export interface VoiceMemo {
id: string;
text: string;
timestamp: number;
deviceId?: string;
category?: string;
isImportant?: boolean;
export interface MemoCategory {

id: string;
name: string;
color: string;

备忘录主界面

// VoiceMemoPage.ets
@Entry
@Component
struct VoiceMemoPage {
@State memos: VoiceMemo[] = [];
@State isRecording: boolean = false;
@State currentText: string = ‘’;

private voiceService = new VoiceService();
private memoManager = new MemoManager();

aboutToAppear() {
this.voiceService.init();
this.loadMemos();
this.subscribeToUpdates();
build() {

Column() {
  // 录音控制区域
  RecordControl({
    isRecording: this.isRecording,
    onStart: this.startRecording.bind(this),
    onStop: this.stopRecording.bind(this)
  })
  
  // 实时转写文本
  if (this.currentText) {
    Text(this.currentText)
      .fontSize(16)
      .padding(10)

// 备忘录列表

  MemoList({
    memos: this.memos,
    onDelete: this.deleteMemo.bind(this),
    onCategoryChange: this.changeCategory.bind(this)
  })

}

private async startRecording() {
this.isRecording = true;
await this.voiceService.startRecording((text) => {
this.currentText = text;
});
private async stopRecording() {

this.isRecording = false;
await this.voiceService.stopRecording();

if (this.currentText) {
  await this.memoManager.saveMemo(this.currentText);
  this.currentText = '';

}

private subscribeToUpdates() {
this.voiceService.subscribeTranscriptChanges((text) => {
this.memos = […this.memos, {
id: Date.now().toString(),
text,
timestamp: Date.now()
}];
});
}

三、关键技术创新点
多设备语音指令协同

// 语音指令处理器
class VoiceCommandProcessor {
private commands = {
‘保存’: this.handleSaveCommand,
‘删除’: this.handleDeleteCommand,
‘重要’: this.handleImportantCommand
};

processCommand(text: string, memo: VoiceMemo) {
const command = this.detectCommand(text);
if (command && this.commands[command]) {
this.commandsmemo;
}

private detectCommand(text: string): string | null {
for (const cmd in this.commands) {
if (text.includes(cmd)) {
return cmd;
}

return null;

private async handleSaveCommand(memo: VoiceMemo) {

await memoManager.saveMemo(memo.text);

}

智能分类算法

// 备忘录自动分类
class MemoClassifier {
private categories: MemoCategory[] = [
id: ‘work’, name: ‘工作’, keywords: [‘会议’, ‘项目’, ‘报告’] },

id: ‘personal’, name: ‘个人’, keywords: [‘购物’, ‘家人’, ‘朋友’] },

id: ‘idea’, name: ‘想法’, keywords: [‘创意’, ‘建议’, ‘灵感’] }

];

classifyMemo(text: string): string {
for (const category of this.categories) {
if (category.keywords.some(keyword => text.includes(keyword))) {
return category.id;
}

return 'other';

}

分布式冲突解决

// 备忘录冲突解决
private resolveMemoConflict(local: VoiceMemo, remote: VoiceMemo): VoiceMemo {
// 策略1: 时间戳优先
if (remote.timestamp > local.timestamp) {
return remote;
// 策略2: 设备优先级

const devicePriority = [‘tablet’, ‘phone’, ‘watch’];
if (devicePriority.indexOf(remote.deviceId) > devicePriority.indexOf(local.deviceId)) {
return remote;
// 策略3: 内容长度优先

if (remote.text.length > local.text.length) {
return remote;
return local;

四、完整UI组件实现
录音控制组件

// RecordControl.ets
@Component
struct RecordControl {
@Prop isRecording: boolean;
@Prop onStart: () => void;
@Prop onStop: () => void;

build() {
Column() {
if (this.isRecording) {
Button(‘停止录音’, { type: ButtonType.Capsule })
.width(120)
.height(120)
.onClick(() => this.onStop())
else {

    Button('开始录音', { type: ButtonType.Capsule })
      .width(120)
      .height(120)
      .onClick(() => this.onStart())

// 录音动画

  if (this.isRecording) {
    Row() {
      ForEach([1, 2, 3, 4, 5], (i) => {
        Rect()
          .width(8)
          .height(20 + Math.random() * 30)
          .fill(Color.Blue)
          .margin(2)
          .animation({
            duration: 300,
            iterations: -1,
            delay: i * 100
          })
      })

.margin({ top: 20 })

}

.padding(20)

}

备忘录列表组件

// MemoList.ets
@Component
struct MemoList {
@Prop memos: VoiceMemo[];
@Prop onDelete: (id: string) => void;
@Prop onCategoryChange: (id: string, category: string) => void;

@State categories: MemoCategory[] = [
id: ‘work’, name: ‘工作’, color: ‘#FF5722’ },

id: ‘personal’, name: ‘个人’, color: ‘#2196F3’ },

id: ‘idea’, name: ‘想法’, color: ‘#4CAF50’ }

];

build() {
List() {
ForEach(this.memos, (memo) => {
ListItem() {
Column() {
Text(memo.text)
.fontSize(16)
.margin({ bottom: 5 })

        Row() {
          Text(this.formatDate(memo.timestamp))
            .fontSize(12)
            .opacity(0.6)
          
          // 分类标签
          if (memo.category) {
            Text(this.getCategoryName(memo.category))
              .fontSize(12)
              .padding(5)
              .backgroundColor(this.getCategoryColor(memo.category))
              .borderRadius(10)
              .margin({ left: 10 })

}

        // 操作按钮
        Row() {
          Button('删除', { type: ButtonType.Text })
            .onClick(() => this.onDelete(memo.id))
          
          // 分类选择
          Select(this.categories.map(c => ({ value: c.id, text: c.name })))
            .selected(memo.category || '')
            .onChange((value) => this.onCategoryChange(memo.id, value))
            .margin({ left: 10 })

.margin({ top: 5 })

.padding(15)

})

.height(‘60%’)

private formatDate(timestamp: number): string {

return new Date(timestamp).toLocaleString();

}

五、项目部署与测试
权限配置

在module.json5中添加:

“requestPermissions”: [
“name”: “ohos.permission.MICROPHONE”

},
“name”: “ohos.permission.DISTRIBUTED_DATASYNC”

},
“name”: “ohos.permission.ACCESS_AI”

]

测试方案

// 语音识别测试
describe(‘VoiceRecognition’, () => {
it(‘should convert speech to text’, async () => {
const service = new VoiceService();
await service.init();

let result = '';
await service.startRecording((text) => {
  result = text;
});

// 模拟音频输入
simulateVoiceInput('测试语音识别');
await service.stopRecording();

expect(result).toContain('测试');

});
});

// 数据同步测试
describe(‘MemoSync’, () => {
it(‘should sync memos between devices’, async () => {
const device1 = new MockDevice(‘device1’);
const device2 = new MockDevice(‘device2’);

await device1.addMemo('测试备忘录');
await device2.waitForSync();

expect(device2.getMemos()).toContainEqual(
  expect.objectContaining({ text: '测试备忘录' })
);

});
});

六、总结与扩展

本方案实现了:
基于鸿蒙AI的实时语音转文字

备忘录内容多设备同步

智能分类与语音指令

分布式冲突解决机制

扩展方向:
添加语音情感分析

开发备忘录智能摘要

集成云端备份恢复

支持多语言语音识别

鸿蒙的AI能力与分布式技术结合,为语音类应用开发提供了强大支持。开发者可基于此项目框架探索更多语音交互的创新应用场景。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐