logo
当前页

发送与接收语音消息


本文介绍如何使用 ZIM SDK 和 ZIM Audio SDK 快速实现基本的语音消息发送与接收功能。

前提条件

在实现“发送与接收语音消息”功能之前,请确保:

实现流程

用户发送与接收语音消息的过程主要包含录制音频、发送音频、接收音频和播放音频等环节。以客户端 A 和 B 的语音消息交互为例:

1 导入头文件

在项目文件中引入头文件 “ZIMAudio.h”。

Untitled
#import <ZIMAudio/ZIMAudio.h>
1
Copied!

2 初始化 SDK

在使用 ZIM Audio SDK 其他接口前,请先调用 initWithLicense 进行初始化。

在调用此接口时,如果您只希望实现最基础的语音消息收发,接口参数可以传空字符串。

如果您希望实现更多音频处理,请传入鉴权文件 License,如何获取 License,请参考 在线鉴权

Untitled
// 初始化 ZIM Audio SDK
// 本文描述的场景无需 License
[[ZIMAudio sharedInstance] initWithLicense:@""];
1
Copied!

3 监听回调

  1. 创建一个声明 ZIMAudioEventHandler 协议的类,并实现 ZIMAudioEventHandler 中的方法。

    Untitled
    #import <ZIMAudio/ZIMAudio.h>
    
    @interface ZIMAudioEventHandler : NSObject<ZIMAudioEventHandler>
    
    + (instancetype)sharedInstance;
    
    @end
    
    @implementation ZIMAudioEventHandler
    
    + (instancetype)sharedInstance {
        static ZIMAudioEventHandler *instance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[ZIMAudioEventHandler alloc] init];
        });
        return instance;
    }
    
    - (void)onError:(ZIMAudioError *)errorInfo{
        // 编写业务逻辑
    }
    @end
    
    1
    Copied!
  2. 调用 setEventHandler 设置该类的一个实例作为监听对象。

    Untitled
    [[ZIMAudio sharedInstance] setEventHandler:[ZIMAudioEventHandler sharedInstance]];
    
    1
    Copied!

4 录制音频文件

4.1 开始录制

  1. 消息发送客户端调用 startRecordWithConfig 接口定义音频文件存放的本地绝对路径(需包含音频文件名称与后缀,如 xxx/xxx/xxx.m4a,仅支持 .m4a 和 .mp3)和录制时长上限,开始录制音频文件。

    Untitled
    ZIMAudioRecordConfig *config = [[ZIMAudioRecordConfig alloc] init];
    config.filePath = @""; // 音频文件预期存放的本地绝对路径并携带文件后缀名,如 xxx/xxx/xxx.m4a,仅支持 .m4a 和 .mp3
    config.maxDuration = 10 * 1000; // 音频的最大录制时长,单位为 ms。
                                    // 默认为 60000 ms(即 60 秒)。最大值不超过 120000 ms(即 120 秒)。
                                    // 此处示例表示 10 个 1000 ms(即 10 秒)。
    [[ZIMAudio sharedInstance] startRecordWithConfig:config];
    
    1
    Copied!
  2. 触发相关回调。

    • 开始录制后,消息发送客户端可以监听 onRecorderStarted 回调,用于更新 UI。

      Untitled
      - (void)onRecorderStarted;
      
      1
      Copied!
    • ZIM Audio SDK 会每 500 毫秒通过 onRecorderProgress 回调一次进度通知,说明已录制的音频文件时长,此信息可用于 UI 更新 。

      Untitled
      - (void)onRecorderProgress:(int)currentDuration;
      
      1
      Copied!
    • 在录音开始时或在录音过程中,如果因异常导致录音失败,ZIM Audio SDK 将会通过 onRecorderFailed 进行通知,消息发送客户端可以监听该回调并参考 ZIM Audio 错误码文档 处理失败事件。

      Untitled
      - (void)onRecorderFailed:(ZIMAudioErrorCode)errorCode;
      
      1
      Copied!

4.2 完成录制

  1. 如需结束录制音频,请调用 completeRecord 接口。

    说明
    • 请在调用 completeRecord 接口之前,您已监听到 onRecorderStarted 回调,否则会导致本次录制取消,且收到录制时间过短的报错。
    • 如果录制没有被 完成取消,当录制时长达到时间上限时,ZIM Audio SDK 将会自动完成录制,并触发 onRecorderCompleted 回调。
    Untitled
    [[ZIMAudio sharedInstance] completeRecord];
    
    1
    Copied!
  2. 收到 onRecorderCompleted 回调后,即可根据开始录制时传入的路径找到该音频文件。

    Untitled
    - (void)onRecorderCompleted:(int)totalDuration; // totalDuration 为音频文件总时长,单位为毫秒
    
    1
    Copied!

4.3(可选)取消录制

  1. 如需提前停止录音且不需要发送语音消息时,调用 cancelRecord 即可中断录制并删除该录制文件。

    Untitled
    [[ZIMAudio sharedInstance] cancelRecord];
    
    1
    Copied!
  2. 调用 cancelRecord 接口后,将会触发 onRecorderCancelled 回调,消息发送客户端可监听该回调用于 UI 更新。

    Untitled
    - (void)onRecorderCancelled;
    
    1
    Copied!

4.4(可选)检查当前是否正在录制

如需在某一时刻检查当前是否正在录制中,可调用 isRecording 接口获取当前录制状态。

Untitled
BOOL isRecording = [[ZIMAudio sharedInstance] isRecording];   
1
Copied!

5 发送语音消息

注意

实现此步骤前,请确认用户已 登录 ZIM

onRecorderCompleted 触发后,消息发送客户端可以使用音频文件绝对路径构造 ZIMAudioMessage(ZIM 音频消息),并调用 sendMediaMessage 接口发送该消息,下列代码以在单聊会话中发送音频消息为例。

Untitled
// 录制完成回调
- (void)onRecorderCompleted:(int)totalDuration{
    // 将单位为毫秒的音频时长转换为 ZIM 需要的秒
    int second = totalDuration / 1000; 
    // 构造 ZIM 音频消息
    ZIMAudioMessage *audioMessage = [[ZIMAudioMessage alloc] initWithFileLocalPath:@"录制音频文件绝对路径" audioDuration: second];

    // 在单聊会话中发送音频消息
    ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
    [[ZIM getInstance] sendMediaMessage:audioMessage toConversationID:@"单聊的会话 ID" conversationType:ZIMConversationTypePeer config:sendConfig notification:nil callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
        if(errorInfo.code == ZIMErrorCodeSuccess){
            // 消息发送成功
        }else{
            // 根据官网 ZIM 错误码文档处理
        }
    }];   
}  
1
Copied!

如需了解发送进度,请参考收发消息文档的 富媒体文件消息的发送进度回调

6 接收语音消息

注意

实现此步骤前,请确认用户已 登录 ZIM

根据会话类型(单聊、房间、群组),消息接收客户端监听 receivePeerMessagereceiveGroupMessagereceiveRoomMessage,接收语音消息的相关通知,然后可以调用 downloadMediaFileWithMessage 接口,下载音频文件到本地。

下列代码描述在单聊会话接收并下载音频消息。

Untitled
// 收到单聊消息时,将会触发 receivePeerMessage 回调
 - (void)zim:(ZIM *)zim receivePeerMessage:(NSArray<ZIMMessage *> *)messageList fromUserID:(NSString *)fromUserID {
    // 遍历收到的消息列表
    for (ZIMMessage *message in messageList) {
        // 如果消息类型为音频消息
        if(message.type == ZIMMessageTypeAudio){
            
            ZIMAudioMessage *audioMessage = (ZIMAudioMessage *)message;

            // 音频消息的本地文件路径为空字符串,则调用下载接口
            if([audioMessage.fileLocalPath isEqual:@""]){
                //如果该音频消息不存在本地文件路径,代表该消息的音频文件还未下载到本地
                [[ZIM getInstance] downloadMediaFileWithMessage:audioMessage fileType:ZIMMediaFileTypeOriginalFile progress:^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
                    // 此处获取音频文件下载进度
                } callback:^(ZIMMediaMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
                    if(errorInfo.code == ZIMErrorCodeSuccess){
                         message.fileLocalPath; // 下载成功,获取音频文件本地绝对路径
                    }else{
                        // 下载失败,根据 ZIM 官网错误码表处理失败事件
                    }
                }];
            }
            // 本地音频文件路径不为空,直接取值即可
            else{
                audioMessage.fileLocalPath; // 音频文件本地绝对路径
            }
        }
    }
}  
1
Copied!

如需了解下载进度,请参考收发消息文档的 富媒体文件消息的下载进度回调

7 播放音频文件

7.1 开始播放

  1. 消息接收客户端调用 startPlayWithConfig 接口,传入音频文件的本地绝对路径,设置音频输出的路由类型,开始播放音频文件。

    Untitled
    // 开始播放音频
    
    // 构造播放设置
    ZIMAudioPlayConfig *config = [[ZIMAudioPlayConfig alloc] init];
    config.filePath = @"";// 填入音频文件的本地路径。
    config.routeType = ZIMAudioRouteTypeSpeaker; // ZIMAudioRouteTypeSpeaker:扬声器播放
                                                 // ZIMAudioRouteTypeReceiver:听筒播放
    [[ZIMAudio sharedInstance] startPlayWithConfig:config];
    
    1
    Copied!
  2. 触发相关回调。

    • 监听回调 onPlayerStarted ,用于 UI 更新。

      Untitled
      - (void)onPlayerStarted:(int)totalDuration; // totalDuration 为音频文件总时长,单位为毫秒
      
      1
      Copied!
    • ZIM Audio SDK 会每 500 毫秒通过 onPlayerProgress 回调一次进度通知,说明已播放时长,此信息可用于 UI 更新 。

      Untitled
      - (void)onPlayerProgress:(int)currentDuration;
      
      1
      Copied!
    • 在播放开始时或在播放过程中,如果因异常导致播放失败,ZIM Audio SDK 将会通过 onPlayerFailed 进行通知,消息接收客户端可以监听该回调并参考 ZIM Audio 错误码文档 处理失败事件。

      Untitled
      - (void)onPlayerFailed:(ZIMAudioErrorCode)errorCode;
      
      1
      Copied!
    • 若因其他操作(如在播放期间开始录音、在播放期间接收到系统的来电事件、在播放期间音频设备被其他应用抢占等情况。)导致播放终端,ZIM Audio SDK 将回调 onPlayerInterrupted

      Untitled
      - (void)onPlayerInterrupted;
      
      1
      Copied!
    • 播放完成时,ZIM Audio SDK 将会回调 onPlayerEnded

      Untitled
      - (void)onPlayerEnded;
      
      1
      Copied!
  3. (可选)如需在播放过程中切换音频输出设备(扬声器或听筒),请调用 setAudioRouteType

    注意

    若用户已连接耳机,该接口调用将不会生效,音频输出仍将通过耳机进行。

    Untitled
    // 设置输出设备为扬声器
    [[ZIMAudio sharedInstance] setAudioRouteType:ZIMAudioRouteTypeSpeaker];
    
    1
    Copied!

7.2(可选)停止播放

  1. 如需中断播放,请调用 stopPlay 接口。

    Untitled
    [[ZIMAudio sharedInstance] stopPlay];
    
    1
    Copied!
  2. 监听 onPlayerStopped 回调,更新 UI。停止播放或播放完成后,ZIM Audio SDK 将释放对音频设备的占用。

    Untitled
    - (void)onPlayerStopped;
    
    1
    Copied!

8 反初始化

如果用户彻底不使用语音功能,可调用 uninit 释放资源。

Untitled
[[ZIMAudio sharedInstance] uninit];
1
Copied!

Previous

集成 SDK

Next

在线鉴权