# 自定义音频采集和渲染
# 简介
实时音频传输过程中,JC SDK 会启动默认的音频模块进行采集和渲染。当遇到不支持系统标准 API 的音频设备的时候,或者希望使用自己已经拥有的音频模块进行音频采集和渲染的时候,您可以选择在音频被采集前自定义音频采集,也可以选择在音频播放前自定义音频渲染。
# 前提条件
在自定义音频采集和渲染前,确保已经初始化了 JCMediaDevice (opens new window) 模块。
# 自定义音频采集
参照下述步骤,在音频输入前,修改音频输入源和采样率等参数:
- 发起通话前,将 JCMediaDevice (opens new window) 中 audioParam (opens new window) 的 autoStartAudioInputDevice (opens new window) 设置为
false
。这种情况下才可以获取音频输入数据。 - 调用 inputCustomAudioData (opens new window) 自定义音频采集。 建议在一对一通话状态为连接中时或者加入频道成功后,在子线程不断的调用此方法传入音频数据。
- 在结束通话的时候,关闭子线程停止音频采集。
// 在开启前将 autoStartAudioInputDevice 属性设为 false
turnOffAutoStartAudioOutputDevice(): void {
this.mediaDevice.audioParam.autoStartAudioInputDevice = false;
}
private customAudioInputTask: TaskExecutor | null = null;
// 自定义音频采集,在状态为连接中时或者加入频道成功后调用此方法
customizeAudioInput(): void {
// 创建子线程任务执行器
this.customAudioInputTask = new TaskExecutor('CustomAudioInput', () => {
const sampleRateHz: number = 8000;
const channels: number = 1;
// 自定义音频数据
const value: ArrayBuffer = stringToArrayBuffer("Any String you want");
const buffer: ArrayBuffer = value;
// 将音频输入数据输入到媒体层
while ((this.call != null && this.call.getActiveCallItem() != null) ||
(this.mediaChannel != null && this.mediaChannel.getState() == JCMediaChannel.STATE_JOINED)) {
this.mediaDevice.inputCustomAudioData(sampleRateHz, channels, buffer, 0, 0, 0);
sleep(1000); // 模拟延迟
}
});
// 启动任务
this.customAudioInputTask.start();
}
// 工具函数:将字符串转换为ArrayBuffer
function stringToArrayBuffer(str: string): ArrayBuffer {
const encoder = new TextEncoder();
return encoder.encode(str).buffer;
}
// 工具函数:模拟延迟
function sleep(ms: number): void {
const start = new Date().getTime();
while (new Date().getTime() < start + ms);
}
# 自定义音频渲染
参照下述步骤,在音频播放前,修改音频输入源和采样率等参数:
- 发起通话前,将 JCMediaDevice (opens new window) 中 audioParam (opens new window) 的 autoStartAudioOutputDevice (opens new window) 设置为
false
。这种情况下才可以获取音频输出数据。 - 调用 getAudioOutputData (opens new window) 自定义音频渲染。建议在一对一通话状态为连接中时或者加入频道成功后,在子线程不断的调用此方法渲染音频数据。
- 在结束通话的时候,关闭子线程停止音频渲染。
// 在开启前将 autoStartAudioOutputDevice 属性设为 false
turnOffAutoStartAudioOutputDevice(): void {
this.mediaDevice.audioParam.autoStartAudioOutputDevice = false;
}
private audioOutputTask: TaskExecutor | null = null;
// 自定义音频渲染,在状态为连接中时或者加入频道成功后调用此方法
customizeAudioOutput(): void {
// 创建子线程任务执行器
this.audioOutputTask = new TaskExecutor('AudioOutputData', () => {
const sampleRateHz: number = 8000;
const channels: number = 1;
const bufferSize: number = Math.floor(sampleRateHz / 100) * 2 * channels;
const buffer: ArrayBuffer = new ArrayBuffer(bufferSize);
// 获取音频输出数据
while ((this.call != null && this.call.getActiveCallItem() != null) ||
(this.mediaChannel != null && this.mediaChannel.getState() == JCMediaChannel.STATE_JOINED)) {
this.mediaDevice.getAudioOutputData(sampleRateHz, channels, buffer);
sleep(1000); // 模拟延迟
}
});
// 启动任务
this.audioOutputTask.start();
}
// 工具函数:模拟延迟
function sleep(ms: number): void {
const start = new Date().getTime();
while (new Date().getTime() < start + ms);
}