腾讯互动直播 音频 视频 踩过的坑 一
由于公司业务需要互动直播业务,再调用腾讯的sdk的时候,由于是小公司,很难即使得到腾讯技术人员回复,以下将列举我再音频,视频这块遇到一些坑
1,由于公司业务需要对互动直播观众端音频可以进行加密,听不清,只有互动两个人才能正常对话,查找腾讯的sdk发现
通过上图可以看到,只有6可以叠加一段音乐,其他5,7不能改变原来声音,所以想通过回调直接把音频加密再去播放通过上述方式是做不到。
2,只能想其他的方法,后来看到腾讯的sdk有
public boolean enableSpeaker(boolean var1, AVAudioCtrl.EnableSpeakerCompleteCallback var2) {
return this.mIsCalling?false:this.nativeEnableSpeaker(var1, var2);
}
这个接口通过字面意思是关闭扬声器,以下是官方文档表述
enableSpeaker
public boolean enableSpeaker(boolean isEnable)
开启或关闭扬声器/耳机。
同步返回结果。此方法操作的物理设备和setAudioOutputMode(int)有关系。
输出模式为OUTPUT_MODE_SPEAKER,则操作的是扬声器。
输出模式为OUTPUT_MODE_HEADSET,则操作的是耳机。
Parameters:
isEnable - true表示开启,false表示关闭。
Returns:
true表示设置成功,false表示失败。
再调用这个接口切记要再主线程否则会返回
1,或者
1201, 1007, 1002.
查找AVError类可以清楚的看到错误的意思
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.tencent.av.sdk;
public class AVError {
public static final int AV_OK = 0;
public static final int AV_ERR_FAIL = 1;
public static final int AV_ERR_REPETITIVE_OPERATION = 1001;
public static final int AV_ERR_EXCLUSIVE_OPERATION = 1002;
public static final int AV_ERR_HAS_IN_THE_STATE = 1003;
public static final int AV_ERR_INVALID_ARGUMENT = 1004;
public static final int AV_ERR_TIMEOUT = 1005;
public static final int AV_ERR_NOT_IMPLEMENTED = 1006;
public static final int AV_ERR_NOT_IN_MAIN_THREAD = 1007;
public static final int AV_ERR_RESOURCE_IS_OCCUPIED = 1008;
public static final int AV_ERR_CONTEXT_NOT_START = 1101;
public static final int AV_ERR_CONTEXT_NOT_STOP = 1102;
public static final int AV_ERR_ROOM_NOT_EXIST = 1201;
public static final int AV_ERR_ROOM_NOT_EXITED = 1202;
public static final int AV_ERR_DEVICE_NOT_EXIST = 1301;
public static final int AV_ERR_ENDPOINT_NOT_EXIST = 1401;
public static final int AV_ERR_ENDPOINT_HAS_NOT_VIDEO = 1402;
public static final int AV_ERR_TINYID_TO_OPENID_FAILED = 1501;
public static final int AV_ERR_OPENID_TO_TINYID_FAILED = 1502;
public static final int AV_ERR_NOT_TRY_NEW_ROOM = 2001;
public static final int AV_ERR_TRY_NEW_ROOM_FAILED = 2002;
public static final int AV_ERR_SERVER_FAILED = 10001;
public static final int AV_ERR_SERVER_NO_PERMISSION = 10003;
public static final int AV_ERR_SERVER_REQUEST_ROOM_ADDRESS_FAIL = 10004;
public static final int AV_ERR_SERVER_CONNECT_ROOM_FAIL = 10005;
public static final int AV_ERR_SERVER_FREE_FLOW_AUTH_FAIL = 10006;
public static final int AV_ERR_IMSDK_UNKNOWN = 6999;
public static final int AV_ERR_IMSDK_TIMEOUT = 7000;
public static final int AV_ERR_UNKNOWN = 65536;
public static final int AV_ERR_SOUTIL_INTERNAL_MEMORY_NOT_ENOUGH = 10101;
public static final int AV_ERR_SOUTIL_INTERNAL_ERROR = 10102;
public AVError() {
}
}
结合帮助文档
static int AV_ERR_CONTEXT_NOT_START
AVContext没有启动
static int AV_ERR_CONTEXT_NOT_STOP
AVContext未结束
static int AV_ERR_DEVICE_NOT_EXIST
设备不存在
static int AV_ERR_ENDPOINT_HAS_NOT_VIDEO
该成员没有上视频
static int AV_ERR_ENDPOINT_NOT_EXIST
房间成员不存在
static int AV_ERR_EXCLUSIVE_OPERATION
互斥操作。已经在进行某种操作,再次去做同类型的其他操作,则返回这个错误
static int AV_ERR_FAIL
一般错误
static int AV_ERR_HAS_IN_THE_STATE
已经处于所要状态,无需再操作。如设备已经打开,再次去打开,就返回这个错误码
static int AV_ERR_IMSDK_TIMEOUT
static int AV_ERR_IMSDK_UNKNOWN
IMSDK内部错误
static int AV_ERR_INVALID_ARGUMENT
错误参数
static int AV_ERR_NOT_IMPLEMENTED
功能未实现
static int AV_ERR_NOT_IN_MAIN_THREAD
不在主线程中执行操作
可以看到错误原因从而解决错误,最终实现了关闭观众端的扬声器。
3,观众端的扬声器关闭,那怎么能让观众听到加密的声音呢,很显然,这里需要对上边的5,7回调进行操作,上述5的回调可以拿到两路主播任意一路的声音,也可以通过上图的7的,拿到两个主播混流的声音,当我拿到他们回调的数据,通过调用android原声的AudioTrack进行播放声音
m_out_buf_size = AudioTrack.getMinBufferSize(48000,
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
// 实例化播放音频对象
m_out_trk = new AudioTrack(AudioManager.STREAM_MUSIC, 48000,
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, m_out_buf_size,
AudioTrack.MODE_STREAM);
对回调里边数据进行播放
ILiveSDK.getInstance().getAvAudioCtrl().registAudioDataCallbackWithByteBuffer(AVAudioCtrl.AudioDataSourceType.AUDIO_DATA_SOURCE_PLAY, new AVAudioCtrl.RegistAudioDataCompleteCallbackWithByteBuffer() {
@Override
public int onComplete(AVAudioCtrl.AudioFrameWithByteBuffer audioFrameWithByteBuffer, int i) {
if (play_flag == 2){
Log.d("jni", "start len = " + audioFrameWithByteBuffer.dataLen);
audio.VoiceDisposeWriteBuf(audioFrameWithByteBuffer.data.array(), 960);
audio.VoiceDisposeRead(960);
audio.VoiceDisposeReadBuf(audio_buf, 960);
m_out_trk.write(audio_buf, 0, audioFrameWithByteBuffer.dataLen);
Log.d("jni", "m_out_trk.write len = " + audioFrameWithByteBuffer.dataLen);
}
//Log.d("jni", "play_flag = " + play_flag);
return 0;
}
});
这样就完成了对观众端数据进行加密