版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.07.21 |
前言
以前做过移动直播项目,做直播的推流和拉流用的是乐视的移动直播业务,集成乐视的移动业务的SDK。前面已经对乐视移动直播进行了简单的介绍,感兴趣的可以看下。这一篇主要讲一下乐视云直播遇到的坑和不方便之处。
1.乐视移动直播的集成(一)
2.乐视移动直播的集成(二)
遇到的几个坑
在用乐视云直播的时候,碰到了几个坑,使用起来不是很顺手,主要包括两个方面。
- sdk在预览时的屏幕方向,就是推流方向,不支持随意改变方向。
- 从云直播后台观看推流不是很稳定,拉流也是。
- app进入后台,稍后从后台转到前台,乐视的sdk不能继续推流,需要app端做额外的逻辑处理,不支持后台推流。
解决问题的方法
1.屏幕预览方向的问题
由于sdk的局限性,我就不能用sdk的预览功能了,最后预览用的是本地的相机,可以横竖屏预览,当开始直播的时候在调用sdk的预览视图并开始直播
推流。
下面我们看一下调用本地相机实现预览功能的代码。
//调起本地相机
[self addLocaleCamera];
//打开本地相机开始预览
- (void)addLocaleCamera
{
AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
self.captureSession = captureSession;
if ([captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;
}
else {
self.captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
}
NSArray *deviceArr = [AVCaptureDevice devices];
NSError *error;
for (AVCaptureDevice *device in deviceArr) {
if ([device hasMediaType:AVMediaTypeVideo]) {
if ([device position] == AVCaptureDevicePositionFront) {
AVCaptureDeviceInput *inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if ([self.captureSession canAddInput:inputDevice]) {
[self.captureSession addInput:inputDevice];
}
}
}
}
AVCaptureMovieFileOutput *captureMovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
self.captureMovieFileOutput = captureMovieFileOutput;
if ([self.captureSession canAddOutput:captureMovieFileOutput]) {
[self.captureSession addOutput:captureMovieFileOutput];
}
self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
self.captureVideoPreviewLayer.frame = self.view.bounds;
self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.captureVideoPreviewLayer.masksToBounds = YES;
[self.view.layer addSublayer:self.captureVideoPreviewLayer];
AVCaptureConnection *captureConnection = [self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
self.captureConnection = captureConnection;
captureConnection.videoOrientation = [self.captureVideoPreviewLayer connection].videoOrientation;
[self.captureSession startRunning];
}
监听屏幕旋转通知,并旋转预览视图。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientDidChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
- (void)orientDidChanged:(NSNotification *)noti
{
UIDeviceOrientation orient = [UIDevice currentDevice].orientation;
self.captureVideoPreviewLayer.frame = self.view.frame;
AVCaptureConnection *connection = [self.captureVideoPreviewLayer connection];
NSLog(@"%ld",orient);
if (orient == UIDeviceOrientationPortrait || orient == UIDeviceOrientationPortraitUpsideDown) {
NSLog(@"竖屏");
connection.videoOrientation = AVCaptureVideoOrientationPortrait;
//设置竖屏视图
[self setupUnstartPortraitView];
}
else if(orient == UIDeviceOrientationLandscapeLeft){
NSLog(@"横屏");
connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
[self setupUnstartLandscapeView];
}
else if(orient == UIDeviceOrientationLandscapeRight){
NSLog(@"横屏");
connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
[self setupUnstartLandscapeView];
}
}
2. 推流拉流不稳定
主播端进行推流,在乐视云直播后台预览直播的时候,可以看见总是会有流不稳定的情况,在确定网络和APP端没有错误的情况下,可以确定是乐视的问题,推流和拉流不稳定,有时候拉流也会变的好一点。
3.后台不支持推流问题
前面已经说过,乐视不支持app推入后台继续推流,因此需要客户端进行额外的逻辑处理,主要包含一下几个情况。
- 节目没开始,预览视图回到前台继续预览。
- 直播中时,从后台进入前台,继续推流。
方案就是在后台进前台,还有前台进后台的通知响应方法里面做相关的逻辑处理,下面看代码。
//通知监听
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidActive) name:kApplicationDidBecomeActive object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground) name:kApplicationDidEnterBackground object:nil];
//后台进入前台重新开始推流
- (void)applicationDidActive
{
if ([self.pushManager videoView]) {
[[self.pushManager videoView] removeFromSuperview];
self.pushManager.manager = nil;
//重新创建推流管理类
[self createPushManager];
//重新加预览视图
[self.view addSubview:[self.pushManager videoView]];
[self.view bringSubviewToFront:self.startPortraitView];
}
//开始推流
[self beginPush];
//继续预览
if (self.captureSession) {
[self.captureSession startRunning];
}
}
//开始推流
- (void)beginPush
{
self.pushManager.pushURLStr = self.livePushAddressStr;
}
- (void)createPushManager
{
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
self.pushManager = [[ZBPushManager alloc] initWithIsPortrait:1];
self.delegate.allowRotation = 100;
}
else {
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
self.pushManager = [[ZBPushManager alloc] initWithIsPortrait:2];
self.delegate.allowRotation = 2;
}
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
self.pushManager = [[ZBPushManager alloc] initWithIsPortrait:3];
self.delegate.allowRotation = 3;
}
}
}
//前台进入后台
- (void)applicationDidEnterBackground
{
//停止推流
[self.pushManager stopPush];
//停止预览
if (self.captureSession) {
[self.captureSession stopRunning];
}
}
这里还需要注意:由于app内部有分享功能,当分享到第三方平台并且由后台进入前台时,也要走这两个方法,所以需要有个标志位。
self.isShare = YES
并且在后台进前台,还有前台进后台的通知响应方法里面,利用这个属性进行事件流的控制,具体代码就不给出了,还是很简单的。
后记
未完,待续~~~