跳到主要内容

混音

集成混音插件​

混音功能包含在 RTCLib SDK 中。如需从网络音源混音,需要额外集成 RongRTCPlayer 插件。在导入 SDK 前,您可以前往 融云官网 SDK 下载页面 确认当前最新版本号。

通过 CocoaPods 管理依赖 (推荐)​

  1. 如果您的项目中没有 Podfile 文件,您需要打开终端并进入到项目的根目录,在终端中运行 pod init 命令,之后系统会自动创建一个默认的 Podfile 文件,在项目中的 Podfile 文件中添加如下内容:

    ruby
    # 基础混音功能(包含在 RTCLib 中)
    pod 'RongCloudRTC', '~> x.y.z'

    # 网络音源混音插件(可选)
    pod 'RongCloudRTC/RongRTCPlayer', '~> x.y.z'
    提示
    • 网络音源混音插件会自动依赖下载对应版本的 RTCLib 库,一般不需要手动指定。
    • x.y.z 代表 RTCLib 具体的版本号,您可以在融云官网 SDK 下载页面或在终端中通过先执行 pod repo update,再执行 pod search RongCloudRTC 命令在 CocoaPods 仓库查询 RTCLib 最新的版本。
  2. 打开终端并进入到 Podfile 文件所在的目录,在终端中运行以下命令:

    shell
    pod install
    提示

    如果终端中出现类似 CocoaPods could not find compatible versions for 等找不到相关版本的报错,可先在终端中执行 pod repo update 命令,再执行 pod install 命令。

  3. 通过 Xcode 打开项目目录下的 xcworkspace 文件加载工程。

手动集成​

  1. 前往 融云官网 SDK 下载页面,下载 RTCLib SDK 和混音插件:

  2. 导入以下内容:

    • RongRTCLib.xcframework(基础混音功能)
    • RongRTCPlayer.xcframework(网络音源混音,可选)
  3. 修改您的项目配置。在 General → Frameworks, Libraries, and Embedded Binaries 中,将手动导入的 RTCLib SDK 所有的 Framework 全部改为 Embed & Sign。

  4. 请将工程中 Target > Build Settings > Other Linker Flags 在此项中添加 -ObjC。为避免编译失败,请勿使用 -all_load 和 -force_load。

开始混音​

混音功能支持将用户自定义的音频数据与本地麦克风采集的音频数据进行混合。加入房间并发布默认的音频流后,调用 startMixingWithURL:playback:mixerMode:loopCount: 方法混音指定的音频文件。

接口原型​

Objective C
- (BOOL)startMixingWithURL:(NSURL *)fileURL
playback:(BOOL)isPlay
mixerMode:(RCRTCMixerMode)mode
loopCount:(NSUInteger)count;

参数说明​

参数类型是否必填说明
fileURLNSURL是本地文件或者网络资源 URL。注意,参数 fileURL 为网络资源时,在线资源混音需要依赖 RongRTCPlayer 插件。
isPlayBOOL是是否在本地播放
mode[RCRTCMixerMode][RCRTCMixerMode]是混音方式
countNSUInteger是循环混音或者播放次数

返回值​

混音成功返回 YES,失败返回 NO。

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

// NSURL *mediaUrl = [NSURL URLWithString:@"https://xxxx.mp3"];
NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"];
NSURL *mediaUrl = [NSURL fileURLWithPath:audioFilePath];
[[RCRTCAudioMixer sharedInstance] startMixingWithURL:mediaUrl
playback:YES
mixerMode:RCRTCMixerModeMixing
loopCount:NSUIntegerMax];

切换左右声道​

提示

SDK 从 5.1.13 开始支持切换左右声道。仅支持本地文件混音时切换声道,不支持网络资源文件。

与本地文件混音时,可以调用 setAudioDualMonoMode 单独选择混音的左右声道。如未调用,默认模式为使用立体声混音。

例如调用 setAudioDualMonoMode 设置为左声道混音时,SDK 会拷贝当前音频的左声道数据填充右声道,进而两个声道都是左声道数据,开始混音后用户听到的就是当前左声道混音的声音。

您可以通过左右声道切换实现原唱、伴唱切换,以满足卡拉 OK 场景下的需求。通过声道切换原唱、伴唱要求音源支持,即原唱、伴唱音轨分别位于两个独立声道。

接口原型​

Objective C
- (BOOL)setAudioDualMonoMode:(RCRTCAudioDualMonoMode)mode;

参数说明​

参数类型是否必填说明
mode[RCRTCAudioDualMonoMode][RCRTCAudioDualMonoMode]是声道模式:0 立体声混音,1 左声道混音,2 右声道混音

返回值​

设置成功返回 YES,失败返回 NO。设置即时生效。

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

RCRTCAudioDualMonoMode mode = RCRTCAudioDualMonoLeft; // RCRTCAudioDualMonoRight
[[RCRTCAudioMixer sharedInstance] setAudioDualMonoMode:mode];

控制混音状态(结束、暂停、恢复)​

  • 结束混音时需要调用以下方法。

    Objective C
    [[RCRTCAudioMixer sharedInstance] stop];
  • 暂停混音

    Objective C
    [[RCRTCAudioMixer sharedInstance] pause];
  • 恢复混音

    Objective C
    [[RCRTCAudioMixer sharedInstance] resume];
  • 获取当前混音状态

    Objective C
    if ([RCRTCAudioMixer sharedInstance].status == RTCMixEngineStatusPlaying) {
    // 处理正在播放混音的逻辑
    }

设置混音播放位置​

提示

从 5.2.5.1 开始,SDK 支持通过 setPlayProgress: 先设置播放位置,再调用 startMixingWithURL:playback:mixerMode:loopCount: 开始混音。

您可以在混音开始前后设置播放位置。如果希望从混音文件指定位置开始混音,建议先设置播放位置,再调用开始混音。

接口原型​

Objective C
- (void)setPlayProgress:(float)progress;

参数说明​

参数类型是否必填说明
progressfloat是设置播放进度,取值范围 [0,1]

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

// 设置播放位置为 50%
[[RCRTCAudioMixer sharedInstance] setPlayProgress:0.5];

音量控制​

SDK 支持控制混音音源输入的音量和混音在本地播放的音量。

调节混音输入音量​

设置音频文件混音时的输入音量,取值范围 [0,100],默认值 100。

接口原型​

Objective C
@property (nonatomic, assign) NSUInteger mixingVolume;

参数说明​

参数类型说明
mixingVolumeNSUInteger混音输入音量,取值范围 [0,100]

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

// 设置音频文件混音输入音量为 50
[RCRTCAudioMixer sharedInstance].mixingVolume = 50;

调节混音本地播放音量​

如果设置混音时选择了本地播放,您可以调节音频文件本地播放音量,取值范围 [0,100],默认值 100。

接口原型​

Objective C
@property (nonatomic, assign) NSUInteger playingVolume;

参数说明​

参数类型说明
playingVolumeNSUInteger本地播放音量,取值范围 [0,100]

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

// 设置音频文件本地播放音量为 50
[RCRTCAudioMixer sharedInstance].playingVolume = 50;

获取音频文件时长​

SDK 支持获取本地音频文件时长。网络资源 URL 在播放后才能拿到音频时长。

接口原型​

Objective C
+ (Float64)durationOfAudioFile:(NSURL *)url;

参数说明​

参数类型是否必填说明
urlNSURL是文件 URL(网络资源 URL 在播放后才能拿到音频时长)

返回值​

返回音频文件时长,单位为秒。

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"];
NSURL *fileUrl = [NSURL fileURLWithPath:audioFilePath];
Float64 duration = [RCRTCAudioMixer durationOfAudioFile:fileUrl];

混音事件回调​

设置混音播放代理,通过代理可以获取 播放/混音进度 和 播放/混音状态。

Objective C
[RCRTCAudioMixer sharedInstance].delegate = self;
Objective C
#pragma mark - RCRTCAudioMixerAudioPlayDelegate - AudioMixer 的播放代理

/*!
当前播放进度

@param progress 播放进度 range [0,1]
@discussion
当前播放进度

@remarks 代理
*/
- (void)didReportPlayingProgress:(float)progress{
NSLog(@"当前播放进度 - %@", @(progress));
}

/*!
混音状态

@param mixingState 混音状态
@param mixingReason 混音状态改变的原因
@discussion
当前混音状态
Add from 5.1.3

@remarks 代理
*/
- (void)didAudioMixingStateChanged:(RCRTCAudioMixingState)mixingState reason:(RCRTCAudioMixingReason)mixingReason{
if (mixingState == RCRTCMixingStatePlaying){
// 开始混音,可能的原因有:
if (mixingReason == RCRTCMixingReasonStartedByUser){
// 调用了开始混音方法 startMix
}else if (mixingReason == RCRTCMixingReasonStartNewLoop){
// 调用了 startMix 传入的loopCount < 0(无限循环)或 > 1时,自动开始下一次混音。
}else if (mixingReason == RCRTCMixingReasonResumedByUser){
// 调用了 resume 方法继续开始混音
}else if (mixingReason == RCRTCMixingReasonFileLoaded){
// 本地或网络混音文件已加载完成(SDK 必须等待资源加载完成后才能播放混音文件),该回调要求 SDK 版本 ≧ 5.2.5.1。
}
}else if(mixingState == RCRTCMixingStateStop){
// 混音完成,可能的原因有:
if (mixingReason == RCRTCMixingReasonAllLoopsCompleted){
// 调用 startMix方法时,传入的 loopCount > 0,并且 loopCount 次数的混音已经完成
}else if (mixingReason == RCRTCMixingReasonOneLoopCompleted){
// 调用 startMix方法时,传入的 loopCount < 0(无限循环)或 > 1,混音完成一次。接下来会继续自动开始下一次混音。
}else if (mixingReason == RCRTCMixingReasonStoppedByUser){
// 调用 stopMix 方法停止混音
}
}else if (mixingState == RCRTCMixingStatePause){
// 暂停了混音,mixingReason 为 RCRTCMixingReasonPausedByUser
}else if (mixingState == RCRTCMixingStateFailed){
// 加载失败,mixingReason 为 RCRTCMixingReasonCanNotOpen
}
}


@end

使用自定义音频数据进行混音​

您可以通过写入自定义音频数据的方式进行混音。自定义音频数据可以使用 SDK 内置的格式要求或使用您自定义的格式。

使用内置音频格式写入自定义混音数据​

  1. 通过以下该属性,获取方法 writeAudioBufferList:frames:sampleTime:playback: 写入 AudioBufferList 要求的格式。

    Objective C
    @property (nonatomic, readonly, class) AudioStreamBasicDescription writeAsbd;
  2. 向即将发送的音频数据中混合自定义音频数据。

    接口原型​

    Objective C
    - (void)writeAudioBufferList:(const AudioBufferList*)abl
    frames:(UInt32)frames
    sampleTime:(SInt64)sampleTime
    playback:(BOOL)isPlay;

    参数说明​

    abl 为 AudioBufferList 类型数据,必须使用上一步中获取的格式。

    参数类型是否必填说明
    ablconst AudioBufferList *是音频数据
    framesUInt32是音频帧个数
    sampleTimeSInt64是音频帧时间戳
    isPlayBOOL是是否在本地播放

    代码示例​

    Objective C
    #import <RongRTCLib/RongRTCLib.h>

    SInt64 sampleTime = 0;
    while (true) {
    CMSampleBufferRef sample = [_outAudioTrack copyNextSampleBuffer];
    if (!sample) {
    break;
    }
    AudioBufferList abl = {0};
    CMBlockBufferRef blockBuffer;
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sample,
    NULL,
    &abl,
    sizeof(abl),
    NULL,
    NULL,
    0,
    &blockBuffer);
    CMItemCount count = CMSampleBufferGetNumSamples(sample);
    [[RCRTCAudioMixer sharedInstance] writeAudioBufferList:&abl
    frames:(UInt32)count
    sampleTime:sampleTime
    playback:YES];
    sampleTime += count;
    CFRelease(blockBuffer);
    CFRelease(sample);
    if (_status == RongRTCFileVideoCapturerStatusStopped) {
    break;
    }
    }

使用自定义格式写入混音数据​

提示

SDK 从 5.2.3 版本开始支持该功能。

如果您希望自行指定 AudioBufferList 数据的格式,可以使用以下方法写入混音数据。

接口原型​

Objective C
- (void)writeAudioBufferList:(const AudioBufferList *)abl
frames:(UInt32)frames
sampleTime:(SInt64)sampleTime
asbd:(AudioStreamBasicDescription)asbd
playback:(BOOL)isPlay;

参数说明​

参数类型是否必填说明
ablconst AudioBufferList *是音频数据,格式为 PCM
framesUInt32是音频帧个数
sampleTimeSInt64是音频帧时间戳
asbdAudioStreamBasicDescription是音频格式描述
isPlayBOOL是是否在本地播放

代码示例​

Objective C
#import <RongRTCLib/RongRTCLib.h>

AudioStreamBasicDescription asbd = {0};
asbd.mSampleRate = 44100;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mChannelsPerFrame = 2;
// ... 其他格式设置

[[RCRTCAudioMixer sharedInstance] writeAudioBufferList:&abl
frames:frames
sampleTime:sampleTime
asbd:asbd
playback:YES];

API 文档​