iOS开源&高仿项目精选奔跑吧 iOSRTMP视频连线互动

高仿映客(iOS)

2016-12-28  本文已影响945人  余生丶91

下载地址:

高仿映客

开发工具:Xcode8 真机上运行,模拟器会报错

开发语言:Objective-C
SDK:RTMPCHybridEngine-IOS

实现:模仿映客,包含推流、拉流、连麦、弹幕、美颜、发礼物等。

效果图:

热门.png 附近.jpg 个人中心.png 搜索.jpg 游客端(直播).jpg 送礼物.jpg 弹框.jpg 主播端(直播).jpg

Gif效果图:

主界面.gif 直播间.gif 送礼物.gif 连麦.gif

比较

RTMPCHybridEngine是为移动端应用量身打造的基于RTMP和RTC混合引擎的连麦互动流媒体直播系统。通过集成本SDK,只需几个简单API调用,便可实现一套完整的连线麦互动直播流媒体应用。包含了流媒体应用中:『采集->编码->传输->解码->播放->连麦视频互动』的所有步骤。

AnyRTC云通讯创新性实现了RTMP+RTC的技术融合,使用RTC技术实现基于标准的RTMP协议的互动连线视频直播,在视频处理,音频降噪,码率控制,硬件加速,美颜滤镜,实时通讯,移动端性能等方面性能优越。

优势:

注意事项:

1、直播间页面为香港卫视rtmp数据(当有两台设备可实现适时直播);

2、演示推流、拉流、连麦至少需要两部iPhone手机;

3、一部手机进入直播页面点击开启直播,开启显示成功后,另一部手机在热门列表下拉刷新,点击列表进入直播间页面。

4、成功后游客端点击左上方连麦按钮,同意后进行连麦。

项目结构:

结构.png

常见问题:

1、无法推流、拉流、连麦->AppDelegate配置SDK失效->官方文档

2、SDK接入需要添加网络权限、访问相机、麦克风权限;
3、可能遇到的问题:

ld: library not found for -XXX
clang: error: linker command failed with exit code 1 (use -v to see invocation)

解决:Build Settings->Other Linker Flags->删除XXX

4、 ios Undefined symbols for architecture arm64
解决

5、使用SDWebImage内存暴增解决办法

开发过程:

准备工作:项目中图片资源通过PP助手获取映客ipa包,接口数据通过抓包工具获得。

SDK集成:项目主要依赖RTMPC SDK 具体请参考官方SDK文档

Code:

++++++++++++游客端拉流、连麦的实现++++++++++++

- (void)repareStartPlay{
    //初始化
    self.guestKit = [[RTMPCGuestKit alloc] initWithDelegate:self withCaptureDevicePosition:RTMPC_SCRN_Portrait withLivingAudioOnly:NO];
    
    
    //只支持rtmp流
    if (!self.livingItem) {
        //假数据  rtmp://live.hkstv.hk.lxdns.com/live/hks
         [self.guestKit StartRtmpPlay:@"rtmp://live.hkstv.hk.lxdns.com/live/hks" andRender:self.showView];
    } else{
        //如果有两部手机运行,且创建项目,可实现实时推流、拉流
        [self.guestKit StartRtmpPlay:self.livingItem.rtmp_url andRender:self.showView];
    }
    
//    [self.guestKit StartRtmpPlay:self.adressStr andRender:self.showView];
//    [self.guestKit setVideoContentMode:VideoShowModeScaleAspectFill];

}

//游客端RTC连麦
- (void)prepareRtc{
    self.guestKit.rtc_delegate = self;
    
    NSString *strUrl = [NSString stringWithFormat:@"http://img2.inke.cn/MTQ4MTI4NTI4NTMxMyMzNjYjanBn.jpg"];
    
    NSDictionary *customDict = [NSDictionary dictionaryWithObjectsAndKeys:@"AnyRTC",@"nickName",strUrl,@"headUrl" ,nil];
    NSString *customStr = [self JSONTOString:customDict];
    
    //当andyrtcId为空,假数据,RTC连麦失败
    [self.guestKit JoinRTCLine:self.livingItem.andyrtcId andCustomID:@"游客A" andUserData:customStr];
}

++++++++++++主播端推流、连麦的实现++++++++++++

#pragma 推流
- (void)prepareStream{
    //初始化主播端  推流代理
    self.hosterKit = [[RTMPCHosterKit alloc]initWithDelegate:self withCaptureDevicePosition:RTMPC_SCRN_Portrait withLivingAudioOnly:NO];
    //推流模式
    [self.hosterKit SetNetAdjustMode:RTMP_NA_Fast];
    [self.hosterKit SetVideoCapturer:self.view andUseFront:YES];
    [self.hosterKit SetBeautyEnable:YES];
    //推流质量
    [self.hosterKit SetVideoMode:RTMPC_Video_SD];
}

//rtc连麦
- (void)prepareRtc{
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"hostID",@"hosterId",self.rtmpUrl,@"rtmp_url",self.hlsUrl,@"hls_url",self.livingName?self.livingName:[self getTopName],@"topic",self.randomStr,@"anyrtcId",[NSNumber numberWithBool:_isAudioLiving],@"isAudioOnly", nil];
    NSString *jsonString = [self JSONTOString:dict];
    //rtc的代理
    self.hosterKit.rtc_delegate = self;
    //打开RTC连麦功能
    [self.hosterKit OpenRTCLine:self.randomStr andCustomID:@"主播端" andUserData:jsonString andRtcArea:@"CN"];
}

NearbyController 使用SDWebImage内存暴增

static BOOL SDImageCacheOldShouldDecompressImages = YES;
static BOOL SDImagedownloderOldShouldDecompressImages = YES;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    index = 0;
     [self.view addSubview:self.nearCollectView];
    [self.locationManager startUpdatingLocation];
    self.view.backgroundColor = [UIColor whiteColor];
    
    SDImageCache *canche = [SDImageCache sharedImageCache];
    SDImageCacheOldShouldDecompressImages = canche.shouldDecompressImages;
    canche.shouldDecompressImages = NO;
    //保存原设置,禁用解压缩
    SDWebImageDownloader *downloder = [SDWebImageDownloader sharedDownloader];
    SDImagedownloderOldShouldDecompressImages = downloder.shouldDecompressImages;
    downloder.shouldDecompressImages = NO;
}

- (void)dealloc{
    self.nearCollectView.dataSource = nil;
    self.nearCollectView.delegate = nil;
    self.locationManager.delegate = nil;
    
    //恢复原设置
    SDImageCache *canche = [SDImageCache sharedImageCache];
    canche.shouldDecompressImages = SDImageCacheOldShouldDecompressImages;
    
    SDWebImageDownloader *downloder = [SDWebImageDownloader sharedDownloader];
    downloder.shouldDecompressImages = SDImagedownloderOldShouldDecompressImages;
}

搜索页长按图像动画的实现:

//长按
- (void)longPressClick:(UILongPressGestureRecognizer *)sender{
    NSInteger tag = [sender view].tag;
    if (sender.state == UIGestureRecognizerStateBegan) {
        [UIView animateWithDuration:0.5 animations:^{
            switch (tag) {
                case 50:
                    self.imageViewF.transform = CGAffineTransformMakeScale(0.8, 0.8);
                    break;
                case 51:
                    self.imageViewS.transform = CGAffineTransformMakeScale(0.8, 0.8);
                    break;
                case 52:
                    self.imageViewT.transform = CGAffineTransformMakeScale(0.8, 0.8);
                    break;
                default:
                    break;
            }
        }];
    } else if (sender.state == UIGestureRecognizerStateEnded) {
        [UIView animateWithDuration:0.5 animations:^{
            self.imageViewF.transform = CGAffineTransformMakeScale(1.0, 1.0);
            self.imageViewS.transform = CGAffineTransformMakeScale(1.0, 1.0);
            self.imageViewT.transform = CGAffineTransformMakeScale(1.0, 1.0);
        }];
    }
}

+++++++++++++++部分动画的实现+++++++++++++++

弹框实现 CameraView

    //关键帧  damp阻尼
    [UIView animateWithDuration:0.8 delay:0.1 usingSpringWithDamping:0.6 initialSpringVelocity:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
        _liveButton.frame = CGRectMake(0, LiveGetY, LiveWidth, LiveWidth);
    } completion:^(BOOL finished) {

    }];

附近动画NearbyController

- (void)showAnimation{
    self.iconImageView.layer.transform = CATransform3DMakeScale(0.1, 0.1, 1);
    [UIView animateWithDuration:0.25 animations:^{
        self.iconImageView.layer.transform = CATransform3DMakeScale(1, 1, 1);
    }];
}

进入主播页动画CameraViewController:

- (void)viewWillAppear:(BOOL)animated{
    //由小变大的圆形动画
    CGFloat radius = [UIScreen mainScreen].bounds.size.height;
    UIBezierPath *startMask =  [UIBezierPath bezierPathWithOvalInRect:CGRectMake(self.view.centerX, self.view.centerY, 0, 0)];
    UIBezierPath *endMask = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(CGRectMake(self.view.centerX, self.view.centerY, 0, 0), -radius, -radius)];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = endMask.CGPath;
    maskLayer.backgroundColor = (__bridge CGColorRef)([UIColor whiteColor]);
    CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    maskLayerAnimation.fromValue = (__bridge id)(startMask.CGPath);
    maskLayerAnimation.toValue = (__bridge id)((endMask.CGPath));
    maskLayerAnimation.duration = 0.8f;
    [maskLayer addAnimation:maskLayerAnimation forKey:@"path"];
    self.view.layer.mask = maskLayer;
}

声明

本项目仅供学习,侵权立删!

总结

第一次仿写直播项目,希望能帮到有需要的朋友,之前也没接触过直播类的项目,写的不好的地方见谅!项目中发现什么问题@我或者私信我,大家一起交流学习,有时间会修复项目中的BUG,有时间更新。

参考

RTMPC

仿映客刷礼物效果---基本逻辑实现

直播类送礼动画<豪华礼物+小礼物>

上一篇下一篇

猜你喜欢

热点阅读