LSS推流功能简介:
-推流 是指将音视频数据采集的数据编码成H264格式之后推送到指定的云平台上
推流功能:
1 VHLivePusher
1.1 VHLivePushConfig 参数类
VHLivePushConfig是推流功能的配置类,也是推流的核心类之一,这个类决定了你推流时一些必备的参数,如视频流的宽高、帧率、码率、编码类型、推流类型等。传递一个分辨率并创建VHLivePushConfig类 。 分辨率定义如下:
推流分辨率定义 | 描述 |
---|---|
VHLivePushFormat.PUSH_MODE_SD | 低清分辨率 352 * 288 |
VHLivePushFormat.PUSH_MODE_HD | 普清分辨率 640 * 480 |
VHLivePushFormat.PUSH_MODE_XHD | 高清分辨率 960 * 540 |
VHLivePushFormat.PUSH_MODE_XXHD | 超清分辨率 1280 * 720 |
config = new VHLivePushConfig(VHLivePushFormat.PUSH_MODE_HD); //
config.screenOri = VHLivePushFormat.SCREEN_ORI_PORTRAIT //指定推流横竖屏设置 , 很重要
VHLivePushConfig 参数配置 以下是VHLivePushConfig的默认配置,如果需要修改,只需要调用相应的参数重新赋值即可
VHLivePushConfig参数 | 默认值 | 描述 |
---|---|---|
screenOri | VHLivePushFormat.SCREEN_ORI_LANDSPACE | 推流横竖屏 |
videoFrameRate | 15 | 视频帧率 |
videoBitrate | 400 * 1000 | 视频码率 |
pushTimeout | 5 * 1000 | 推流超时 |
pushReconnectTimes | 5 | 推流重连次数 |
encodeColorFormat | VHLivePushFormat.ENCODE_COLOR_FORMAT_YUV420SP_NV21 | 采集的颜色空间 |
streamMode | VHLivePushFormat.STREAM_MODE_RTMP | 推流协议 |
encodeType | VHLivePushFormat.ENCODE_TYPE_SOFT | 编码方式 |
1.2 初始化音视频采集器
VHVideoCaptureView 是SDK提供的一个视频采集View,VHVideoCaptureView主要操作Camera,完成推流的采集工作和对摄像头的Api调用。需要先在XML中引用View,听过FindView获取采集器的实例。VHAudioCapture 是SDK提供的音频采集类,直接初始化调用
//初始化音视频采集器
videoCapture = (VHVideoCaptureView) this.findViewById(R.id.videoCaptureView);
audioCapture = new VHAudioCapture();
1.3 初始化VHLivePusher
VHLivePusher 是发起推流的核心对象,创建时传递的参数是,视频采集器,音频采集器和VHLivePushConfig,其实就是将1.1到1.3创建对象的实例传入进去。添加监听也在此时配置,监听的描述请看,到这里初始化的操作就完成了
pusher = new VHLivePusher(videoCapture, audioCapture, config);
pusher.addListener(new MyListener());
当初始化工作完成后,就可以调用API的功能了
2: 开始推流
当一切就绪时,调用start()开始推流,此方法需要传入房间号roomId和有效的Token,这些参数在调用Api前获取,调用Start()后,如果想要了解推流的状态可以从监听中获取
/**
@param = roomId; //标识当前的房间号
@param = accessToken; // 发起的Token
*/
void start(String roomId,String accessToken);
3: 切换前置或后置摄像头
顺序切换下一个摄像头,返回摄像头ID , 默认使用后置摄像头(注意 一定要将摄像头的权限打开)
int switchCamera();
4: 指定打开哪个摄像头
返回摄像头ID (注意 一定要将摄像头的权限打开)
int changeCamera(int cameraId);
5: 切换闪光灯
返回闪光灯打开状态 , 只有在后置的摄像头才能打开闪光灯
boolean changeFlash(boolean flash);
6: 获取当前直播状态
获取直播时的状态,也可以根据监听获取状态
Status getStatus();
enum Status {
IDEL,STARTED, STOPED, END
}
状态 | 描述 |
---|---|
IDEL | 闲置状态 ,默认状态 |
STARTED | 运行状态 |
STOPED | 停止状态 |
END | 结束状态 |
7: 暂停直播 / 恢复直播
调用后推流会暂停,采集工作也会停止,根据应用场景调用 ,调用后推流重新连接,采集工作重新开始,根据应用场景调用
void pause();
void resume();
8: 聚焦坐标
void focus(int x, int y);
9: 设置缩放比例
void setZoom(int level);
10: 设置view内手势是否可用(聚焦和变焦)
videoCaptureView内部实现了手势聚焦和变焦,如果不需要手势,可设置false,自行调用focus和zoom接口
void setGestureEnable(boolean enable);
11: 设置摄像头预览模式
void setCameraDrawMode(int mode);
预览模式 | 参数 |
---|---|
VHLivePushFormat.DRAW_MODE_ASPECTFILL | 将图像等比例铺满整个屏幕,多余部分裁剪掉,此模式下画面不会留黑边,但可能因为部分区域被裁剪而显示不全 |
VHLivePushFormat.DRAW_MODE_ASPECTFIT | 将图像等比例缩放,适配最长边,缩放后的宽和高都不会超过显示区域,居中显示,画面可能会留有黑边 |
VHLivePushFormat.DRAW_MODE_NONE | 默认 |
12: 结束直播
当调用stop()方法时,内部的请求地址会置空,当重新发起推流会重新获取推流地址
void stop();
13:销毁
此方法会销毁当前已经初始化的视频采集器和音频采集器,如果需要再次使用需要重新初始化直播器
void release();
事件处理 VHPushLiveListener 监听
在构建推流器的时候添加监听,用户根据监听回调的事件可以进行相应的处理,详细信息请查看Demo ,此处只做简单描述
错误码 | 描述 |
---|---|
VHLivePusher.ERROR_PUSH | 推送过程出错 |
VHLivePusher.ERROR_AUDIO_CAPTURE | 音频采集过程出错 |
VHLivePusher.ERROR_VIDEO_CAPTURE | 视频采集过程出错 |
直播事件 | 描述 |
---|---|
VHLivePusher.EVENT_STATUS_STARTING | 开始推流 |
VHLivePusher.EVENT_STATUS_STARTED | 推流成功 |
VHLivePusher.EVENT_STATUS_STOPED | 推流停止 |
VHLivePusher.EVENT_UPLOAD_SPEED | 下载速度 |
Demo示例:
public class PushActivity extends Activity {
VHVideoCaptureView videoCapture;
IVHCapture audioCapture;
VHLivePusher pusher;
VHLivePushConfig config;
//status info
boolean isFlashOpen = false;
int mCameraId = 0;
boolean isAudioEnable = true;
boolean isPushing = false;
int mDrawMode = VHLivePushFormat.DRAW_MODE_NONE;
//view
TextView mSpeedView;
ProgressBar mLoadingView;
ImageView mPushBtn;
private String roomId = "";
private String accessToken = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
roomId = getIntent().getStringExtra("roomid");
accessToken =getIntent().getStringExtra("token");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.push_layout);
//initview
mSpeedView = (TextView) this.findViewById(R.id.tv_speed);
mLoadingView = (ProgressBar) this.findViewById(R.id.pb_loading);
mPushBtn = (ImageView) this.findViewById(R.id.btn_push);
//配置发直播系列参数
config = new VHLivePushConfig(VHLivePushFormat.PUSH_MODE_HD);
config.screenOri = VHLivePushFormat.SCREEN_ORI_PORTRAIT;//横竖屏设置 重要
//初始化音视频采集器
videoCapture = (VHVideoCaptureView) this.findViewById(R.id.videoCaptureView);
audioCapture = new VHAudioCapture();
//初始化直播器
pusher = new VHLivePusher(videoCapture, audioCapture, config);
pusher.addListener(new MyListener());
}
@Override
protected void onPause() {
super.onPause();
if (pusher.getStatus() == IVHLivePusher.Status.STARTED) {
pusher.pause();
mPushBtn.setImageResource(R.mipmap.icon_start_bro);
}
}
@Override
protected void onResume() {
super.onResume();
if (pusher.resumeAble())
pusher.resume();
}
@Override
protected void onDestroy() {
super.onDestroy();
pusher.release();
}
public void push(View view) {
if (isPushing) {
pusher.stop();
mPushBtn.setImageResource(R.mipmap.icon_start_bro);
} else {
if (pusher.resumeAble())
pusher.resume();
else
pusher.start(roomId, accessToken);
mPushBtn.setImageResource(R.mipmap.icon_pause_bro);
}
}
public void changeFlash(View view) {
isFlashOpen = videoCapture.changeFlash(!isFlashOpen);
}
public void changeCamera(View view) {
mCameraId = videoCapture.switchCamera();
}
public void changeFilter(View view) {
int level = (++mBeautyLevel) % 6;
if (level == 0)
videoCapture.setFilter(null);
else {
videoCapture.setFilter(new VHBeautyFilter());
videoCapture.setBeautyLevel(level);
}
Toast.makeText(this, "level:" + level, Toast.LENGTH_SHORT).show();
}
public void switchAudio(View view) {
isAudioEnable = audioCapture.setEnable(!isAudioEnable);
}
public void changeMode(View view) {
switch (mDrawMode) {
case VHLivePushFormat.DRAW_MODE_NONE:
mDrawMode = VHLivePushFormat.DRAW_MODE_ASPECTFILL;
break;
case VHLivePushFormat.DRAW_MODE_ASPECTFILL:
mDrawMode = VHLivePushFormat.DRAW_MODE_ASPECTFIT;
break;
case VHLivePushFormat.DRAW_MODE_ASPECTFIT:
mDrawMode = VHLivePushFormat.DRAW_MODE_NONE;
break;
}
videoCapture.setCameraDrawMode(mDrawMode);
}
class MyListener implements VHPushLiveListener {
@Override
public void onError(int errorCode, int innerErrorCode) {
mLoadingView.setVisibility(View.GONE);
switch (errorCode) {
case VHLivePusher.ERROR_PUSH://推送过程出错
break;
case VHLivePusher.ERROR_AUDIO_CAPTURE://音频采集过程出错
break;
case VHLivePusher.ERROR_VIDEO_CAPTURE://视频采集过程出错
break;
}
Toast.makeText(PushActivity.this, "push error,errorCode:" + errorCode + ",innerCode:" + innerErrorCode, Toast.LENGTH_SHORT).show();
}
@Override
public void onEvent(int eventCode, String eventMsg) {
switch (eventCode) {
case VHLivePusher.EVENT_STATUS_STARTING:
mLoadingView.setVisibility(View.VISIBLE);
break;
case VHLivePusher.EVENT_STATUS_STARTED:
mLoadingView.setVisibility(View.GONE);
isPushing = true;
break;
case VHLivePusher.EVENT_STATUS_STOPED:
mLoadingView.setVisibility(View.GONE);
isPushing = false;
break;
case VHLivePusher.EVENT_UPLOAD_SPEED:
mSpeedView.setText(eventMsg + "kbps");
break;
}
}
}
}