大家有没有想过在直播过程中的掌声,口哨,背景音等音效是怎么实现的吗?这些功能都是可以通过混音来实现的。本篇文章介绍即构科技音视频SDK高级功能第五篇,ZegoLiveRoom SDK 混音功能,还是以iOS环境为例。
混音
1、功能简介
ZegoLiveRoom SDK 为开发者提供了混音功能。混音是指,SDK 从 App 获取一路音频数据,将其与采集的音频数据,整合为一路混音数据,进而推流。直播过程中的掌声,口哨,背景音等音效均可通过混音实现。
2、步骤
混音的使用流程如下:
- App 启用混音功能
- App 设置混音音量
- App 将混音数据传递给 SDK
2.1 启用混音功能
调用此 API 启用混音功能。
ZegoLiveRoomApi-Publisher.h
/**
混音开关
@param enable true 启用混音输入,false 关闭混音输入。默认 false
@return true 成功,false 失败
@attention 必须确保在 initSDK 后调用
@note 主播端开启混音后,SDK 在 [ZegoLiveRoomApi (Publisher) -onAuxCallback:dataLen:sampleRate:channelCount:] 中获取混音输入数据
*/
- (bool)enableAux:(BOOL)enable;
请注意,后续操作均基于开启混音功能的基础上。
2.2 设置混音音量
启用混音后,调用此 API 调整混音音量。
ZegoLiveRoomApi-Publisher.h
/**
设置混音音量
@param volume 0~100,默认为 50
*/
- (void)setAuxVolume:(int)volume;
也可调用此 API 设置混音静音。
ZegoLiveRoomApi-Publisher.h
/**
混音静音开关
@param bMute true: aux 输入播放静音,false: 不静音。默认 false
@return true 成功,false 失败
@attention 推流开始前调用本 API 进行参数配置
*/
- (bool)muteAux:(bool)bMute;
请注意,SDK 对上述两个混音音量相关的 API 的调用时机无要求,混音前或混音后调用均可,取决于用户需求。
2.3 App 传递数据给 SDK
启用混音后,SDK 通过此 API 获取待传递的混音数据。
ZegoLiveRoomApi-Publisher.h
/** 混音音频数据输入回调。
当开启混音后,通过此回调获取混音音频数据。
<p><b>注意:</b>
1. 支持 16k 32k 44.1k 48k 采样率、单声道或者双声道、16位深的PCM 音频数据;<br>
2. 用户根据实际填写采样率及声道数;<br>
3. 为确保混音效果,请不要在此 API 中执行耗时操作</p>
@param pDataLen
*pDataLen既是输入参数也是输出参数;
作为输入参数,SDK会提供好长度值,用户按照这个长度写入数据即可,数据足够的情况下,无需更改*pDataLen的值
作为输出参数,如果填写的数据不足SDK提供的长度值,则赋值*pDataLen = 0;
或者最后的尾音不足SDK提供的长度值,可以用静音数据补齐。
@param pSampleRate 混音数据采样率,支持16k、32k、44.1k、48k
@param pNumChannels 混音数据声道数,支持1、2
@attention 用户调用该 API 将混音数据传递给 SDK
@note 混音数据 bit depth 必须为 16(2字节)
*/
- (void)onAuxCallback:(void *)pData dataLen:(int *)pDataLen sampleRate:(int *)pSampleRate channelCount:(int *)pChannelCount;
示例代码片段如下: 示例代码中pcm文件采样率为:44100 声道数为: 2
ZegoLiveViewController.m
- (void)onAuxCallback:(void *)pData dataLen:(int *)pDataLen sampleRate:(int *)pSampleRate channelCount:(int *)pChannelCount
{
if (self.auxData == nil)
{
//初始化auxData
NSURL *auxURL = [[NSBundle mainBundle] URLForResource:@"a.pcm" withExtension:nil];
if (auxURL)
{
self.auxData = [NSData dataWithContentsOfURL:auxURL options:0 error:nil];
self.pPos = (void *)[self.auxData bytes];
}
}
if (self.auxData)
{
int nLen = (int)[self.auxData length];
if (self.pPos == 0)
self.pPos = (void *)[self.auxData bytes];
const void *pAuxData = [self.auxData bytes];
if (pAuxData == NULL)
return;
*pSampleRate = 44100;
*pChannelCount = 2;
int nLeftLen = (int)(pAuxData + nLen - self.pPos);
if (nLeftLen < *pDataLen) {
self.pPos = (void *)pAuxData;
*pDataLen = 0;
return;
}
memcpy(pData, self.pPos, *pDataLen);
self.pPos = self.pPos + *pDataLen;
}
}
请注意:
- Demo 中演示的是循环播放音频,请开发者按照各自的需求实现该方法,不要直接复制。
- 如果数据足够,则copy pDataLen长度的数据到pData,如果不足要不补齐静音到SDK指定的pDataLen长度,要不设置
*pDataLen = 0。