手把手教你视频直播开发

#pragma mark viewDidLoad
- (void)viewDidLoad {
    [super viewDidLoad];

    self.liveRoomVC = LiveRoomVC_LiveRoomViewController;
    self.isTouchHomeEd = NO;
    NSLog(@"!!!%ld",(long)self.staruserid);

    [AppDelegate shareAppDelegate].isNeedReturnLiveRoom = YES;

    // Do any additional setup after loading the view.

    [self initGeneralView];  //初始化scrollView以及loadingView

    //    主播信息
    UserInfo *userInfo = [UserInfoManager shareUserInfoManager].currentUserInfo;
    if (self.staruserid > 0)//主播id
    {
        if (userInfo == nil)//游客的情况
        {
            [self initUserView];//顶部正在直播和退出
            [self initToolBar];//初始化聊天界面
        }
        else if (userInfo.userId == self.staruserid && [AppDelegate shareAppDelegate].isSelfWillLive)//主播id和用户id一样
        {
            [self initStarView];//自己主播
        }
        else
        {
            [self initUserView];//看别人直播
            [self initToolBar];//初始化聊天界面
        }
    }

    [self initRoomSetting];//初始化房间定时等信息1.后台播放音频设置,2,进入之前先退出房间,关闭定时器,停止播放,断开TCP。加载loadView,初始化主播信息

    [[SeekuSingle shareSeekuSingle] lib_audioSession_initialize];//跟lib_audioSession_uninitialize是成对出现

}

//initGeneralView方法初始化scrollView以及loadingView(也就是主播界面元素)

#pragma mark - 加载显示视频的imageView 以及背景 ,loadingView
- (void)initGeneralView
{
    //音视频画布
    if ([self phoneLiving]) {

        _liveRoomIamgeView = [[LiveRoomIamgeView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        _liveRoomIamgeView.userInteractionEnabled = YES;
        [self.view addSubview:_liveRoomIamgeView];
        self.liveBg = [[UIImageView alloc] initWithFrame:_liveRoomIamgeView.bounds];
        self.liveBg.image = [UIImage imageNamed:@"liveBg"];
        [_liveRoomIamgeView addSubview:self.liveBg];

    }else{
        _videoImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        _videoImage.backgroundColor =  [UIColor colorWithPatternImage:[UIImage imageNamed:@"livrRoomPram"]];
        //    _videoImage.contentMode = UIViewContentModeScaleAspectFill;
        _videoImage.clipsToBounds = YES;
        [self.view addSubview:_videoImage];
        self.liveBg = [[UIImageView alloc] initWithFrame:_videoImage.bounds];
        self.liveBg.image = [UIImage imageNamed:@"liveBg"];
        [_videoImage addSubview:self.liveBg];
    }

    //加载loadingView
    _liveLoadingView  = [[LiveLoadingView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    [self.view addSubview:_liveLoadingView];

    //公聊区
    _middleView = [[LiveRoomMiddleView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) showInView:self.view];
    _middleView.rootViewController = self;
    _middleView.delegate = self;
    [self.view addSubview:_middleView];

    [LiveRoomHelper shareLiveRoomHelper].rootLiveRoomViewController = self;

    //头像列表
    _liveAudienceHeaderView = [[AudienceHeaderView alloc]initWithFrame:CGRectMake(SCREEN_WIDTH/2-10, 0+2, SCREEN_WIDTH -(SCREEN_WIDTH/2-10), 14+35) showInView:self.view];
    __weak typeof(self) weakself = self;
    _liveAudienceHeaderView.rootLiveRoomViewController = self;
    _liveAudienceHeaderView.audienceHeaderViewTouch = ^(UserInfo* userInfo){
        _userIdcount = userInfo.userId;
        [weakself userInfor:userInfo];
    };

    [self.view addSubview:_liveAudienceHeaderView];

    //底部栏
    _liveBottomView = [[LiveBottomView alloc]initView:CGRectMake(0, SCREEN_HEIGHT-35-10, SCREEN_WIDTH, 35+10) withType:[self phoneLiving]?BottomType_ZhuBo:BottomType_GuanZHong];
    _liveBottomView.userInteractionEnabled = YES;

    _liveBottomView.backgroundColor = [UIColor clearColor];

    __weak typeof(self) weakself1 = self;
    _liveBottomView.LiveBottomViewTouch = ^(NSInteger tag){

        if (tag==0) {//公聊

            [weakself1.chatToolBar.messageCotent becomeFirstResponder];
            weakself1.chatToolBar.typeKey = TypeKey_GONGLIAO;

        }else if (tag==1){//私聊

            if ([weakself1 showLoginDialog]){
                return ;
            }

            weakself1.chatToolBar.isPrivateChat = YES;
            [weakself1.priVateChatView changeFieldText];
            [weakself1.priVateChatView  hidPrivateChatViewWithisHid:NO];
            weakself1.chatToolBar.frame =  CGRectMake (0, SCREEN_HEIGHT-33 , SCREEN_WIDTH, 33);

        }else if (tag==2){//分享

            [weakself1.liveShareView hidSelfWithisHid:NO];

        }else if (tag==3){//礼物
            if (_liveBottomView.type == BottomType_ZhuBo) {//关闭
                [weakself1 liveEndDealog];
            }else {
                [weakself1 giftAction:nil];
            }

        }else if (tag==4){//关闭
            NSLog(@"右下角关闭按钮");
            [weakself1 autoExitRoom];

        }

    };
    [self.view addSubview:_liveBottomView];

    _liveShareView = [[LiveShareView alloc]initWithFrame:[self phoneLiving]?CGRectMake(SCREEN_WIDTH-10-(4-2)*(35+7)+7+35/2-103/2, SCREEN_HEIGHT-_liveBottomView.frameHeight-9-6-150/2, 103, 150/2+6):CGRectMake(SCREEN_WIDTH-10-(5-2)*(35+7)+7+35/2-103/2, SCREEN_HEIGHT-_liveBottomView.frameHeight-9-6-354/2, 103, 354/2+6) showInView:self.view];

    _liveShareView.rootLiveRoomViewController = self;
    [_liveShareView hidSelfWithisHid:YES];
    _liveShareView.liveShareViewTouche = ^(NSInteger tag){

#pragma mark 分享&相机设置
        if (tag==0) {//微信

            if (weakself.liveBottomView.type == BottomType_ZhuBo) {//闪光灯
                if (weakself.liveRoomIamgeView.isAVCaptureTorchModeOn) {
                    [weakself showNoticeInWindow:@"闪光灯已关闭" duration:1];
                    [weakself.liveRoomIamgeView setFlashMode:AVCaptureTorchModeOff];
                }else{

                    if (weakself.liveRoomIamgeView.isAVCaptureDevicePositionFront) {
                        [weakself showNoticeInWindow:@"当前摄像头不支持闪光灯" duration:1];
                        return ;
                    }
                    [weakself showNoticeInWindow:@"闪光灯已打开" duration:1];
                    [weakself.liveRoomIamgeView setFlashMode:AVCaptureTorchModeOn];
                }

            }else{
                [[LiveRoomHelper shareLiveRoomHelper] helperShareWithNumber:0 withShareTyep:@[UMShareToWechatSession] withParms:weakself1.headImageView.image];
            }

        }else if (tag==1){//朋友圈

            if (weakself.liveBottomView.type == BottomType_ZhuBo) {//翻转

                [weakself.liveRoomIamgeView rotateCamera];

            }else{
                [[LiveRoomHelper shareLiveRoomHelper] helperShareWithNumber:0 withShareTyep:@[UMShareToWechatTimeline] withParms:weakself1.headImageView.image];
            }

        }else if (tag==2){//QQ
            [[LiveRoomHelper shareLiveRoomHelper] helperShareWithNumber:0 withShareTyep:@[UMShareToQQ] withParms:weakself1.headImageView.image];
        }else if (tag==3){//QQ空间
            [[LiveRoomHelper shareLiveRoomHelper] helperShareWithNumber:0 withShareTyep:@[UMShareToQzone] withParms:weakself1.headImageView.image];
        }else if (tag==4){//微博

            [[LiveRoomHelper shareLiveRoomHelper] helperShareWithNumber:0 withShareTyep:@[UMShareToSina] withParms:weakself1.headImageView.image];
        }

    };
    [self.view addSubview:_liveShareView];

    _priVateChatView = [[PrivateChatView alloc]initWithFrame:CGRectMake(0, SCREEN_HEIGHT-570/2, SCREEN_WIDTH, 570/2) showInView:self.view];
    [_priVateChatView hidPrivateChatViewWithisHid:YES];
    _priVateChatView.rootLiveRoomViewController = self;
    [self.view addSubview:_priVateChatView];
    [self.view bringSubviewToFront:self.chatToolBar];

    [self initStatusView];   //顶部赞个观众

    _liveEndView = [[LiveEndView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    _liveEndView.rootLiveRoomController = self;
    _liveEndView.hidden = YES;
    [self.view addSubview:_liveEndView];

    [self hidLiveRoomBeforLiveViewHid:YES];

    if (![AppManager  valueForKey:@"isLiveGuideFirst"]&&![self phoneLivingSelf]) {//引导层

        UIImageView* imageViewGuide = [[ UIImageView alloc]initWithFrame:CGRectMake(0, 0, 270/2, 78/2)];
        imageViewGuide.center = CGPointMake(SCREEN_WIDTH-10-(5-4)*(35+7)+7-270/2/2, SCREEN_HEIGHT-35-10-78/2/2-5);
        [self.view addSubview:imageViewGuide];
        imageViewGuide.image =[UIImage imageNamed:@"LRLiveShare.png"];

        __weak  UIImageView* safeGuide = imageViewGuide;
        EWPButton*buttonGuide= [[EWPButton alloc]initWithFrame:CGRectMake(0, 0  , SCREEN_WIDTH, SCREEN_HEIGHT)];
        __weak EWPButton* button =buttonGuide;
        buttonGuide.buttonBlock = ^(EWPButton* sender){
            [AppManager setUserBoolValue:YES key:@"isLiveGuideFirst"];
            [safeGuide removeFromSuperview];
            [button removeFromSuperview];

        };

        [self.view addSubview:buttonGuide];
    }

}

//开始直播的代码

 if (model.code == 1)
                     {
                         [stongSelf startLiving];

                         if (stongSelf.isFrontCamera) {//当为前置摄像头时候关闭闪光灯
                             [stongSelf.openFlashLight setImage:[UIImage imageNamed:@"Star_LiveRoom_lightning_no.png"] forState:UIControlStateNormal];
                             _isFlashOn  = NO;
                         }
                     }
#pragma mark- <<<<<<<<开播成功 >>开始录制上传视频流
- (void)startLiving
{

    if (self.strUploadUrl.length==0) {
//        [self showNoticeInWindow:@"url为nil" duration:2];
//        NSLog(@"url为nil,退出");
//        [self autoExitRoom];
    __weak typeof(self) weakself = self;
        [self showAlertView:@"获取视频服务器信息失败" message:@"是否重试" confirm:^(id sender) {
            weakself.liveRoomOtherThings = LiveRoomOtherThing_SelfLiveIpError;
            [weakself getLivingInfo];
        } cancel:^(id sender) {
             NSLog(@"获取自己直播时,视频服务器信息失败,退出");
            [weakself stopPlayingautoExitRoom];
        }];
        return;
    }

    const char* a= [self.strUploadUrl UTF8String];

    int result = -1 ;
  NSString * str =[UserInfoManager shareUserInfoManager].currentStarInfo.roomfmt;
       const char * pargs =[str cStringUsingEncoding:NSASCIIStringEncoding];
    if ([[SeekuSingle shareSeekuSingle] streamInitialized])
    {
        result = [[SeekuSingle shareSeekuSingle] lib_seeku_stream_start:a args:pargs];
    }

    if (result<0) {
        self.beforeLiveView.buttonLiving.userInteractionEnabled = YES;
        [self showNoticeInWindow:@"获取视频失败,请稍后重试" duration:2];

    }else{

        [_liveRoomIamgeView setCanUpLoad ];

        [self upLodSeeku];
    }

}

作者:郑岐
链接:http://www.zhihu.com/question/36076688/answer/104440589
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1、从推流到拉流的通道,这当中包括数据采集→数据编码→数据传输(流媒体服务器) →解码数据→播放显示整个流程;
2、内容复制分发,也就是cdn这块,服务器收集到主播视频后再通过在全国各地的节点将视频内容分发到终端。cdn是直播中最贵的,技术难度较高,一般都是采用第三方的;如果自己做的话,也需要和cdn厂商对接有经验的技术;
3、美颜:美颜涉及到复杂的算法和图像处理技术,美颜起初是用于图片上,目前图片上的美颜技术已经较为成熟,然而在视频上的美颜还需要很长的路要走;
4、聊天室:我们在看直播的时候,还可以在聊天室中聊天,这是应用了im及时通讯中的聊天室功能,聊天室和群聊的区别是,只有用户进入聊天室才能发言,看到好友,退出聊天室后就类似于退群,就收不到消息,看不到用户,看不到聊天记录了;
5、服务器:对于直播产品来说,流量变化是非常大的,一天中直播的流量高峰期基本在晚上,有时候搞个活动,或周杰伦跑来直播了,那这个时候流量可能是平时的几十倍。流量忽高忽低对服务器自然提出了很高的要求;

二、我们肉眼上所看到的只是直播的UI层设计,一个直播产品要将聊天室和视频呈现给观众,手机屏幕就这么大,可发挥的空间很有限,因此我们从UI层来看,各个直播app似乎大同小异。

三、然而直播最复杂的技术逻辑是在后端的处理上。直播的技术实现一般两种方法,自研or使用第三方SDK,从长远看,等到直播平台发展到像斗鱼这样的体量,自研可以节省成本。对于一个初创团队来讲,自研直播不管在技术门槛、CDN、带宽上都是有很大的门槛的。所以,目前体量较大的直播产品也有使用第三方直播云服务的。

四、利益相关
我们团队是做直播技术的,底层架构都是做好的,开放给开发者sdk和api接口,开发者接入后就可以实现直播的功能。感兴趣的同学qq2479775187私聊

时间: 2024-10-14 10:09:35

手把手教你视频直播开发的相关文章

手把手教你使用FineUI开发一个b/s结构的取送货管理信息系统系列博文索引

近阶段接到一些b/s类型的软件项目,但是团队成员之前大部分没有这方面的开发经验,于是自己选择了一套目前网上比较容易上手的开发框架(FineUI),计划录制一套视频讲座,来讲解如何利用FineUI快速开发一个小型的b/s结构的管理系统,已达到帮助团队成员快速掌握b/s结构信息系统的开发方法. 源码位置:https://github.com/kamiba/FineUIDemo 源码下载办法:安装SVN客户端(本文最后提供下载地址),然后checkout以下的地址:https://github.com

CSS3实战开发:手把手教你照片墙实战开发

在<CSS3 2D转换技术之translate实战开发>文章中,我给大家列出了CSS3中的2D转换方法: 1.    translate() 2.    rotate() 3.    scale() 4.    skew() 5.    matrix() 同时对第一个方法 translate()做了非常详尽的介绍,并带领大家实战开发了一个导航条.如果你对translate不了解或不是太熟悉,请阅读我的博文 <CSS3 2D转换技术之translate实战开发> . 在讲解知识点之前

手把手教你使用 Clion 开发 Linux C++ 项目

手把手教你使用 Clion 开发 Linux C++ 项目 关于CLion CLion是一款专为开发C及C++所设计的跨平台IDE.它是以IntelliJ为基础设计的,包含了许多智能功能来提高开发人员的生产力,提高开发人员的工作效率.这种强大的IDE帮助开发人员在Linux.OS X和Windows上来开发C/C++,同时它还使用智能编辑器来提高代码质量.自动代码重构并且深度整合CMake编译系统,从而提高开发人员的工作效率.重要功能有:提供C及C++支持(包含C++11, libc++ 和Bo

东方耀 手把手教React Native实战开发视频教程+源码笔记全集

课程序号标题 第0课0.手把手教React Native实战之开山篇_视频 第1课1.手把手教React Native实战之环境搭建_视频_Windows环境 第1课1.手把手教React Native实战之环境搭建[Mac真机]同时调试开发Android&IOS 第2课2.手把手教React Native实战之从React到RN 第3课3.手把手教React Native实战之flexbox布局(RN基础) 第4讲4.手把手教React Native实战之flexbox布局(伸缩属性) 第5讲

手把手教你搭建PHP开发“黄金自由新搭档”

引言:随着PHP广泛应用白热化,大家使用的开发工具从重量级的ZendStudio到轻量级的Notepad++可以说是五花八门.应有尽有,这给初学者带来不少困惑,工具太多了就无从下手选择适合自己需要的东东.笔者亲自测试和比较,选择适合大多数开发人员追求既"自由.快捷.简便"又满足功能强大的实际需要,从自定义PHP运行环境配置文件着手搭建PHP开发平台,并给出详细的操作步骤.手把手教你用网络风暴WebStorm+集成开发工具PhpStorm+自定义运行环境phpRE搭建PHP开发"

视频直播开发——直播源码的功能有哪些?

直播行业在经过爆发式的发展,经历了2017年相对平稳的发展阶段,2018年直播系统得到了更广泛的工具化应用.如果你要问我,这时候涉足直播行业还赚钱吗?我会非常肯定的跟你说,非常赚钱.就看你做不做了!如何去做一个直播平台,那你就得看看直播源码是如何构成新功能的!直播源码功能的丰富性成就了各式各样的直播平台!我们先来看直播源码的全新功能都有哪些?1.直播间连麦功能:用户在直播间对主播发起连麦申请,主播通过申请后,发起申请的用户画面出现在直播间的左上角,主播和观众实时互动,直播体验更愉快!2.密码房间

手把手教你智能硬件开发(一) 我选Arduino

第1节 我选Arduino 高大上的无人机玩过吗?智能的家庭空气检测仪见过吗?手机控制的电子体重秤.血压仪用过吗?这些"高科技"都属于智能硬件. 作为软件开发者的你,有没有想过自己开发一个智能硬件呢? 也许你会觉得硬件开发的门槛很高,作为小白或者软件开发者难以企及,那么这你就想错了.其实,现在已经有了很多专门为软件开发者设计的智能硬件开发平台.例如现在火爆的树莓派-raspberry pi.英特尔推出的爱迪生-Edison,以及本系列讲重点介绍的Arduino. 有了它们,即使你对硬件

手把手教你智能硬件开发(六)直流马达

第6节 直流马达 马达是我们经常使用到的电动装置,它可以将电能转化成动能,驱动其他东西的运动.听起来很抽象,举几个例子吧. 我们小时候玩的四驱车,带动轮子转动的那个小装置就是马达:夏天让风扇旋转带给我们凉意,也是马达的功劳. 根据使用电源的不同,可以将马达分成直流马达和交流马达.我们做智能硬件使用的基本都是直流马达,通过马达来驱动外接设备运动. 6.1 工作原理 将电能转化成动能的物理原理,我们在中学已经学过,这里利用了两个原理:电磁感应和磁铁的同性相斥异性相吸. 将一根磁棒放在金属罩中间,两端

手把手教你用VUE开发后台管理系统(三):搭建SpringBoo 2.xt环境

原文地址:https://www.cnblogs.com/hugo123/p/11581938.html