名称: 上海璟梦信息科技有限公司 音视频 SDK 集成文档
版本: V1.0.1
日期: 2022-04-19
在跟目录下的build.gradle
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
maven {
url "https://nexus-sdk.cm253.com/repository/maven-public/"
}
}
}
在app目录下的buil.gradle
implementation 'com.chuanglan.sdk:rtc:1.2.0.2@jar'
ndk{
abiFilters "armeabi-v7a", "arm64-v8a"
}
1)添加 SDK 相关权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA"/>
# IM
-keep class com.chuanglan.** { *;}
-keep class com.network.okhttp.** { *;}
-keep class com.network.okio.** { *;}
-keep class org.apache.mina.** { *;}
-keep class com.google.protobuf.** { *;}
-keep class org.slf4j.** { *;}
# 实时音视频
-keep class com.chuanglan.** { *;}
-keep class com.cloud.audio.** { *;}
-keep class com.lib.commonlib.** { *;}
-keep class com.medialib.audio.** { *;}
-keep class com.protocol.tlv.** { *;}
-keep class com.smart.audio.** { *;}
-keep class com.third.google.gson** { *;}
在代码中调用 SDK 初始化方法:
private VoipInitInfo info = new VoipInitInfo();
info.setAppId(xxx);
info.setRoomId(xxx);
info.setUserId(xxx);
//BusinessDataStorage.getInstance().getAppToken(); IM登录成功后这样获取token
info.setAppToken(xxx);
info.setRoomSecret(xxx);
CLVideoLib.Builder videoBuilder = CLVideoLib.create();
videoBuilder.builder(context, "您的APPID");
// 设置 IP 地址 私有化部署可以设置
// CLVoiceLib.getInstance().setTcpHost("xxx.xxx.xxx.xxx");
// 设置端口号
// CLVoiceLib.getInstance().setTcpPort(xxxx);
// 语音模块初始化
CLVideoLib.getInstance().init(videoBuilder);
// 初始化房间信息
CLVideoLib.getInstance().initRoomParam(info);
VoipListener voipListener = new VoipListener(){
@Override
public void initSuccess() {
// 初始化成功
}
@Override
public void initError(String msg) {
// 初始化失败
}
@Override
public void messageError(int errorCode, Object errorInfo) {
// 错误信息
}
@Override
public void micAction(boolean isUp) {
// 上下麦
}
@Override
public void loginAction(boolean success, String msg) {
// 登录动作回调
}
@Override
public void logoutAction(boolean success, String msg) {
// 登出动作回调
}
@Override
public void loginRoomNotify(LoginNotify loginRoomNotify, String msg) {
// 用户进入房间回调
}
@Override
public void logoutRoomNotify(LogoutNotify logoutRoomNotify, String msg) {
// 用户离开房间回调
}
@Override
public void onReceive(VideoStreamInfo videoStreamInfo) {
}
@Override
public void onSend(boolean status, int msgCode, Object msg) {
}
@Override
public void onMicList(List<MicInfo> userMicList) {
// 查询麦上所有人回调
}
};
// 观察 Voip 监听器
CLVideoLib.getInstance().observeVoipListener(voipListener, true);
CLVideoLib.getInstance().login(true,false);
销毁时移除监听回调
// 移除 Voip 监听器
CLVideoLib.getInstance().observeVoipListener(voipListener, false);
CLVideoLib.getInstance().onDestroy();
// 设置您是否为呼出方 callOut == true 为呼出方, callOut == false 则为接收方
// 如果是游戏房间创建者 callOut = true 其他用户进入房间的 callOut = false
// Param2 是否是实时视频
CLVideoLib.getInstance().login(callOut, false);
CLVideoLib.getInstance().logout();
// 初始化之后,设置此方法才有效的
// 音量等级监听
CLVoiceLib.getInstance().setVolumeCallback(new VolumeCallback() {
@Override
public void onVolumeLevel(String userId, int level) {
}
});
// 音量大小监听
CLVoiceLib.getInstance().setVolumeSizeCallback(new VolumeSizeCallback() {
@Override
public void onVolumeLevel(String userId, float volume) {
}
});
// 开始拉取音频流接口
CLVoiceLib.getInstance().startPull();
// 开始推送音频流接口
CLVoiceLib.getInstance().startPush();
// 停止拉取音频流接口
CLVoiceLib.getInstance().stoptPull();
// 停止拉取某人音频流接口
CLVoiceLib.getInstance().stopPull(userId);
// 停止推送音频流接口
CLVoiceLib.getInstance().stopPush();
// @param userId 您要调整的麦上人的接收的声音
// @param volume 声音大小,最大值为 1, 当设置 0 是则为静音
CLVoiceLib.getInstance().adjustUserVolume(userId, volume);
// 上麦接口
CLVideoLib.getInstance().micActionUp();
// 下麦接口
CLVideoLib.getInstance().micActionDown();
CLVideoLib.getInstance().queryMicList();
// 设置查询麦上所有人监听
@Override
public void onMicList(List<MicInfo> userMicList) {
StringBuilder micUp = new StringBuilder();
for (MicInfo userMicInfo : userMicList) {
if (VoiceConstant.MIC_TYPE_UP == userMicInfo.getMicStatus()) {
micUp.append(userMicInfo.getUserId());
micUp.append(":");
if (!userList.contains(userMicInfo.getUserId())) {
userList.add(userMicInfo.getUserId());
}
}
}
if (micUp.toString().length() > 0) {
micUp.append("在麦上");
MLog.i(micUp.toString());
print(micUp.toString());
} else {
print("无人上麦");
}
}
String audioPath = "";
// 当前 Activity 布局文件的 rootView
ConstraintLayout rootLayout = findViewById(R.id.root_view);
// 录音按钮
Button audioButton = findViewById(R.id.btn_record);
// 用于显示录音音频路径
TextView tvAudioPath = findViewById(R.id.tv_audio_path);
// 录音功能初始化
AudioRecorderPanel audioRecorderPanel= new AudioRecorderPanel(context);
// 设置录音最大时长
audioRecorderPanel.setMaxDuration(60);//60秒
// 将 AudioorderPanel 附加到 button 上
audioRecorderPanel.attach(rootLayout, audioButton);
audioRecorderPanel.setRecordListener(new AudioRecorderPanel.OnRecordListener(){
@Override
public boolean onEnableRecord() {
return true;
}
// audioFile 音频文件路径
// duration 音频时长
@Override
public void onRecordSuccess(String audioFile, int duration) {
audioPath = s;
tvAudioPath.setText(audioPath);
}
@Override
public void onRecordFail(String s) {
}
// 开始录音 START
// 录音中 RECORDING
// 用户准备取消 TO_CANCEL,
// 最长录音时间快到 TO_TIMEOUT,
@Override
public void onRecordStateChanged(AudioRecorderPanel.RecordState recordState) {
}
});
// 播放录音按钮
Button playAudioButton = findViewById(R.id.btn_play_record);
playAudioButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Param1:context 上下文
// Param2:audioPath 录音操作时保存的音频路径
AudioPlayManager.getInstance().startPlay(context, audioPath, new IAudioPlayListener(){
@Override
public void onStart(String s) {
}
@Override
public void onStop(String s) {
}
@Override
public void onComplete(String s) {
}
});
}
});
// 视频初始化信息
private VoipInitInfo info = new VoipInitInfo();
info.setAppId(xxx);
info.setRoomId(xxx);
info.setUserId(xxx);
//BusinessDataStorage.getInstance().getAppToken(); IM登录成功后这样获取token
info.setAppToken(xxx);
info.setRoomSecret(xxx);
// 视频模块构造器
CLVideoLib.Builder videoBuilder = CLVideoLib.create();
videoBuilder.builder(context, "您的APPID");
// 设置 IP 地址 私有化部署可以需要设置
// CLVoiceLib.getInstance().setTcpHost("xxx.xxx.xxx.xxx");
// 设置端口号
// CLVoiceLib.getInstance().setTcpPort(xxxx);
// 初始化视频模块
CLVideoLib.getInstance().init(videoBuilder);
// 初始化房间信息
CLVideoLib.getInstance().initRoomParam(info);
VoipListener voipListener = new VoipListener(){
@Override
public void initSuccess() {
}
@Override
public void initError(String msg) {
}
@Override
public void messageError(int errorCode, Object errorInfo) {
}
@Override
public void micAction(boolean isUp) {
}
@Override
public void loginAction(boolean success, String msg) {
}
@Override
public void logoutAction(boolean success, String msg) {
}
@Override
public void loginRoomNotify(LoginNotify loginRoomNotify, String msg) {
}
@Override
public void logoutRoomNotify(LogoutNotify logoutRoomNotify, String msg) {
}
@Override
public void onReceive(VideoStreamInfo videoStreamInfo) {
if (videoStreamInfo.getData() != null) {
Log.d("VideoActivity", "onReceive length=" + videoStreamInfo.getData().length);
// 此处将数据流转码后更新到您自己的组件即可,详情请看视频流解码
PlayerSurfaceView.decodeH264(videoStreamInfo.getData());
}
}
@Override
public void onSend(boolean status, int msgCode, Object msg) {
}
@Override
public void onMicList(List<MicInfo> userMicList) {
}
};
CLVideoLib.getInstance().observeVoipListener(voipListener, true)
// RecordSurfaceView 是我们提供给您的, 若您不想使用我们提供的可以自定义 SurfaceView
RecordSurfaceView.initCamera(context, null, true, CLVideoProfile.VIDEO_PROFILE_HD1080P);
销毁时移除监听回调:
CLVideoLib.getInstance().observeVoipListener(voipListener, false)
CLVideoLib.getInstance().onDestroy();
// 设置您是否为呼出方 callOut == true 为呼出方, callOut == false 则为接收方
// Param2 是否是实时视频
CLVideoLib.getInstance().login(callOut, true);
CLVideoLib.getInstance().logout();
VIDEO_PROFILE_LOWEST(0), //分辨率 160x90 码率 120k
VIDEO_PROFILE_LOW(1), //分辨率 480x270 码率 525k
VIDEO_PROFILE_STANDARD(2), //分辨率 640x360 码率 900k
VIDEO_PROFILE_HD720P(3), //分辨率 1280x720 码率 1300k
public class YourSurfaceView extends SurfaceView implements SurfaceHolder.Callback,
H264Encoder.H264DataListener{
private H264Encoder h264Encoder = null;
private int frameCount = 0;
private Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// 此处为判断您的相机是否打开
if (isCameraOpen) {
handlePreviewFrame(data);
}
}
};
private void handlePreviewFrame(byte[] data) {
if (h264Encoder != null) {
frameCount++;
h264Encoder.onFrame(data);
}
}
private void init(Context context){
SurfaceHolder holder = this.getHolder();
if (holder != null) {
holder.addCallback(this);
}
}
public YourSurfaceView(@NonNull Context context) {
super(context);
}
public YourSurfaceView(@NonNull Context context, AttributeSet attrs) {
super(context, attrs);
}
public YourSurfaceView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
h264Encoder = new H264Encoder(this);
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
if (h264Encoder != null) {
h264Encoder.close();
h264Encoder = null;
}
}
@Override
public void h264Data(byte[] buffer, int length) {
// 此处为视频推流接口
CLVideoLib.getInstance().sendVideoStream(buffer, frameCount, 0);
}
}
public class PlayerSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
public PlayerSurfaceView(Context context) {
super(context);
init(context);
}
public PlayerSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private H264Decoder h264Decoder;
private void init(Context context){
this.getHolder().addCallback(this);
}
public void decodeH264(byte[] h264) {
if (h264 == null || h264Decoder == null) {
return;
}
h264Decoder.decodeH264(h264);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
h264Decoder = new H264Decoder(this.getWidth(), this.getHeight(), this.getHolder());
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (h264Decoder!=null){
h264Decoder.stopCodec();
}
}
}
发布日期 | 发布版本 | 更新说明 |
---|---|---|
2021-02-18 | V1.0.0 | 初版发布 |