融云 Web SDK 如何实现语音的收发 ?
根据融云的开发文档, 总结得出, 融云 WebSDK 需要的是一个 aac 格式的音频 url, 不关注 url 如何生成. 生成 url 的步骤由开发者实现
文档: https://docs.rongcloud.cn/v4/views/im/noui/guide/private/msgmanage/msgsend/web.html#HQVCMsg
所以关注点放在以下几个问题:
1、Web 端能否实现语音录制
2、结合融云 SDK 实现语音的发送
3、结合融云 SDK 实现语音的接收和播放
Web 端能否实现语音录制
答案是可以. 不过只有部分浏览器支持, 录制的音频格式有很多限制, 且只有当前站点为 localhost 或 https 时才可使用
录制原理:
getUserMedia、MediaRecorder
使用 getUserMedia 获取音频流, 使用 MediaRecorder 录音获取音频数据
以下为录制 5s, 获取 File 对象的代码:
// 通过 getUserMedia 获取音频流
navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
const mediaRecorder = new MediaRecorder(stream);
const chunks = [];
// 收集音频数据
mediaRecorder.ondataavailable = function (e) {
chunks.push(e.data);
};
// 监听音频录制停止
mediaRecorder.onstop = e => {
const blob = new Blob(chunks);
blob.lastModifiedDate = new Date();
const file = new File([blob], 'audio_file.aac', { type: "audio/aac" }); // 获取到 File 对象, 可将此对象上传至服务器, 获取音频 url
};
mediaRecorder.start(); // 开始录音. 此处自动开始, 读者可按产品逻辑点击某个按钮触发录音
setTimeout(function () { // 5s 倒计时自动停止录音. 读者可按产品逻辑设置停止时机
mediaRecorder.stop();
}, 5000)
});
获取到 file 对象后, 可将 file 上传至服务器, 获取音频的远端 url
经过测试, 发现录制的音频只能在集成了融云的 Android 端播放, iOS 端无法播放
经过搜集资料, 发现 MediaRecorder
录音的编码是有限制的, 默认是 webm
格式, 而融云支持播放的是 aac
格式
JS 官方文档也没有给出 MediaRecorder 具体支持的格式, 因为各个浏览器实现的编码都不同, 且就算编码格式支持, 也有可能因为计算资源不足而导致编码失败
官网提供以下代码检测支持状况:
var types = ["video/webm",
"audio/webm",
"video/webm\;codecs=vp8",
"video/webm\;codecs=daala",
"video/webm\;codecs=h264",
"audio/webm\;codecs=opus",
"video/mpeg"];
for (var i in types) {
console.log( "Is " + types[i] + " supported? " + (MediaRecorder.isTypeSupported(types[i]) ? "Maybe!" : "Nope :("));
// 重点 API: MediaRecorder.isTypeSupported
}
经过一系列调研, 总结以下几点:
1、需要注意浏览器兼容问题 getUserMedia、MediaRecorder
2、录制上传后的音频为 webm 格式. 融云 iOS 暂不支持播放. 读者可以尝试在录音时将录音数据编码由 webm 转化为 aac 格式. 也可以将数据传给服务端, 由服务端转换格式
3、要注意 getUserMedia
的安全限制. 要求访问站点必须为 localhost
或 https
结合融云 SDK 实现语音的发送
根据文章前的描述. 获取到远端音频 url 后, 调用融云的发送消息方法就可以了
注意: 记得先 初始化、连接 融云 SDK
var conversation = im.Conversation.get({
targetId: '接收方的 userId',
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
conversation.send({
messageType: RongIMLib.MESSAGE_TYPE.HQ_VOICE, // 'RC:HQVCMsg'
content: {
remoteUrl: 'https://rongcloud-audio.cn.ronghub.com/audio_amr__RC-2020-03-17_42_1584413950049.aac?e=1599965952&token=CddrKW5AbOMQaDRwc3ReDNvo3-sL_SO1fSUBKV3H:CDngyWj7ZApNmAfoecng7L_3SaU=', // 音频 url, 建议格式: aac
duration: 6, // 音频时长
type: 'aac'
}
}).then(function(message){
console.log('发送语音消息成功', message);
});
结合融云 SDK 实现语音的接收和播放
发送: 依照融云文档设置消息监听即可
var im = RongIMLib.init({ appkey: '' }); // 建议全局只初始化一次
var conversationList = []; // 当前已存在的会话列表
im.watch({
message: function(event){
var message = event.message;
console.log('有人给我发消息啦: ', message);
}
});
播放: 融云发送的音频默认格式为 aac 格式. Web 端使用 audio 标签直接播放即可
播放时遇到的坑:
Web 收到的消息不是 aac 格式, 而是 amr 格式:
测试时发现 Android 发送的语音消息是 RC:VcMsg
, 而不是 RC:HQVCMsg
查看文档, 发现 RC:VcMsg 是融云旧语音消息, RC:HQVCMsg 是新语音消息. 但是融云移动端 IMKit 默认发送还是旧语音消息
根据文档提供的切换接口, 将 Android 发送语音改为 RC:HQVCMsg
, 此问题成功解决了
切换文档:
https://docs.rongcloud.cn/v4/views/im/noui/guide/private/msgmanage/msgsend/android.html#voice