HarmonyOS 6 悬浮导航 + 沉浸光感:打造鸿蒙智能体驱动的沉浸式会议效率助手

每日一句正能量
世上没有完全快乐的人,只有比较想得开的人。
快乐不是一种恒定的状态,而是一种瞬间的体验。“想得开”意味着能在痛苦中看见意义,在不完美中接受局限。比较的不是谁更快乐,是谁更少被执念困住。
一、前言:当AI会议助理常驻屏幕边缘
在远程办公与混合办公成为常态的今天,职场人士每天平均要参加3-5场会议。然而,传统会议模式存在诸多痛点:会议中需要手动记录要点,容易遗漏关键信息;讨论跑题时无人提醒,导致会议超时;会后整理纪要耗时费力,行动项容易遗漏;跨时区会议时间协调困难。
HarmonyOS 6(API 23)带来的悬浮导航(Floating Navigation)和沉浸光感(Immersive Lighting)能力,让我们有机会打造一个常驻屏幕边缘的AI会议助理——它像一位专业的会议秘书,在你开会时静静悬浮在屏幕角落,实时转录语音、提取关键决策、追踪行动项;它通过光效感知会议节奏,在讨论超时前以琥珀色光效温和提醒,在达成关键共识时以绿色光效确认,在会议即将结束时以蓝色光效提示收尾。
核心创新点:
- 🎙️ 实时语音转录悬浮窗:胶囊形态常驻显示会议时长与关键决策数,支持跨应用会议追踪
- 💡 会议节奏光感:通过设备边框光效颜色变化,反映会议效率与时间管理状态
- 🤖 多模态会议智能体:支持语音指令"记录这个决定"、自动提取行动项、生成会议纪要
- ⏱️ 智能时间管理:自动识别跑题、计算发言时间占比、提醒会议进度
二、应用场景设计
2.1 场景一:实时会议转录与决策追踪
用户正在参加产品评审会,悬浮胶囊常驻屏幕边缘显示"已进行25分钟 | 3项决策"。当产品经理说"我们决定下周发布v2.0版本"时,用户语音指令"记录这个决定",智能体自动提取决策内容并标记决策人,边框泛起绿色确认光效。
2.2 场景二:会议节奏管理
会议已进行50分钟,原定45分钟结束。AI检测到当前话题与议程偏离度超过60%,设备底部边框泛起琥珀色呼吸光效,悬浮窗弹出提示"当前讨论已偏离议程,建议回归主题或延长会议"。主持人看到后及时调整方向。
2.3 场景三:会后智能纪要
会议结束,AI智能体在3秒内生成结构化会议纪要:包含参会人、关键决策(带决策人)、行动项(带负责人与截止日期)、待讨论议题。用户一键分享至企业微信/钉钉,边框泛起彩虹渐变光效表示"任务完成"。
三、技术架构
┌─────────────────────────────────────────────────────────────┐
│ HarmonyOS Meeting Efficiency Assistant Agent │
├─────────────┬─────────────┬─────────────┬───────────────────┤
│ 悬浮窗UI │ 沉浸光感 │ 智能体引擎 │ 音频处理模块 │
│ FloatUI │ Lighting │ AI Engine │ AudioProcessor │
├─────────────┴─────────────┴─────────────┴───────────────────┤
│ 会议感知层(Meeting Context) │
│ 语音识别 │ 语义分析 │ 议程追踪 │ 时间管理 │ 决策提取 │
├─────────────────────────────────────────────────────────────┤
│ HarmonyOS 6 (API 23) 系统服务层 │
│ 悬浮导航 │ 光感服务 │ 智能体框架 │ 音频服务 │ 语音识别 │ 日历 │
└─────────────────────────────────────────────────────────────┘
四、核心代码实现
4.1 会议上下文感知引擎(MeetingContextEngine)
这是整个系统的"会议之耳",通过音频捕获与语音识别,实时分析会议内容与状态。
// engine/MeetingContextEngine.ets
import { audio } from '@kit.AudioKit';
import { speechRecognizer } from '@kit.SpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';
export interface MeetingContext {
meetingId: string;
startTime: number;
duration: number; // 已进行时长(秒)
scheduledDuration: number; // 预定时长(秒)
participants: Participant[]; // 参会人列表
agenda: AgendaItem[]; // 议程项
currentTopic: string; // 当前讨论主题
decisions: Decision[]; // 已记录决策
actionItems: ActionItem[]; // 行动项
speakingStats: SpeakingStats; // 发言统计
deviationScore: number; // 议程偏离度 0-100
efficiency: number; // 会议效率评分 0-100
transcript: TranscriptEntry[]; // 实时转录文本
}
export interface Participant {
id: string;
name: string;
role: string;
speakingTime: number; // 发言时长(秒)
joinTime: number;
}
export interface AgendaItem {
id: string;
title: string;
duration: number; // 预计时长
status: 'pending' | 'active' | 'completed' | 'skipped';
startTime?: number;
}
export interface Decision {
id: string;
content: string;
decisionMaker: string;
timestamp: number;
relatedAgenda?: string;
}
export interface ActionItem {
id: string;
content: string;
assignee: string;
dueDate?: number;
priority: 'high' | 'medium' | 'low';
status: 'pending' | 'in_progress' | 'completed';
}
export interface SpeakingStats {
totalSpeakingTime: number;
participantShares: Map<string, number>; // 各人发言占比
silenceDuration: number; // 沉默时长
interruptions: number; // 打断次数
}
export interface TranscriptEntry {
timestamp: number;
speaker: string;
text: string;
type: 'speech' | 'decision' | 'action' | 'question';
}
export class MeetingContextEngine {
private audioCapturer: audio.AudioCapturer | null = null;
private recognizer: speechRecognizer.SpeechRecognizer | null = null;
private contextCallbacks: Array<(context: MeetingContext) => void> = [];
private currentContext: MeetingContext | null = null;
private updateInterval: number = 0;
private transcriptBuffer: TranscriptEntry[] = [];
private lastSpeechTime: number = Date.now();
/**
* 初始化会议上下文感知
* 亮点:实时音频捕获 + 流式语音识别 + 语义分析
*/
async init(config: MeetingConfig): Promise<void> {
try {
// 申请音频权限
const hasPermission = await this.requestAudioPermission();
if (!hasPermission) {
console.warn('[MeetingContext] 音频权限未授予');
return;
}
// 初始化音频捕获
const capturerInfo: audio.AudioCapturerInfo = {
source: audio.SourceType.MIC,
capturerFlags: 0
};
const audioStreamInfo: audio.AudioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_16000,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
};
this.audioCapturer = await audio.createAudioCapturer(capturerInfo, audioStreamInfo);
// 初始化语音识别器
this.recognizer = await speechRecognizer.createEngine({
language: 'zh-CN',
online: true,
extraParams: {
punctuation: true,
enableWordTimeOffset: true
}
});
// 注册识别结果回调
this.recognizer.setCallback({
onResult: (result) => this.handleSpeechResult(result),
onError: (error) => console.error(`[Speech] 识别错误: ${error}`)
});
// 初始化会议上下文
this.currentContext = this.createInitialContext(config);
// 启动音频捕获
await this.audioCapturer.start();
// 启动定时刷新(每秒)
this.updateInterval = setInterval(() => this.refreshContext(), 1000);
console.info('[MeetingContext] 会议上下文感知引擎初始化完成');
} catch (err) {
console.error(`[MeetingContext] 初始化失败: ${JSON.stringify(err)}`);
}
}
/**
* 创建初始会议上下文
*/
private createInitialContext(config: MeetingConfig): MeetingContext {
return {
meetingId: config.meetingId || `meeting_${Date.now()}`,
startTime: Date.now(),
duration: 0,
scheduledDuration: config.scheduledDuration || 3600,
participants: config.participants || [],
agenda: config.agenda || [],
currentTopic: config.agenda[0]?.title || '开场',
decisions: [],
actionItems: [],
speakingStats: {
totalSpeakingTime: 0,
participantShares: new Map(),
silenceDuration: 0,
interruptions: 0
},
deviationScore: 0,
efficiency: 100,
transcript: []
};
}
/**
* 处理语音识别结果
*/
private handleSpeechResult(result: speechRecognizer.SpeechRecognitionResult): void {
if (!result.result || result.result.length === 0) return;
const text = result.result;
const speaker = this.identifySpeaker(result);
// 创建转录条目
const entry: TranscriptEntry = {
timestamp: Date.now(),
speaker,
text,
type: this.classifySpeechType(text)
};
this.transcriptBuffer.push(entry);
this.lastSpeechTime = Date.now();
// 自动提取决策
if (entry.type === 'decision') {
this.extractDecision(text, speaker);
}
// 自动提取行动项
if (entry.type === 'action') {
this.extractActionItem(text);
}
// 更新当前话题
this.updateCurrentTopic(text);
}
/**
* 识别说话人
* 简化实现,实际应使用声纹识别
*/
private identifySpeaker(result: speechRecognizer.SpeechRecognitionResult): string {
// 基于音高/音色特征匹配
// 简化:返回"参会人A"或从上下文推断
return this.currentContext?.participants[0]?.name || '未知';
}
/**
* 分类语音类型
*/
private classifySpeechType(text: string): TranscriptEntry['type'] {
const decisionPatterns = [
/决定|决议|确定|定为|就.*达成一致/,
/同意|批准|通过|采纳/,
/选择|选用|采用|使用/
];
const actionPatterns = [
/负责|跟进|落实|执行|完成/,
/下周|明天|截止日期|之前/,
/任务|工作|事项|行动/
];
const questionPatterns = [
/问题|疑问|请问|如何|为什么/,
/是否|能不能|可不可以/
];
if (decisionPatterns.some(p => p.test(text))) return 'decision';
if (actionPatterns.some(p => p.test(text))) return 'action';
if (questionPatterns.some(p => p.test(text))) return 'question';
return 'speech';
}
/**
* 提取决策
*/
private extractDecision(text: string, speaker: string): void {
const decisionPatterns = [
/(?:我们|大家|会议)?决定(.*)/,
/(?:确定|定为)(.*)/,
/(?:一致)?同意(.*)/
];
for (const pattern of decisionPatterns) {
const match = text.match(pattern);
if (match && match[1]) {
const decision: Decision = {
id: `decision_${Date.now()}`,
content: match[1].trim(),
decisionMaker: speaker,
timestamp: Date.now(),
relatedAgenda: this.currentContext?.currentTopic
};
this.currentContext?.decisions.push(decision);
break;
}
}
}
/**
* 提取行动项
*/
private extractActionItem(text: string): void {
const actionPatterns = [
/(.*?)负责(.*)/,
/(.*?)跟进(.*)/,
/(.*?)在(.*?)之前完成(.*)/
];
for (const pattern of actionPatterns) {
const match = text.match(pattern);
if (match) {
const assignee = match[1]?.trim() || '待定';
const content = match[2]?.trim() || text;
const actionItem: ActionItem = {
id: `action_${Date.now()}`,
content,
assignee,
priority: 'medium',
status: 'pending'
};
// 尝试提取截止日期
const dateMatch = text.match(/(明天|下周[一二三四五六日]|\d{1,2}月\d{1,2}日)/);
if (dateMatch) {
actionItem.dueDate = this.parseDate(dateMatch[1]);
}
this.currentContext?.actionItems.push(actionItem);
break;
}
}
}
/**
* 更新当前话题
*/
private updateCurrentTopic(text: string): void {
// 基于关键词匹配议程
const agenda = this.currentContext?.agenda || [];
for (const item of agenda) {
if (text.includes(item.title) || this.isRelated(text, item.title)) {
this.currentContext!.currentTopic = item.title;
if (item.status === 'pending') {
item.status = 'active';
item.startTime = Date.now();
}
break;
}
}
}
/**
* 判断文本与话题是否相关
*/
private isRelated(text: string, topic: string): boolean {
// 简化:基于关键词重叠度
const textWords = text.split(/\s+/);
const topicWords = topic.split(/\s+/);
const overlap = textWords.filter(w => topicWords.includes(w)).length;
return overlap / topicWords.length > 0.3;
}
/**
* 刷新会议上下文
*/
private refreshContext(): void {
if (!this.currentContext) return;
const now = Date.now();
const duration = Math.round((now - this.currentContext.startTime) / 1000);
// 计算议程偏离度
const deviation = this.calculateDeviation();
// 计算会议效率
const efficiency = this.calculateEfficiency(duration);
// 更新发言统计
const silenceDuration = Math.round((now - this.lastSpeechTime) / 1000);
this.currentContext.speakingStats.silenceDuration = silenceDuration;
// 更新转录
this.currentContext.transcript = [...this.currentContext.transcript, ...this.transcriptBuffer];
this.transcriptBuffer = [];
const context: MeetingContext = {
...this.currentContext,
duration,
deviationScore: deviation,
efficiency
};
this.currentContext = context;
this.contextCallbacks.forEach(cb => cb(context));
}
/**
* 计算议程偏离度
*/
private calculateDeviation(): number {
const agenda = this.currentContext?.agenda || [];
const activeItem = agenda.find(a => a.status === 'active');
if (!activeItem) return 0;
// 基于当前话题与活跃议程的匹配度
const currentTopic = this.currentContext?.currentTopic || '';
const similarity = this.calculateSimilarity(currentTopic, activeItem.title);
return Math.round((1 - similarity) * 100);
}
/**
* 计算文本相似度
*/
private calculateSimilarity(text1: string, text2: string): number {
const words1 = new Set(text1.split(''));
const words2 = new Set(text2.split(''));
const intersection = new Set([...words1].filter(w => words2.has(w)));
return intersection.size / Math.max(words1.size, words2.size);
}
/**
* 计算会议效率
*/
private calculateEfficiency(duration: number): number {
const scheduled = this.currentContext?.scheduledDuration || 3600;
const decisions = this.currentContext?.decisions.length || 0;
const actions = this.currentContext?.actionItems.length || 0;
// 效率评分维度
let score = 100;
// 时间控制:超时扣分
if (duration > scheduled) {
score -= Math.min((duration - scheduled) / 60 * 5, 30);
}
// 产出质量:决策与行动项加分
score += decisions * 5;
score += actions * 3;
// 偏离度扣分
score -= this.currentContext?.deviationScore || 0;
return Math.max(0, Math.min(100, score));
}
/**
* 语音指令处理
*/
async processVoiceCommand(command: string): Promise<<string> {
const commandPatterns: Record<string, RegExp> = {
'record_decision': /记录.*决定|记录.*决策|标记.*决定/,
'record_action': /记录.*任务|记录.*行动|添加.*行动项/,
'next_agenda': /下一项|下一个议题|进入.*议程/,
'extend_time': /延长.*时间|加时|再.*分钟/,
'end_meeting': /结束.*会议|散会|到此为止/
};
for (const [action, pattern] of Object.entries(commandPatterns)) {
if (pattern.test(command)) {
return await this.executeCommand(action, command);
}
}
return '未识别的指令,请尝试"记录这个决定"或"进入下一项议程"';
}
private async executeCommand(action: string, command: string): Promise<<string> {
switch (action) {
case 'record_decision':
// 从最近语音中提取决策
const recentText = this.transcriptBuffer.slice(-3).map(t => t.text).join(' ');
this.extractDecision(recentText, '主持人');
return '已记录决策';
case 'next_agenda':
// 切换至下一议程
const agenda = this.currentContext?.agenda || [];
const currentIndex = agenda.findIndex(a => a.status === 'active');
if (currentIndex >= 0) {
agenda[currentIndex].status = 'completed';
if (currentIndex + 1 < agenda.length) {
agenda[currentIndex + 1].status = 'active';
this.currentContext!.currentTopic = agenda[currentIndex + 1].title;
}
}
return `已进入议程:${this.currentContext?.currentTopic}`;
case 'end_meeting':
// 结束会议
return '正在生成会议纪要...';
default:
return '指令执行中';
}
}
private parseDate(dateStr: string): number {
// 简化日期解析
const now = new Date();
if (dateStr === '明天') {
return now.getTime() + 24 * 3600 * 1000;
}
return now.getTime() + 7 * 24 * 3600 * 1000; // 默认一周后
}
onContextChange(callback: (context: MeetingContext) => void): void {
this.contextCallbacks.push(callback);
}
getCurrentContext(): MeetingContext | null {
return this.currentContext;
}
destroy(): void {
clearInterval(this.updateInterval);
this.audioCapturer?.stop();
this.audioCapturer?.release();
this.recognizer?.destroy();
}
}
interface MeetingConfig {
meetingId?: string;
scheduledDuration?: number;
participants?: Participant[];
agenda?: AgendaItem[];
}
4.2 沉浸光感会议节奏反馈(MeetingLightingController)
光效是会议节奏的"时间化延伸",让参会者无需看屏幕就能感知会议状态。
// lighting/MeetingLightingController.ets
import { lighting } from '@kit.ArkUI';
export class MeetingLightingController {
private currentPhase: string = 'normal';
private isOvertime: boolean = false;
/**
* 初始化会议光感
* 设计哲学:光效应成为会议的"时间节拍器"
*/
async init(): Promise<void> {
if (!lighting.isImmersiveLightSupported()) {
console.warn('[MeetingLight] 设备不支持沉浸光感');
return;
}
// 初始状态:柔和白色,表示会议开始
await this.setLightEffect({
type: 'solid',
position: 'bottom_edge',
color: '#E0E0E0',
brightness: 20,
duration: 0
});
console.info('[MeetingLight] 会议光感初始化完成');
}
/**
* 根据会议状态更新光效
*/
async updateByMeeting(context: {
duration: number;
scheduledDuration: number;
deviationScore: number;
efficiency: number;
silenceDuration: number;
}): Promise<void> {
const progress = context.duration / context.scheduledDuration;
const remaining = context.scheduledDuration - context.duration;
// 会议超时
if (remaining < 0) {
if (!this.isOvertime) {
this.isOvertime = true;
await this.setOvertimeAlert();
}
return;
}
// 议程偏离
if (context.deviationScore > 60) {
await this.setDeviationAlert();
return;
}
// 长时间沉默
if (context.silenceDuration > 30) {
await this.setSilenceReminder();
return;
}
// 正常进度
await this.setProgressLighting(progress, context.efficiency);
}
/**
* 进度光效
* 随着时间推移颜色从绿->黄->橙渐变
*/
private async setProgressLighting(progress: number, efficiency: number): Promise<void> {
let color: string;
let brightness: number;
if (progress < 0.5) {
color = '#00E676'; // 翠绿:前半段
brightness = 25;
} else if (progress < 0.75) {
color = '#FFD600'; // 琥珀:中段
brightness = 30;
} else if (progress < 0.9) {
color = '#FF9100'; // 橙黄:接近尾声
brightness = 35;
} else {
color = '#FF5722'; // 橙红:即将结束
brightness = 40;
}
// 效率高时亮度增加
if (efficiency > 80) {
brightness += 10;
}
await lighting.setImmersiveLight({
type: 'solid',
position: 'bottom_edge',
color,
brightness,
duration: 0
});
}
/**
* 决策确认光效
* 记录决策时的正向反馈
*/
async confirmDecision(): Promise<void> {
await lighting.setImmersiveLight({
type: 'flashing',
position: 'all_edges',
color: '#00E676',
brightness: 50,
duration: 1000,
flashCount: 2
});
}
/**
* 行动项记录光效
*/
async confirmActionItem(): Promise<void> {
await lighting.setImmersiveLight({
type: 'flashing',
position: 'bottom_edge',
color: '#448AFF',
brightness: 40,
duration: 800,
flashCount: 1
});
}
/**
* 议程偏离告警
*/
private async setDeviationAlert(): Promise<void> {
await lighting.setImmersiveLight({
type: 'wave',
position: 'all_edges',
color: '#FFD600',
brightness: 45,
duration: 0,
direction: 'alternate',
speed: 'medium'
});
}
/**
* 超时告警
*/
private async setOvertimeAlert(): Promise<void> {
await lighting.setImmersiveLight({
type: 'flashing',
position: 'all_edges',
color: '#FF1744',
brightness: 50,
duration: 0,
flashCount: -1,
frequency: 1000
});
}
/**
* 沉默提醒
*/
private async setSilenceReminder(): Promise<void> {
await lighting.setImmersiveLight({
type: 'breathing',
position: 'bottom_edge',
color: '#9E9E9E',
brightness: 30,
duration: 0,
frequency: 2000
});
}
/**
* 会议结束庆祝
*/
async celebrateEnd(): Promise<void> {
const colors = ['#00E676', '#00B0FF', '#2979FF', '#7C4DFF', '#F50057', '#FF9100'];
for (const color of colors) {
await lighting.setImmersiveLight({
type: 'solid',
position: 'all_edges',
color,
brightness: 50,
duration: 150
});
await new Promise(resolve => setTimeout(resolve, 150));
}
await this.reset();
}
/**
* 纪要生成完成
*/
async summaryComplete(): Promise<void> {
await lighting.setImmersiveLight({
type: 'flashing',
position: 'all_edges',
color: '#00E676',
brightness: 50,
duration: 2000,
flashCount: 3
});
}
async reset(): Promise<void> {
await lighting.resetImmersiveLight();
}
}
4.3 会议智能体引擎(MeetingAgentEngine)
这是系统的"会议大脑",负责分析会议内容、生成纪要、提供效率建议。
// agent/MeetingAgentEngine.ets
import { ai } from '@kit.AiKit';
import { MeetingContext, Decision, ActionItem, TranscriptEntry } from '../engine/MeetingContextEngine';
export interface MeetingSummary {
title: string;
date: string;
duration: string;
participants: string[];
keyDecisions: Decision[];
actionItems: ActionItem[];
discussedTopics: string[];
pendingQuestions: string[];
efficiency: number;
nextMeeting?: string;
}
export interface EfficiencyReport {
score: number;
strengths: string[];
improvements: string[];
speakingBalance: Map<string, number>;
timeAllocation: Map<string, number>;
}
export class MeetingAgentEngine {
private agent: ai.AgentSession | null = null;
/**
* 初始化会议智能体
*/
async init(): Promise<void> {
const model = await ai.createModel({
modelId: 'harmonyos-meeting-v1',
type: ai.ModelType.LOCAL,
capabilities: ['meeting_analysis', 'summarization', 'action_extraction']
});
this.agent = await ai.createAgentSession({
model: model,
systemPrompt: `你是一位专业的会议效率顾问,精通会议管理与信息提取。
请基于会议转录文本,提供:
1. 结构化会议纪要
2. 关键决策与行动项提取
3. 会议效率分析
4. 改进建议
输出要求:
- 使用Markdown格式
- 决策必须包含决策人
- 行动项必须包含负责人与截止日期
- 效率分析客观具体`
});
console.info('[MeetingAgent] 会议智能体初始化完成');
}
/**
* 生成会议纪要
*/
async generateSummary(context: MeetingContext): Promise<<MeetingSummary> {
if (!this.agent) return this.fallbackSummary(context);
const transcript = context.transcript.map(t =>
`[${new Date(t.timestamp).toLocaleTimeString()}] ${t.speaker}: ${t.text}`
).join('\n');
const prompt = `请基于以下会议转录生成结构化纪要:
会议时长:${this.formatDuration(context.duration)}
参会人:${context.participants.map(p => p.name).join(', ')}
议程:${context.agenda.map(a => a.title).join(', ')}
转录文本:
${transcript}
请生成包含以下内容的纪要:
1. 会议标题与基本信息
2. 关键决策(已识别:${context.decisions.length}项)
3. 行动项(已识别:${context.actionItems.length}项)
4. 讨论的主要话题
5. 遗留问题
6. 下次会议建议`;
const result = await this.agent.invoke({
input: { question: prompt },
options: { maxTokens: 2048, temperature: 0.3 }
});
return this.parseSummary(result, context);
}
/**
* 生成效率分析报告
*/
async generateEfficiencyReport(context: MeetingContext): Promise<<EfficiencyReport> {
const speakingBalance = new Map<string, number>();
const timeAllocation = new Map<string, number>();
// 计算发言平衡
context.participants.forEach(p => {
const share = context.speakingStats.participantShares.get(p.id) || 0;
speakingBalance.set(p.name, share);
});
// 计算时间分配
context.agenda.forEach(item => {
if (item.startTime) {
const duration = item.status === 'completed'
? (Date.now() - item.startTime) / 1000
: 0;
timeAllocation.set(item.title, duration);
}
});
const prompt = `请分析以下会议的效率:
预定时长:${this.formatDuration(context.scheduledDuration)}
实际时长:${this.formatDuration(context.duration)}
决策数量:${context.decisions.length}
行动项数量:${context.actionItems.length}
议程偏离度:${context.deviationScore}%
沉默时长:${context.speakingStats.silenceDuration}秒
请给出:
1. 效率评分(0-100)
2. 会议优点
3. 改进建议`;
const result = await this.agent!.invoke({
input: { question: prompt },
options: { maxTokens: 512, temperature: 0.3 }
});
return {
score: context.efficiency,
strengths: result.data?.strengths || ['讨论充分', '决策明确'],
improvements: result.data?.improvements || ['控制时间', '减少跑题'],
speakingBalance,
timeAllocation
};
}
/**
* 实时会议建议
*/
async generateRealtimeSuggestion(context: MeetingContext): Promise<<string> {
if (!this.agent) return '';
const prompt = `当前会议状态:
已进行:${this.formatDuration(context.duration)}
当前话题:${context.currentTopic}
偏离度:${context.deviationScore}%
沉默时长:${context.speakingStats.silenceDuration}秒
请给出一条简短的会议引导建议(不超过20字)。`;
const result = await this.agent.invoke({
input: { question: prompt },
options: { maxTokens: 64, temperature: 0.5 }
});
return result.data?.suggestion || '';
}
/**
* 语音指令理解
*/
async understandCommand(command: string, context: MeetingContext): Promise<<{
action: string;
parameters: any;
}> {
const prompt = `理解会议语音指令:
指令:"${command}"
当前议程:${context.currentTopic}
请解析为结构化指令。`;
const result = await this.agent!.invoke({
input: { question: prompt },
options: { maxTokens: 128, temperature: 0.1 }
});
return {
action: result.data?.action || 'unknown',
parameters: result.data?.parameters || {}
};
}
private parseSummary(result: ai.ModelOutput, context: MeetingContext): MeetingSummary {
const data = result.data || {};
return {
title: data.title || '会议纪要',
date: new Date().toLocaleDateString(),
duration: this.formatDuration(context.duration),
participants: context.participants.map(p => p.name),
keyDecisions: context.decisions,
actionItems: context.actionItems,
discussedTopics: data.discussedTopics || [],
pendingQuestions: data.pendingQuestions || [],
efficiency: context.efficiency,
nextMeeting: data.nextMeeting
};
}
private fallbackSummary(context: MeetingContext): MeetingSummary {
return {
title: '会议纪要',
date: new Date().toLocaleDateString(),
duration: this.formatDuration(context.duration),
participants: context.participants.map(p => p.name),
keyDecisions: context.decisions,
actionItems: context.actionItems,
discussedTopics: [context.currentTopic],
pendingQuestions: [],
efficiency: context.efficiency
};
}
private formatDuration(seconds: number): string {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
if (hours > 0) return `${hours}小时${minutes}分钟`;
return `${minutes}分钟`;
}
destroy(): void {
this.agent?.destroy();
}
}
4.4 悬浮窗会议面板(MeetingFloatWindow)
// float/MeetingFloatWindow.ets
import { window } from '@kit.ArkUI';
import { emitter } from '@kit.BasicServicesKit';
import { MeetingContext } from '../engine/MeetingContextEngine';
import { MeetingSummary } from '../agent/MeetingAgentEngine';
export class MeetingFloatWindow {
private floatWin: window.Window | null = null;
private currentLevel: 'capsule' | 'panel' | 'summary' = 'capsule';
async create(): Promise<void> {
const option: window.WindowOption = {
name: 'MeetingAssistant',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext(this)
};
this.floatWin = await window.createWindow(getContext(this), option);
// 胶囊形态:显示会议时长与决策数
await this.floatWin.resize({ width: 130, height: 80 });
await this.floatWin.moveWindowTo({ x: 890, y: 100 });
await this.floatWin.setWindowTouchable(true);
await this.floatWin.setUIContent('pages/MeetingCapsulePage');
await this.floatWin.showWindow();
}
async expandToPanel(context: MeetingContext): Promise<void> {
if (!this.floatWin) return;
this.currentLevel = 'panel';
await this.floatWin.resize({ width: 460, height: 720 });
await this.floatWin.moveWindowTo({ x: 540, y: 80 });
await this.floatWin.setUIContent('pages/MeetingPanelPage');
emitter.emit('showMeetingPanel', { data: context });
}
async showSummary(summary: MeetingSummary): Promise<void> {
if (!this.floatWin) return;
this.currentLevel = 'summary';
await this.floatWin.resize({ width: 500, height: 800 });
await this.floatWin.moveWindowTo({ x: 520, y: 40 });
await this.floatWin.setUIContent('pages/MeetingSummaryPage');
emitter.emit('showMeetingSummary', { data: summary });
}
async collapseToCapsule(): Promise<void> {
if (!this.floatWin) return;
this.currentLevel = 'capsule';
await this.floatWin.resize({ width: 130, height: 80 });
await this.floatWin.moveWindowTo({ x: 890, y: 100 });
await this.floatWin.setUIContent('pages/MeetingCapsulePage');
}
destroy(): void {
this.floatWin?.destroyWindow();
}
}
4.5 会议胶囊页面(MeetingCapsulePage)
// pages/MeetingCapsulePage.ets
import { emitter } from '@kit.BasicServicesKit';
@Entry
@Component
struct MeetingCapsulePage {
@State duration: string = '00:00';
@State decisionCount: number = 0;
@State actionCount: number = 0;
@State efficiency: number = 100;
@State isRecording: boolean = false;
aboutToAppear() {
emitter.on('updateMeetingContext', (event) => {
const ctx = event.data;
this.duration = this.formatDuration(ctx?.duration || 0);
this.decisionCount = ctx?.decisions?.length || 0;
this.actionCount = ctx?.actionItems?.length || 0;
this.efficiency = ctx?.efficiency || 100;
});
}
build() {
Stack() {
// 效率指示外圈
Circle()
.width(140)
.height(140)
.fill('none')
.stroke(
this.efficiency > 80 ? '#00E676' :
this.efficiency > 60 ? '#FFD600' : '#FF1744'
)
.strokeWidth(3)
.strokeDashArray([
2 * Math.PI * 70 * (this.efficiency / 100),
2 * Math.PI * 70
])
.animation({ duration: 1000 })
Column() {
// 录音状态
if (this.isRecording) {
Circle()
.width(8)
.height(8)
.fill('#FF1744')
.animation({
duration: 1000,
iterations: -1,
curve: Curve.EaseInOut,
playMode: PlayMode.Alternate
})
}
// 时长
Text(this.duration)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
// 决策/行动项
Text(`${this.decisionCount}决策 · ${this.actionCount}行动`)
.fontSize(10)
.fontColor('#666')
// 效率
Text(`${this.efficiency}%`)
.fontSize(10)
.fontColor(
this.efficiency > 80 ? '#00C853' :
this.efficiency > 60 ? '#FF9100' : '#FF1744'
)
}
.width(130)
.height(80)
.justifyContent(FlexAlign.Center)
.backgroundColor('rgba(255, 255, 255, 0.95)')
.borderRadius(16)
.shadow({ radius: 12, color: 'rgba(0,0,0,0.12)' })
.gesture(
GestureGroup(GestureMode.Sequence,
TapGesture({ count: 1 })
.onAction(() => emitter.emit('expandToPanel')),
LongPressGesture({ duration: 800 })
.onAction(() => emitter.emit('toggleRecording'))
)
)
}
.width('100%')
.height('100%')
.align(Alignment.Center)
}
private formatDuration(seconds: number): string {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
}
4.6 会议面板页面(MeetingPanelPage)
// pages/MeetingPanelPage.ets
import { emitter } from '@kit.BasicServicesKit';
import { MeetingContext, AgendaItem, Decision, ActionItem } from '../engine/MeetingContextEngine';
@Entry
@Component
struct MeetingPanelPage {
@State context: MeetingContext | null = null;
@State selectedTab: string = 'live';
private tabs: string[] = ['live', 'agenda', 'decisions', 'actions'];
aboutToAppear() {
emitter.on('showMeetingPanel', (event) => {
this.context = event.data;
});
}
build() {
Column() {
// 顶部标题栏
Row() {
Text('🎙️ 会议助手')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Button('收起')
.fontSize(12)
.backgroundColor('#f0f0f0')
.fontColor('#333')
.onClick(() => emitter.emit('collapseToCapsule'))
}
.width('100%')
.padding(16)
// Tab切换
Row() {
ForEach(this.tabs, (tab: string) => {
Button(this.getTabName(tab))
.fontSize(12)
.backgroundColor(this.selectedTab === tab ? '#2979FF' : '#f0f0f0')
.fontColor(this.selectedTab === tab ? '#FFF' : '#666')
.margin({ right: 8 })
.onClick(() => this.selectedTab = tab)
})
}
.width('100%')
.margin({ bottom: 12 })
// 内容区
if (this.selectedTab === 'live') {
this.LiveTab()
} else if (this.selectedTab === 'agenda') {
this.AgendaTab()
} else if (this.selectedTab === 'decisions') {
this.DecisionsTab()
} else {
this.ActionsTab()
}
// 语音指令输入
Row() {
TextInput({ placeholder: '语音指令:记录这个决定 / 下一项议程...' })
.fontSize(13)
.layoutWeight(1)
.onSubmit((value) => this.submitCommand(value))
Button('🎤')
.fontSize(14)
.backgroundColor('#2979FF')
.onClick(() => this.startVoiceCommand())
}
.width('100%')
.padding(12)
.backgroundColor('#f8f9fa')
.borderRadius(8)
.margin({ top: 8 })
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#FFF')
.borderRadius(16)
}
@Builder
LiveTab() {
Column() {
// 实时转录
Text('📝 实时转录')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.width('100%')
List() {
ForEach(this.context?.transcript.slice(-10) || [], (entry: any) => {
ListItem() {
Column() {
Text(`${entry.speaker} · ${new Date(entry.timestamp).toLocaleTimeString()}`)
.fontSize(10)
.fontColor('#999')
.width('100%')
Text(entry.text)
.fontSize(13)
.fontColor('#333')
.width('100%')
.margin({ top: 2 })
if (entry.type === 'decision') {
Text('✓ 决策')
.fontSize(10)
.fontColor('#00C853')
.backgroundColor('#E8F5E9')
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.borderRadius(4)
.margin({ top: 4 })
} else if (entry.type === 'action') {
Text('⚡ 行动项')
.fontSize(10)
.fontColor('#2979FF')
.backgroundColor('#E3F2FD')
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.borderRadius(4)
.margin({ top: 4 })
}
}
.padding(8)
.backgroundColor('#f8f9fa')
.borderRadius(6)
.margin({ bottom: 6 })
}
})
}
.width('100%')
.layoutWeight(1)
.margin({ top: 8 })
}
}
@Builder
AgendaTab() {
List() {
ForEach(this.context?.agenda || [], (item: AgendaItem) => {
ListItem() {
Row() {
// 状态指示
Circle()
.width(12)
.height(12)
.fill(
item.status === 'completed' ? '#00E676' :
item.status === 'active' ? '#2979FF' :
item.status === 'skipped' ? '#9E9E9E' : '#E0E0E0'
)
Column() {
Text(item.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.width('100%')
.decoration({
type: item.status === 'completed' ? TextDecorationType.LineThrough : TextDecorationType.None
})
Text(`${this.formatDuration(item.duration)}`)
.fontSize(11)
.fontColor('#999')
.width('100%')
}
.layoutWeight(1)
.margin({ left: 12 })
Text(
item.status === 'completed' ? '✓' :
item.status === 'active' ? '进行中' :
item.status === 'skipped' ? '跳过' : '待开始'
)
.fontSize(12)
.fontColor(
item.status === 'completed' ? '#00C853' :
item.status === 'active' ? '#2979FF' : '#999'
)
}
.width('100%')
.padding(12)
.backgroundColor('#fff')
.borderRadius(8)
.margin({ bottom: 8 })
}
})
}
.width('100%')
.layoutWeight(1)
}
@Builder
DecisionsTab() {
List() {
ForEach(this.context?.decisions || [], (decision: Decision) => {
ListItem() {
Column() {
Row() {
Text('✓')
.fontSize(16)
.fontColor('#00C853')
Text(decision.content)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.layoutWeight(1)
.margin({ left: 8 })
}
.width('100%')
Text(`决策人:${decision.decisionMaker} · ${new Date(decision.timestamp).toLocaleTimeString()}`)
.fontSize(11)
.fontColor('#999')
.width('100%')
.margin({ top: 4 })
}
.padding(12)
.backgroundColor('#E8F5E9')
.borderRadius(8)
.margin({ bottom: 8 })
}
})
}
.width('100%')
.layoutWeight(1)
}
@Builder
ActionsTab() {
List() {
ForEach(this.context?.actionItems || [], (action: ActionItem) => {
ListItem() {
Row() {
Column() {
Text(action.content)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.width('100%')
Text(`负责人:${action.assignee}${action.dueDate ? ' · 截止:' + new Date(action.dueDate).toLocaleDateString() : ''}`)
.fontSize(11)
.fontColor('#999')
.width('100%')
}
.layoutWeight(1)
Text(
action.priority === 'high' ? '高' :
action.priority === 'medium' ? '中' : '低'
)
.fontSize(11)
.fontColor('#FFF')
.backgroundColor(
action.priority === 'high' ? '#FF1744' :
action.priority === 'medium' ? '#FF9100' : '#00C853'
)
.padding({ left: 8, right: 8, top: 2, bottom: 2 })
.borderRadius(4)
}
.width('100%')
.padding(12)
.backgroundColor('#E3F2FD')
.borderRadius(8)
.margin({ bottom: 8 })
}
})
}
.width('100%')
.layoutWeight(1)
}
private getTabName(tab: string): string {
const names: Record<string, string> = {
'live': '实时',
'agenda': '议程',
'decisions': '决策',
'actions': '行动'
};
return names[tab] || tab;
}
private formatDuration(seconds: number): string {
const mins = Math.floor(seconds / 60);
return `${mins}分钟`;
}
private submitCommand(command: string) {
emitter.emit('processVoiceCommand', { data: { command } });
}
private startVoiceCommand() {
emitter.emit('startVoiceCommand');
}
}
4.7 主入口与系统集成(Index.ets)
// Index.ets
import { MeetingContextEngine } from './engine/MeetingContextEngine';
import { MeetingLightingController } from './lighting/MeetingLightingController';
import { MeetingFloatWindow } from './float/MeetingFloatWindow';
import { MeetingAgentEngine } from './agent/MeetingAgentEngine';
import { emitter } from '@kit.BasicServicesKit';
@Entry
@Component
struct MeetingAssistantApp {
private meetingEngine: MeetingContextEngine = new MeetingContextEngine();
private lightController: MeetingLightingController = new MeetingLightingController();
private floatWindow: MeetingFloatWindow = new MeetingFloatWindow();
private agentEngine: MeetingAgentEngine = new MeetingAgentEngine();
aboutToAppear() {
this.initSystem();
}
aboutToDisappear() {
this.meetingEngine.destroy();
this.lightController.reset();
this.floatWindow.destroy();
this.agentEngine.destroy();
}
async initSystem() {
// 1. 初始化沉浸光感
await this.lightController.init();
// 2. 初始化悬浮窗
await this.floatWindow.create();
// 3. 初始化智能体引擎
await this.agentEngine.init();
// 4. 初始化会议引擎
await this.meetingEngine.init({
meetingId: `meeting_${Date.now()}`,
scheduledDuration: 3600,
participants: [
{ id: 'p1', name: '张三', role: '产品经理', speakingTime: 0, joinTime: Date.now() },
{ id: 'p2', name: '李四', role: '开发负责人', speakingTime: 0, joinTime: Date.now() },
{ id: 'p3', name: '王五', role: '设计师', speakingTime: 0, joinTime: Date.now() }
],
agenda: [
{ id: 'a1', title: '产品需求评审', duration: 900, status: 'active' },
{ id: 'a2', title: '技术方案讨论', duration: 1200, status: 'pending' },
{ id: 'a3', title: '排期确认', duration: 600, status: 'pending' },
{ id: 'a4', title: '风险与问题', duration: 600, status: 'pending' },
{ id: 'a5', title: '下一步行动', duration: 300, status: 'pending' }
]
});
// 当会议上下文变化时,更新光效和悬浮窗
this.meetingEngine.onContextChange(async (context) => {
// 更新光效
await this.lightController.updateByMeeting({
duration: context.duration,
scheduledDuration: context.scheduledDuration,
deviationScore: context.deviationScore,
efficiency: context.efficiency,
silenceDuration: context.speakingStats.silenceDuration
});
// 更新悬浮窗
emitter.emit('updateMeetingContext', { data: context });
});
// 5. 设置事件监听
this.setupEventListeners();
}
private setupEventListeners() {
emitter.on('expandToPanel', async () => {
const context = this.meetingEngine.getCurrentContext();
if (context) {
await this.floatWindow.expandToPanel(context);
}
});
emitter.on('collapseToCapsule', async () => {
await this.floatWindow.collapseToCapsule();
});
emitter.on('toggleRecording', () => {
// 切换录音状态
});
emitter.on('processVoiceCommand', async (event) => {
const command = event.data?.command;
const context = this.meetingEngine.getCurrentContext();
if (command && context) {
const result = await this.meetingEngine.processVoiceCommand(command);
// 显示结果
}
});
emitter.on('startVoiceCommand', () => {
// 启动语音识别
});
emitter.on('endMeeting', async () => {
const context = this.meetingEngine.getCurrentContext();
if (context) {
const summary = await this.agentEngine.generateSummary(context);
await this.floatWindow.showSummary(summary);
await this.lightController.celebrateEnd();
}
});
}
build() {
Column() {
Text('🎙️ HarmonyOS会议效率助手')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 8 })
Text('AI智能体正在记录您的会议...')
.fontSize(14)
.fontColor('#666')
Text('悬浮窗常驻显示,语音指令随时控制')
.fontSize(12)
.fontColor('#999')
.margin({ top: 4 })
.textAlign(TextAlign.Center)
// 会议统计
Column() {
Text('📊 会议概览')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 12 })
Row() {
Column() {
Text('5')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#2979FF')
Text('议程项')
.fontSize(12)
.fontColor('#999')
}
.layoutWeight(1)
Column() {
Text('3')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#00C853')
Text('参会人')
.fontSize(12)
.fontColor('#999')
}
.layoutWeight(1)
Column() {
Text('60min')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#FF9100')
Text('预计时长')
.fontSize(12)
.fontColor('#999')
}
.layoutWeight(1)
}
.width('100%')
}
.width('90%')
.padding(20)
.backgroundColor('#f8f9fa')
.borderRadius(12)
.margin({ top: 32 })
// 当前状态
Row() {
Text('系统状态:')
.fontSize(14)
.fontColor('#666')
Text('🟢 会议进行中')
.fontSize(14)
.fontColor('#00C853')
.fontWeight(FontWeight.Medium)
}
.margin({ top: 20 })
// 结束会议按钮
Button('结束会议并生成纪要')
.fontSize(16)
.backgroundColor('#FF1744')
.width('80%')
.margin({ top: 32 })
.onClick(() => emitter.emit('endMeeting'))
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
五、配置文件
// module.json5
{
"module": {
"name": "MeetingAssistant",
"type": "entry",
"description": "鸿蒙智能体会议效率助手",
"mainElement": "EntryAbility",
"deviceTypes": ["phone", "tablet", "2in1"],
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "会议效率助手主入口",
"icon": "$media:layered_image",
"label": "AI会议助手",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
"reason": "需要悬浮窗权限以常驻显示会议状态"
},
{
"name": "ohos.permission.MICROPHONE",
"reason": "需要麦克风权限以捕获会议音频"
},
{
"name": "ohos.permission.INTERNET",
"reason": "连接云端语音识别与智能体服务"
},
{
"name": "ohos.permission.ACCESS_AI_MODEL",
"reason": "使用端侧AI模型进行语义分析"
}
]
}
}
六、效果展示与使用场景
6.1 典型会议场景
场景A:产品评审会
产品经理张三正在主持评审会,悬浮胶囊显示"已进行25分钟 | 2项决策"。当他说"我们决定下周发布v2.0版本"时,参会人李四语音指令"记录这个决定",边框泛起绿色确认光效,决策自动记录到"决策"标签页。会议进行50分钟时,讨论偏离到技术细节,边框泛起琥珀色波浪光效,提示"当前讨论已偏离议程"。
场景B:跨时区站会
海外团队站会,悬浮窗实时转录中英文混合发言。当印度同事发言时,智能体自动识别口音并提高转录准确率。会议超时5分钟,边框红色快闪提醒。结束后3秒生成纪要,包含"3项决策、5个行动项",一键分享至Slack。
场景C:一对一绩效面谈
HR与员工面谈,悬浮窗静默记录(经双方同意)。智能体分析对话情绪,当检测到紧张氛围时,边框泛起蓝色舒缓光效。面谈结束生成结构化记录,包含"员工诉求、HR承诺、后续跟进",双方确认后归档。
6.2 光效语义设计
| 会议状态 | 光效表现 | 会议提示 |
|---|---|---|
| 会议初期 | 底部翠绿常亮 | 时间充裕,充分讨论 |
| 会议中期 | 底部琥珀常亮 | 注意时间分配 |
| 接近尾声 | 底部橙红常亮 | 准备收尾 |
| 记录决策 | 全边框绿色双闪 | 决策已记录 |
| 记录行动项 | 底部蓝色单闪 | 行动项已添加 |
| 议程偏离 | 全边框琥珀波浪 | 建议回归主题 |
| 会议超时 | 全边框红色快闪 | 立即结束或延长 |
| 长时间沉默 | 底部灰色呼吸 | 建议引导发言 |
| 纪要生成 | 彩虹渐变 | 任务完成 |
七、性能与隐私优化
7.1 音频处理策略
// 音频处理优化
const audioStrategy = {
// 采样率:根据网络状况动态调整
sampleRate: {
high: 16000, // 高质量:16kHz
normal: 8000, // 标准:8kHz
low: 4000 // 低质量:4kHz
},
// 语音识别模式
recognition: {
realTime: true, // 实时识别
partialResults: true, // 返回中间结果
punctuation: true // 自动标点
},
// 本地缓存
cache: {
enabled: true,
maxDuration: 3600, // 最多缓存1小时
autoCleanup: true // 自动清理
}
};
7.2 隐私保护
- 本地优先:语音识别优先本地处理,敏感内容不上云
- 同意机制:录音前明确提示,可随时暂停/删除
- 数据隔离:不同会议数据完全隔离
- 自动清理:会议结束后7天自动删除原始音频
八、总结与展望
本文展示了如何基于HarmonyOS 6(API 23)的悬浮导航和沉浸光感能力,构建一个鸿蒙智能体驱动的沉浸式会议效率助手。与传统会议工具不同,它具备三个核心创新:
- 实时感知:悬浮窗常驻屏幕边缘,会议状态随时可见,光效即时反馈节奏
- 智能提取:AI智能体自动识别决策与行动项,无需手动记录
- 效率提升:多模态交互(语音+光效+悬浮窗)协同提升会议效率
未来演进方向:
- 多语言支持:实时翻译跨语言会议,消除语言障碍
- 情绪分析:基于语音情绪识别,优化会议氛围
- 智能排期:基于参会人日历与习惯,自动推荐最佳会议时间
- 知识沉淀:会议决策自动关联项目管理系统,形成知识图谱
HarmonyOS 6的智能体框架和系统级交互创新,正在让"AI会议助理常驻身边"成为现实。对于职场人士而言,这不仅是一个记录工具,更是一位24小时在线、懂议程、懂效率、懂协作的智能会议伙伴。
转载自:https://blog.csdn.net/u014727709/article/details/161420923
欢迎 👍点赞✍评论⭐收藏,欢迎指正
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)