iOS直播实用篇

极速蜗牛 8年前
   <h3><strong>一.简述总体内容</strong></h3>    <ul>     <li> <p>1.直播流程介绍</p> </li>     <li> <p>2. Mac 搭建 nginx+rtmp 服务器(模拟推流拉流)</p> </li>     <li> <p>3.简单的集成推流拉流( <strong>实用篇</strong> )</p> </li>     <li> <p>4.好的博客推荐</p> </li>    </ul>    <h3><strong>二.直播流程介绍</strong></h3>    <ul>     <li style="text-align:center"> <p style="text-align: left;">1.简单的流程图</p> <img src="https://simg.open-open.com/show/c09c42035926260f70c99d00d11e4613.png"> <p style="text-align: left;">简单的流程图</p> </li>     <li style="text-align:center"> <p style="text-align: left;">2.七牛的直播流程</p> <img src="https://simg.open-open.com/show/ad2c5ee0ec451e44ec363b42f62b8cd0.jpg"> <p>七牛的直播流程</p> </li>     <li> <p>3.视频直播,可以分为 <strong>采集</strong> , <strong>前处理(美颜等等)</strong> , <strong>编码</strong> , <strong>推流和传输</strong> , <strong>服务器处理</strong> , <strong>解码拉流</strong></p>      <ul>       <li style="text-align:center"> <p style="text-align: left;">1. <strong>采集</strong> :采集是整个视频推流过程中的第一个环节,它从系统的采集设备中获取原始视频数据,将其输出到下一个环节。视频的采集涉及两方面数据的采集:音频采集和图像采集,它们分别对应两种完全不同的输入源和数据格式. iOS 系统因为软硬件种类不多, 硬件适配性比较好, 所以比较简单. 而 Android 端市面上机型众多, 要做些机型的适配工作. PC 端是最麻烦的, 各种奇葩摄像头驱动.所以现在很多的中小型直播平台, 都放弃了 PC 的直播, 更有一些直播平台只做 iOS 端的视频直播.</p> <img src="https://simg.open-open.com/show/ea03f423ff04e8bc092500fcfd8263f2.jpg"></li>      </ul> </li>    </ul>    <p style="text-align:center">采集</p>    <ul>     <li style="text-align:center"> <p style="text-align:left">2. <strong>前处理</strong> : 美颜算法,视频的模糊效果, 水印等都是在这个环节做. 目前iOS端最著名开源框架的毫无疑问就是GPUImage.其中内置了125种渲染效果, 还支持各种脚本自定义. GPUImage所有滤镜介绍 都说「80% 的主播没有美颜根本没法看」,美颜是直播产品中最常见的功能之一。最近准备在香港上市的美图公司的主打产品就是美颜相机和美拍,有媒体戏称其会冲击化妆品行业,其实就是美颜的效果的功劳,让美女主播们不化妆也可以自信的直播,而美颜相机的用户则可以拍出「更好的自己」。</p> <p> </p> <img src="https://simg.open-open.com/show/0c3981b26b62dfcc646d8ca546614073.png"> <p>前处理</p> </li>     <li> <p>3. <strong>编码</strong> :对流媒体传输来说,编码也非常重要,它的编码性能、编码速度和编码压缩比会直接影响整个流媒体传输的用户体验和传输成本.重难点在于要在分辨率,帧率,码率,GOP等参数设计上找到最佳平衡点。iOS8之后, Apple开放了VideoToolbox.framework, 可以直接进行硬编解码, 这也是为什么现在大多数直播平台最低只支持到iOS8的原因之一. iOS端硬件兼容性比较好, 可以直接采取硬编码,常用的编码有: H265</p> </li>     <li> <p>4.推流和传输: 这块一般都是交给CDN服务商. CDN只提供带宽和服务器之间的传输, 发送端和接收端的网络连接抖动缓存还是要自己实现的.目前国内最大的CDN服务商应该是网宿.传输协议一般是RTMP,HLS,FLV</p> </li>     <li> <p>5.服务器处理:需要在服务器做一些流处理工作, 让推送上来的流适配各个平台各种不同的协议, 比如:RTMP,HLS,FLV...</p> </li>     <li> <p>6.解码拉流:推流需要编码,同样拉流解码是必须的. iOS 端兼容较好, Android 依然大坑.这块的难点在于音画同步, 目前很多直播平台这块是硬伤.国内比较好的开源项目应该是B站开源的 ijkplayer .斗鱼就是基于 ijkplayer 的, 本项目也是基于 ijkplayer 的.</p> </li>    </ul>    <h3><strong>三.Mac搭建nginx+rtmp服务器(模拟推流拉流)</strong></h3>    <p>效果如下(把桌面的视频推到搭建的服务器再利用播放器 VLC 密码: 7gbp 拉流),也可以用自己写的播放软件来拉流,或者三方</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/51bd269f6afa5b87de2eab0de66e247b.png"></p>    <p style="text-align:center">Mac搭建nginx+rtmp服务器(模拟推流拉流)</p>    <p>手动输入命令的时候容易出现了bug(所以, 建议大家直接复制命令, 不要手动输入命令). </p>    <ul>     <li> <p>1.打开终端, 查看是否已经安装了 Homebrew , 直接终端输入命令</p> <pre>  <code class="language-objectivec">man brew</code></pre> <p>如果Mac已经安装了, 会显示一些命令的帮助信息. 此时输入Q退出即可, 直接进入第二步.反之, 如果没有安装,执行命令</p> <pre>  <code class="language-objectivec">ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</code></pre> <p>如果安装后, 想要卸载</p> <pre>  <code class="language-objectivec">ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"</code></pre> </li>    </ul>    <p>2.安装nginx</p>    <p>先clone nginx项目到本地</p>    <pre style="text-align:center">  <code class="language-objectivec">brew tap homebrew/nginx</code></pre>    <p>执行安装:</p>    <pre style="text-align:center">  <code class="language-objectivec">brew install nginx-full --with-rtmp-module</code></pre>    <p>此时, nginx和rtmp模块就安装好了</p>    <p>输入命令:</p>    <pre style="text-align:center">  <code class="language-objectivec">nginx</code></pre>    <p>在浏览器里打开 http://localhost:8080</p>    <p>如果出现下图, 则表示安装成功</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/14752143e5a859f49a23448a3f82d4d4.jpg"></p>    <p>安装成功</p>    <p>如果终端上提示</p>    <p>nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)</p>    <p>nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)</p>    <p>nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)</p>    <p>nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)</p>    <p style="text-align:center">.....</p>    <p>则表示 8080 端口被占用了, 查看端口PID</p>    <pre>  <code class="language-objectivec">lsof -i tcp:8080</code></pre>    <p>根据端口PID, kill掉(这儿的9603换成你自己8080端口的PID)</p>    <pre>  <code class="language-objectivec">kill 9603</code></pre>    <p>然后重新执行 nginx , 打开 http://localhost:8080 进行检测是否 nginx 安装成功</p>    <ul>     <li> <p>3.配置nginx和ramp</p> <p>首先我们查看nginx安装到哪了</p> <pre>  <code class="language-objectivec">brew info nginx-full</code></pre> <p>如图, 找到nginx.conf文件所在位置</p> </li>    </ul>    <p style="text-align:center"><img src="https://simg.open-open.com/show/22acb470128439cba2ae3c1b9fe628e7.png"></p>    <p style="text-align:center">nginx.conf文件所在位置</p>    <p>通过 vim 或者点击 Finder ->前往->前往文件夹->输入 /usr/local/etc/nginx/nginx.conf ->用记事本工具(推荐 Sublime Text )打开nginx.conf.</p>    <p>直接滚到最后一行, 在最后一个 } (即最后的空白处, 没有任何 {} )后面添加</p>    <pre>  <code class="language-objectivec"># 在http节点后面加上rtmp配置:    rtmp {      server {      listen 1935;      application rtmplive {          live on;          record off;        }      }   }</code></pre>    <p>记得保存 command+S</p>    <p>然后重启nginx(其中的1.10.1要换成你自己安装的 nginx 版本号, 查看版本号用 nginx -v 命令即可)</p>    <pre>  <code class="language-objectivec">/usr/local/Cellar/nginx-full/1.10.1/bin/nginx -s reload</code></pre>    <ul>     <li> <p>4.安装ffmpeg</p> <p>执行命令</p> <pre>  <code class="language-objectivec">brew install ffmpeg</code></pre> <p>安装 ffmpeg 时间就要长一点了. 如果速度过慢, 建议KX上网. 不过也才 50 多 M 的东西, 耐心一点就好. 等待的时间里, 再安装一个支持 rtmp 协议的视频播放器 VLC 密码: 7gbp</p> </li>     <li> <p>5.进行推流</p> <p>(1).ffmpeg推流,用我桌面的一个动画片为例,执行推流命令</p> </li>    </ul>    <p style="text-align:center"><img src="https://simg.open-open.com/show/97921c8894e6c76bc37d15ab51843327.png"></p>    <p style="text-align:center">动画片</p>    <p>ffmpeg -re -i /Users/jinqianxiang/Desktop/BigBuck.m4v -vcodec libx264 -acodec aac -strict -2 -f flv rtmp://localhost:1935/rtmplive/room</p>    <p>提醒: /Users/jinqianxiang/Desktop/BigBuck.m4v是路径,你可把视频拖进终端,查看路径</p>    <p>将视频推流到服务器后,打开 VLC ,然后 File->open network-> 输入:</p>    <pre>  <code class="language-objectivec">rtmp://localhost:1935/rtmplive/room</code></pre>    <p><img src="https://simg.open-open.com/show/843999d8febe346c78fbc94a21228c4b.png"></p>    <p style="text-align: center;">输入拉流的url</p>    <p>效果如下</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/80f60847449a18fb6434c840704467ac.png"></p>    <p style="text-align:center">效果</p>    <p>四.简单的集成推流拉流(实用篇)</p>    <ul>     <li> <p>1. <strong>推流端</strong> ,这里我才用的 开源的拉流框架,开源的iOS推流框架 LFLiveKit . 是用OC写的, 很适合学习集成也非常简单, 几句代码就OK了.</p> <p>采用cocopods导入即可</p> <pre>  <code class="language-objectivec">pod 'LFLiveKit'</code></pre> </li>    </ul>    <p>提示: LFLiveKit 已经集成了 GPUImage , 如果项目中有集成 GPUImage , 需要将之前的移除掉. 且集成 LFLiveKit 需要关闭 Bitcode.</p>    <p><img src="https://simg.open-open.com/show/9339cf9b9617732220b180aedfe2fd6a.png"></p>    <p>集成 LFLiveKit 需要关闭 Bitcode.</p>    <p>导入成功</p>    <p><img src="https://simg.open-open.com/show/e6af842637ffb6be2d034926324558aa.png"></p>    <p>cocopods成功导入LFLiveKit</p>    <p>在推流的控制器写入下面的代码</p>    <pre>  <code class="language-objectivec">导入推流框架 #import "LFLiveKit.h"    - (LFLiveSession*)session {  if (!_session) {      _session = [[LFLiveSession alloc] initWithAudioConfiguration:[LFLiveAudioConfiguration defaultConfiguration] videoConfiguration:[LFLiveVideoConfiguration defaultConfiguration]];      _session.preView = self;      _session.delegate = self;    }    return _session;  }    - (void)startLive {       LFLiveStreamInfo *streamInfo = [LFLiveStreamInfo new];      streamInfo.url = @"your server rtmp url";      [self.session startLive:streamInfo];  }    - (void)stopLive {        [self.session stopLive];  }    //MARK: - CallBack:  - (void)liveSession:(nullable LFLiveSession *)session liveStateDidChange: (LFLiveState)state;  - (void)liveSession:(nullable LFLiveSession *)session debugInfo:(nullable LFLiveDebug*)debugInfo;  - (void)liveSession:(nullable LFLiveSession*)session errorCode:(LFLiveSocketErrorCode)errorCode;</code></pre>    <p>到此推流就成功了,提示网络一定要打来</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/427f4e3f03579181eb1578834fe4b802.png"></p>    <p>打开网络</p>    <ul>     <li> <p>2. <strong>拉流端</strong> 主要是基于 ijkplayer 的. 最好是打包成framework.打包教程</p> <p>下载 ijkplayer打包好的静态库 密码: mcjt</p> <p>导入库:</p> </li>    </ul>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6c0102c15281a3d49712ab8e2eb8bddb.png"></p>    <p>导入库</p>    <p>完成上述之后,运行不报错,就说明你基本上成功了,在拉流的控制器里面输入下面的代码</p>    <pre>  <code class="language-objectivec">导入 #import <IJKMediaFramework/IJKMediaFramework.h>     1.创建推流对象   - (LFLiveSession*)session {       if (!_session) {      _session = [[LFLiveSession alloc] initWithAudioConfiguration:[LFLiveAudioConfiguration defaultConfiguration] videoConfiguration:[LFLiveVideoConfiguration defaultConfiguration]];      _session.delegate = self;    }    return _session;  }</code></pre>    <p>2.在点击开始直播的方法里面输入</p>    <pre>  <code class="language-objectivec">NSLog(@"开始直播");    // 判断是否是模拟器  if ([[UIDevice deviceVersion] isEqualToString:@"iPhone Simulator"]) {        [MBProgressHUD showError:@"请用真机进行测试, 此模块不支持模拟器测试"];        return;  }    // 判断是否有摄像头  if(![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){      [MBProgressHUD showError:@"您的设备没有摄像头或者相关的驱动, 不能进行直播"];      return;  }    // 判断是否有摄像头权限  AVAuthorizationStatus  authorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];  if (authorizationStatus == AVAuthorizationStatusRestricted|| authorizationStatus == AVAuthorizationStatusDenied) {      [MBProgressHUD showError:@"app需要访问您的摄像头。\n请启用摄像头-设置/隐私/摄像头"];        return;  }    // 开启麦克风权限  AVAudioSession *audioSession = [AVAudioSession sharedInstance];  if ([audioSession respondsToSelector:@selector(requestRecordPermission:)]) {      [audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {          if (granted) {              return YES;          }          else {              //[self showInfo:@"app需要访问您的麦克风。\n请启用麦克风-设置/隐私/麦克风"];              return NO;          }      }];  }    LFLiveStreamInfo *streamInfo = [LFLiveStreamInfo new];    streamInfo.url = kTRMPServe;    [self.session startLive:streamInfo];</code></pre>    <p>相关的类demo里面都有 简单的直播demo 密码: w935</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/2d46f3418ecfae6b8d1432a9b37bc707.png"></p>    <p style="text-align:center">屏幕快照 2016-11-09 上午12.27.36.png</p>    <p>到此,推流和拉流就完成了,更多美颜等功能等等,就看更多的大神博客,下面推荐</p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/339041855364</p>    <p> </p>