Flutter阿里AI通话功能插件ali_ai_call的使用

Flutter阿里AI通话功能插件ali_ai_call的使用

阿里云 AI 通话 Flutter 插件,支持实时语音对话、语音识别、声纹识别等功能。

功能特性

  • AI 语音通话
  • 声纹识别
  • 实时语音识别(ASR)
  • 语音合成(TTS)
  • 网络质量监控
  • 麦克风/扬声器控制
  • AI语音打断
  • 多角色支持
  • 多音色支持

环境要求

  • Flutter: >=3.3.0
  • iOS: >= 12.0
  • Android: minSdkVersion 19

安装

  1. 添加依赖到 pubspec.yaml:
dependencies:
  ali_ai_call: ^1.0.0
  1. iOS 配置: 在 ios/Runner/Info.plist 添加以下权限:
<key>NSMicrophoneUsageDescription</key>
<string>需要访问麦克风进行语音通话</string>
<key>NSCameraUsageDescription</key>
<string>需要访问相机进行视频通话</string>
  1. Android 配置: 在 android/app/src/main/AndroidManifest.xml 添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />

使用方法

后端服务需要正常运行,可以在本项目中找到Server配置文件修改配置文件中的配置然后运行一下

初始化

await AliAiCall.initEngine(userId: "your_user_id");

设置回调

AliAiCall.setEngineEventHandler(
  onCallBegin: () {
    print('通话开始');
  },
  onCallEnd: () {
    print('通话结束');
  },
  onError: (error) {
    print('发生错误: $error');
  },
  onUserAsrSubtitleNotify: (Map<String, dynamic> data) {
    // 用户语音识别结果
    String text = data['text'];
    bool isSentenceEnd = data['isSentenceEnd'];
    int sentenceId = data['sentenceId'];
    VoicePrintStatusCode voicePrintStatus = data['voicePrintStatus'];
    
    switch (voicePrintStatus) {
      case VoicePrintStatusCode.speakerRecognized:
        print('说话人已识别');
        break;
      case VoicePrintStatusCode.speakerNotRecognized:
        print('说话人未识别');
        break;
      case VoicePrintStatusCode.disable:
        print('声纹识别已禁用');
        break;
      case VoicePrintStatusCode.enableWithoutRegister:
        print('声纹识别已启用但未注册');
        break;
      case VoicePrintStatusCode.unknown:
        print('未知状态');
        break;
    }
    
    print('用户语音识别: $text');
  },
  onAIAgentSubtitleNotify: (Map<String, dynamic> data) {
    // AI回复文本
    String text = data['text'];
    bool isSentenceEnd = data['isSentenceEnd'];
    int userAsrSentenceId = data['userAsrSentenceId'];
    print('AI回复: $text');
  },
  onVolumeChanged: (Map<String, dynamic> data) {
    // 音量变化
    String uid = data['uid'];
    int volume = data['volume'];
    print('音量变化: $volume');
  },
);

开始通话

await AliAiCall.call(
  rtcToken: "your_rtc_token",
  aiAgentInstanceId: "your_instance_id",
  aiAgentUserId: "your_agent_user_id",
  channelId: "your_channel_id",
);

结束通话

await AliAiCall.hangup();

音频控制

// 切换麦克风
await AliAiCall.switchMicrophone(true/false);

// 切换扬声器
await AliAiCall.enableSpeaker(true/false);

// 打断 AI 说话
await AliAiCall.interruptSpeaking();

// 启用语音打断
await AliAiCall.enableVoiceInterrupt(true/false);

AI控制

// 切换 AI 音色
await AliAiCall.switchRobotVoice("voice_id");

// 设置 AI 角色
await AliAiCall.setAIRole("role_id", "role_name");

回调参数说明

onUserAsrSubtitleNotify

参数 类型 说明
text String 识别到的文本内容
isSentenceEnd bool 是否是句子结束
sentenceId int 句子ID
voicePrintStatus VoicePrintStatusCode 声纹状态,可能的值:
- disable: 禁用
- enableWithoutRegister: 启用但未注册
- speakerRecognized: 说话人已识别
- speakerNotRecognized: 说话人未识别
- unknown: 未知状态

onAIAgentSubtitleNotify

参数 类型 说明
text String AI回复的文本内容
isSentenceEnd bool 是否是句子结束
userAsrSentenceId int 对应的用户语音ID

onVolumeChanged

参数 类型 说明
uid String 用户ID
volume int 音量大小 (0-255)

错误处理

插件会通过 onError 回调返回错误信息,建议在使用时做好错误处理:

onError: (error) {
  switch(error) {
    case "NETWORK_ERROR":
      // 处理网络错误
      break;
    case "PERMISSION_DENIED":
      // 处理权限错误
      break;
    // 处理其他错误...
  }
}

最佳实践

  1. 初始化时机

    • 建议在应用启动时就完成初始化
    • 确保在调用其他方法前完成初始化
  2. 资源释放

    • 在页面销毁时调用 hangup()
    • 注意清理回调避免内存泄漏
  3. 错误处理

    • 对网络错误进行重试
    • 对权限错误给予用户提示
    • 记录错误日志便于问题排查
  4. 性能优化

    • 避免频繁切换音色和角色
    • 合理使用语音打断功能
    • 注意控制录音文件大小

常见问题

  1. Q: 初始化失败怎么办?

    • A: 检查网络连接和参数配置是否正确
  2. Q: 没有声音怎么办?

    • A: 检查音量设置和权限是否正确
  3. Q: 语音识别不准确怎么办?

    • A: 建议在安静环境使用,说话清晰度也重要
  4. Q: 遇到 “Multiple commands produce xxx-umbrella.h” 错误怎么办?

    • A: 这是 Xcode 构建冲突导致的问题,解决步骤如下:
      1. 确保 podspec 文件中正确配置了 source_filespublic_header_files
      2. 删除 ios/Classes 目录下的重复 umbrella header 文件
      3. 清理并重新安装 pods:
      cd example/ios
      pod deintegrate
      pod cache clean --all
      rm -rf Pods
      rm -rf .symlinks
      rm Podfile.lock
      pod install
      
      1. 重新构建项目:
      flutter clean
      flutter pub get
      cd example/ios
      pod install
      cd ..
      flutter build ios
      

更新日志

1.0.0

  • 初始版本发布
  • 支持基础语音通话功能
  • 支持语音识别和合成
  • 支持音量控制和监控

问题反馈

如有问题请提交 Issue

License

MIT License

开源不易觉得好用给个Star或者赞助一下

img.png

完整示例Demo

main.dart

import 'package:flutter/material.dart';
import 'screens/config_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AI Agent Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        inputDecorationTheme: const InputDecorationTheme(
          border: OutlineInputBorder(),
          contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
        ),
      ),
      home: const ConfigScreen(),
    );
  }
}

config_screen.dart

import 'package:flutter/material.dart';
import 'package:ali_ai_call/ali_ai_call.dart';

class ConfigScreen extends StatefulWidget {
  const ConfigScreen({Key? key}) : super(key: key);

  [@override](/user/override)
  _ConfigScreenState createState() => _ConfigScreenState();
}

class _ConfigScreenState extends State<ConfigScreen> {
  final TextEditingController _userIdController = TextEditingController();
  final TextEditingController _rtcTokenController = TextEditingController();
  final TextEditingController _instanceIdController = TextEditingController();
  final TextEditingController _agentUserIdController = TextEditingController();
  final TextEditingController _channelIdController = TextEditingController();

  [@override](/user/override)
  void initState() {
    super.initState();
    AliAiCall.setEngineEventHandler(
      onCallBegin: () {
        print('通话开始');
      },
      onCallEnd: () {
        print('通话结束');
      },
      onError: (error) {
        print('发生错误: $error');
      },
      onUserAsrSubtitleNotify: (data) {
        String text = data['text'];
        bool isSentenceEnd = data['isSentenceEnd'];
        int sentenceId = data['sentenceId'];
        VoicePrintStatusCode voicePrintStatus = data['voicePrintStatus'];

        switch (voicePrintStatus) {
          case VoicePrintStatusCode.speakerRecognized:
            print('说话人已识别');
            break;
          case VoicePrintStatusCode.speakerNotRecognized:
            print('说话人未识别');
            break;
          case VoicePrintStatusCode.disable:
            print('声纹识别已禁用');
            break;
          case VoicePrintStatusCode.enableWithoutRegister:
            print('声纹识别已启用但未注册');
            break;
          case VoicePrintStatusCode.unknown:
            print('未知状态');
            break;
        }

        print('用户语音识别: $text');
      },
      onAIAgentSubtitleNotify: (data) {
        String text = data['text'];
        bool isSentenceEnd = data['isSentenceEnd'];
        int userAsrSentenceId = data['userAsrSentenceId'];
        print('AI回复: $text');
      },
      onVolumeChanged: (data) {
        String uid = data['uid'];
        int volume = data['volume'];
        print('音量变化: $volume');
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AI通话配置'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _userIdController,
              decoration: InputDecoration(labelText: '用户ID'),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _rtcTokenController,
              decoration: InputDecoration(labelText: 'RTC Token'),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _instanceIdController,
              decoration: InputDecoration(labelText: '实例ID'),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _agentUserIdController,
              decoration: InputDecoration(labelText: 'AI代理用户ID'),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _channelIdController,
              decoration: InputDecoration(labelText: '频道ID'),
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () async {
                await AliAiCall.initEngine(userId: _userIdController.text);
                await AliAiCall.call(
                  rtcToken: _rtcTokenController.text,
                  aiAgentInstanceId: _instanceIdController.text,
                  aiAgentUserId: _agentUserIdController.text,
                  channelId: _channelIdController.text,
                );
              },
              child: Text('开始通话'),
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () async {
                await AliAiCall.hangup();
              },
              child: Text('结束通话'),
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter阿里AI通话功能插件ali_ai_call的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter阿里AI通话功能插件ali_ai_call的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中集成和使用阿里AI通话功能插件 ali_ai_call,可以通过以下步骤进行。下面是一个基本的代码示例,展示了如何配置和使用该插件。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 ali_ai_call 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  ali_ai_call: ^latest_version  # 请替换为实际的最新版本号

然后运行 flutter pub get 来获取依赖。

2. 配置Android和iOS

由于阿里AI通话功能依赖于原生代码,你需要在 AndroidManifest.xmlInfo.plist 中进行必要的配置。具体配置步骤请参考 ali_ai_call 插件的官方文档,因为这部分配置可能随着插件版本更新而变化。

3. 初始化插件

在你的 Flutter 应用中,你需要初始化 ali_ai_call 插件。这通常在应用的入口文件(如 main.dart)中进行。

import 'package:flutter/material.dart';
import 'package:ali_ai_call/ali_ai_call.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AliAiCall? _aliAiCall;

  @override
  void initState() {
    super.initState();
    // 初始化插件
    _initAliAiCall();
  }

  Future<void> _initAliAiCall() async {
    // 替换为你的阿里云AppKey和Secret
    String appKey = 'your_app_key';
    String secret = 'your_app_secret';

    _aliAiCall = AliAiCall(appKey: appKey, secret: secret);

    // 你可以在这里添加更多的初始化逻辑,比如鉴权等
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Ali AI Call Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              // 启动AI通话(示例代码,具体方法名及参数请参考插件文档)
              _startAICall();
            },
            child: Text('Start AI Call'),
          ),
        ),
      ),
    );
  }

  Future<void> _startAICall() async {
    if (_aliAiCall != null) {
      try {
        // 替换为实际的通话参数
        Map<String, dynamic> params = {
          'callerNumber': 'caller_phone_number',
          'calleeNumber': 'callee_phone_number',
          // 其他参数...
        };

        // 调用插件提供的启动AI通话方法(示例方法名,实际方法名请参考插件文档)
        await _aliAiCall!.startCall(params);
      } catch (e) {
        print('Failed to start AI call: $e');
      }
    }
  }
}

注意事项

  1. 权限管理:确保你的应用已经请求并获得了必要的权限,如网络权限、麦克风权限等。
  2. 错误处理:在实际应用中,你需要添加更多的错误处理和日志记录,以便更好地调试和维护。
  3. 插件文档:由于插件的API可能会随着版本更新而变化,因此强烈建议查阅最新的 ali_ai_call 插件文档,以获取最准确的使用方法和参数信息。

总结

上述代码展示了如何在Flutter项目中集成和使用 ali_ai_call 插件来启动阿里AI通话功能。请务必根据插件的官方文档和实际需求进行相应的调整和优化。

回到顶部