iOS視頻直播初窺:高仿<喵播APP>
?
2016.07.06 00:20*?字?jǐn)?shù) 3095?閱讀 69159評(píng)論 369喜歡 1174贊賞 9
效果圖
gif1
gif2
由于licecap錄制的GIF失幀太嚴(yán)重, 都模糊掉了, 再放兩張高清截圖
png1
png2
前言
今年三月份置尔,斗魚(yú)獲騰訊領(lǐng)投的1億美元融資的消息被各大平臺(tái)報(bào)道轉(zhuǎn)載,在電競(jìng)调限、泛娛樂(lè)已是熱門(mén)投資的當(dāng)下涂召,網(wǎng)絡(luò)直播平臺(tái)自然也獲得了各界的關(guān)注坠非。盜用兩張關(guān)于游戲直播的趨勢(shì)圖
游戲直播規(guī)模
游戲直播規(guī)模
這還僅僅是游戲直播這塊的蛋糕.直播行業(yè)的競(jìng)爭(zhēng)會(huì)越來(lái)越激烈, 不管是主播還是直播平臺(tái)都面臨著激烈的競(jìng)爭(zhēng), 當(dāng)然直播行業(yè)也會(huì)越來(lái)越規(guī)范, 直播元素也越來(lái)越多.
視頻直播初窺
視頻直播敏沉,可以分為 采集果正,前處理,編碼盟迟,傳輸, 服務(wù)器處理秋泳,解碼,渲染
采集: iOS系統(tǒng)因?yàn)檐浻布N類不多, 硬件適配性比較好, 所以比較簡(jiǎn)單. 而Android端市面上機(jī)型眾多, 要做些機(jī)型的適配工作.PC端是最麻煩的, 各種奇葩攝像頭驅(qū)動(dòng).所以現(xiàn)在很多的中小型直播平臺(tái), 都放棄了PC的直播, 更有一些直播平臺(tái)只做iOS端的視頻直播.
前處理: 美顏算法,視頻的模糊效果, 水印等都是在這個(gè)環(huán)節(jié)做. 目前iOS端最著名開(kāi)源框架的毫無(wú)疑問(wèn)就是GPUImage.其中內(nèi)置了125種渲染效果, 還支持各種腳本自定義. 我高仿的喵播的美顏效果也是基于GPUImage的.
編碼: 重難點(diǎn)在于要在分辨率攒菠,幀率迫皱,碼率,GOP等參數(shù)設(shè)計(jì)上找到最佳平衡點(diǎn)辖众。iOS8之后,?Apple開(kāi)放了VideoToolbox.framework, 可以直接進(jìn)行硬編解碼, 這也是為什么現(xiàn)在大多數(shù)直播平臺(tái)最低只支持到iOS8的原因之一. iOS端硬件兼容性比較好, 可以直接采取硬編碼. 而Android得硬編碼又是一大坑.
傳輸: 這塊一般都是交給CDN服務(wù)商.?CDN只提供帶寬和服務(wù)器之間的傳輸, 發(fā)送端和接收端的網(wǎng)絡(luò)連接抖動(dòng)緩存還是要自己實(shí)現(xiàn)的.目前國(guó)內(nèi)最大的CDN服務(wù)商應(yīng)該是網(wǎng)宿.
服務(wù)器處理: 需要在服務(wù)器做一些流處理工作, 讓推送上來(lái)的流適配各個(gè)平臺(tái)各種不同的協(xié)議, 比如:RTMP,HLS,FLV...
解碼和渲染: 也就即音視頻的播放. 解碼毫無(wú)疑問(wèn)也必須要硬解碼. iOS端兼容較好, Android依然大坑.這塊的難點(diǎn)在于音畫(huà)同步, 目前很多直播平臺(tái)這塊是硬傷.國(guó)內(nèi)比較好的開(kāi)源項(xiàng)目應(yīng)該是B站開(kāi)源的ijkplayer .?斗魚(yú)就是基于ijkplayer 的, 本項(xiàng)目也是基于ijkplayer 的.
技術(shù)坑 : 降噪, 音頻解碼器, 藍(lán)牙適配, 回聲消除, 信令控制, 登錄, 鑒權(quán), 權(quán)限管理, 狀態(tài)管理, 應(yīng)用消息, 消息推送, 禮物系統(tǒng), 即時(shí)聊天, 支付系統(tǒng), 統(tǒng)計(jì)系統(tǒng), 數(shù)據(jù)庫(kù), 緩存, 分布式文件存儲(chǔ), 消息隊(duì)列, 運(yùn)維系統(tǒng)等等大小不一的坑等你來(lái)填!!!
資金坑 : 以帶寬為例, 2萬(wàn)人同時(shí)在線, 手機(jī)碼率在600KB, 每個(gè)月的帶寬費(fèi)用至少在30萬(wàn)左右. 根據(jù)歡聚時(shí)代(YY)15年四季度財(cái)務(wù)報(bào), 他們的帶寬成本為人民幣1.611億元, 折合每月5000萬(wàn)+. 人力成本+渠道支出和其他支出就不詳談了.
社會(huì)坑: 還得每時(shí)每刻與各種黑暗勢(shì)力斗爭(zhēng), 包括色情, 廣告, 刷小號(hào), 刷充值, 告侵權(quán), DDos...(我反編譯喵播的官方APP, 他們的項(xiàng)目名就叫Shehui, O(∩_∩)O哈哈~)
項(xiàng)目下載地址
前期準(zhǔn)備
項(xiàng)目主要是基于ijkplayer 的. 最好是打包成framework. 原本我準(zhǔn)備寫(xiě)一個(gè)打包教程, 不過(guò)后來(lái)在簡(jiǎn)書(shū)上發(fā)現(xiàn)了一篇特別詳細(xì)的打包blog, 分享給大家: http://www.reibang.com/p/1f06b27b3ac0.
如果你根據(jù)教程打包失敗了(當(dāng)然這種幾率比較小), 我這還有一份我已經(jīng)打包好的(Release版), 下載地址:
鏈接:http://pan.baidu.com/s/1eRVetdK?密碼:2dc0
下載后, 直接解壓即可.
項(xiàng)目文件結(jié)構(gòu)
Frameworks: 如果文件夾不存在, 點(diǎn)擊classes選擇Show in Finder, 新建一個(gè)即可, 將你打包的或者下載的framework拖入其中并拉進(jìn)項(xiàng)目中. 你也可以自己建一個(gè)文件夾, 把這個(gè)Frameworks直接delete即可
Profile : 個(gè)人中心, 這里面只有一個(gè)ProfileController. 因?yàn)榭倢?xiě)重復(fù)代碼, 都寫(xiě)吐了, 這兒有興趣的自己寫(xiě)一下吧, So easy...
Network : 關(guān)于網(wǎng)絡(luò)連接的工具類. 關(guān)于網(wǎng)絡(luò)的實(shí)時(shí)監(jiān)控, 網(wǎng)絡(luò)狀態(tài)的切換, 網(wǎng)絡(luò)請(qǐng)求的工具類都在這里面.
Other : 全局的常量. 當(dāng)然你也可以在里面將文件結(jié)構(gòu)更加細(xì)化.
Home : 包含最新主播, 最熱直播, 關(guān)注的直播, 禮物排行榜等模塊. 還有最重要的視頻直播也在這里面了.
ShowTime :見(jiàn)名知意. 視頻直播的前處理, 智能美顏和H264硬編碼等都在這里面.
Main :?UITabBarController和UINavigationController的配置
Toos : 這兒命名有點(diǎn)不規(guī)范, 這里面放置的都是項(xiàng)目用到的分類
Login : 登錄模塊
Resource : 項(xiàng)目用到的資源文件
項(xiàng)目詳解
tip1: 判讀網(wǎng)絡(luò)類型.
在觀看直播的時(shí)候, 我們通常都是用WiFi或者3/4G(土豪級(jí)別的), 一般用戶在進(jìn)行網(wǎng)絡(luò)切換的時(shí)候, 我們都要給出友善的提示, 告訴TA: 您的網(wǎng)絡(luò)狀態(tài)切換到了XX狀態(tài). 假設(shè)用戶從WiFi切換到4G, 你的應(yīng)用也沒(méi)個(gè)提醒, 導(dǎo)致TA的流量歸零甚至欠了運(yùn)營(yíng)商一屁股的錢(qián), 我想你的APP的用戶體驗(yàn)也就歸零或者為負(fù)了.
我們可以使用蘋(píng)果的Reachability結(jié)合下面的代碼實(shí)時(shí)監(jiān)聽(tīng)網(wǎng)絡(luò)狀態(tài)的改變
typedefNS_ENUM(NSUInteger, NetworkStates) {? ? NetworkStatesNone,// 沒(méi)有網(wǎng)絡(luò)NetworkStates2G,// 2GNetworkStates3G,// 3GNetworkStates4G,// 4GNetworkStatesWIFI// WIFI};
// 判斷網(wǎng)絡(luò)類型+ (NetworkStates)getNetworkStates{NSArray*subviews = [[[[UIApplicationsharedApplication] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];// 保存網(wǎng)絡(luò)狀態(tài)NetworkStates states = NetworkStatesNone;for(idchildinsubviews) {if([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {//獲取到狀態(tài)欄碼intnetworkType = [[child valueForKeyPath:@"dataNetworkType"] intValue];switch(networkType) {case0://無(wú)網(wǎng)模式states = NetworkStatesNone;break;case1:? ? ? ? ? ? ? ? ? ? states = NetworkStates2G;break;case2:? ? ? ? ? ? ? ? ? ? states = NetworkStates3G;break;case3:? ? ? ? ? ? ? ? ? ? states = NetworkStates4G;break;case5:? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? states = NetworkStatesWIFI;? ? ? ? ? ? ? ? }break;default:break;? ? ? ? ? ? }? ? ? ? }? ? }//根據(jù)狀態(tài)選擇returnstates;}
tip2: 登錄模塊
如果你多運(yùn)行幾次就會(huì)發(fā)現(xiàn), 登錄模塊背景中播放的視頻是2個(gè)視頻每次隨機(jī)播放一個(gè)的.并且是無(wú)限重復(fù)的, 也就是說(shuō)只要你一直呆著登錄界面, 就會(huì)單視頻循環(huán)播放當(dāng)前的視頻. 這兒的登錄只是幾個(gè)按鈕, 沒(méi)有具體的登錄邏輯, 隨便點(diǎn)哪一個(gè)按鈕都可以進(jìn)入首頁(yè).
我們需要監(jiān)聽(tīng)視頻, 是否播放完成.
// 監(jiān)聽(tīng)視頻是否播放完成[[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(didFinish) name:IJKMPMoviePlayerPlaybackDidFinishNotification object:nil];
如果播放完成了, 讓IJKFFMoviePlayerController再次play即可
- (void)didFinish{// 播放完之后, 繼續(xù)重播[self.player play];}
tip3: 首頁(yè)
首頁(yè)
這種效果相信很多人都看到過(guò)或者做過(guò).我簡(jiǎn)單說(shuō)一下我的做法(不一定是最佳的, 只是提供一個(gè)思路)
一個(gè)父控制器HomeViewController+三個(gè)子控制器(最熱/最新/關(guān)注. 每個(gè)控制器各自管理自己的業(yè)務(wù)邏輯, 高內(nèi)聚低耦合). 重寫(xiě)HomeViewController的loadView, 將self.view替換成UIScrollView. 將三個(gè)子控制器的view添加到UIScrollView上即可. 其他的效果實(shí)現(xiàn), 請(qǐng)參照我的代碼, 都有詳細(xì)的中文注釋.
tip4: 直播(面向觀眾端)
這個(gè)是整個(gè)項(xiàng)目的重點(diǎn)之一了.這種直播的布局, 應(yīng)該是比較主流的了. 我下載的好多直播類APP都是這個(gè)項(xiàng)目布局, 包括YY也是這種界面布局.這個(gè)里面涉及的東西比較多了, 三言兩語(yǔ)真說(shuō)不清.
簡(jiǎn)單說(shuō)一下已經(jīng)實(shí)現(xiàn)的效果:
A: 主播的直播
B: 關(guān)聯(lián)主播的視頻直播, 默認(rèn)是只有界面, 沒(méi)有聲音的. 點(diǎn)擊該視圖可以切換到此主播
C: 下拉切換另一個(gè)主播, 這個(gè)功能是很常見(jiàn)的. 做法是直播控制器是一個(gè)UICollectionViewController, 只有一個(gè)cell, 且cell.frame就是self.collectionViewb.bounds. 我們進(jìn)入直播控制器的時(shí)候, 其實(shí)是傳進(jìn)去一個(gè)關(guān)聯(lián)主播數(shù)組, 每次下拉的時(shí)候, 就加載數(shù)組里面的主播
D. 查看觀眾席的觀眾詳情
E. 查看主播詳情
F. 足跡: 粒子動(dòng)畫(huà), 后面詳解
G. 彈幕: 點(diǎn)擊最下方的工具欄第一個(gè)按鈕可以開(kāi)啟/關(guān)閉彈幕, 后面詳解
...
tip5: 粒子動(dòng)畫(huà)實(shí)現(xiàn)游客足跡
粒子動(dòng)畫(huà)的layer是添加到播放器的view上面的. 下面代碼有詳細(xì)的注釋
CAEmitterLayer*emitterLayer = [CAEmitterLayerlayer];// 發(fā)射器在xy平面的中心位置emitterLayer.emitterPosition =CGPointMake(self.moviePlayer.view.frame.size.width-50,self.moviePlayer.view.frame.size.height-50);// 發(fā)射器的尺寸大小emitterLayer.emitterSize =CGSizeMake(20,20);// 渲染模式emitterLayer.renderMode = kCAEmitterLayerUnordered;// 開(kāi)啟三維效果//? ? _emitterLayer.preservesDepth = YES;NSMutableArray*array = [NSMutableArrayarray];// 創(chuàng)建粒子for(inti =0; i<10; i++) {// 發(fā)射單元CAEmitterCell*stepCell = [CAEmitterCellemitterCell];// 粒子的創(chuàng)建速率卓起,默認(rèn)為1/sstepCell.birthRate =1;// 粒子存活時(shí)間stepCell.lifetime = arc4random_uniform(4) +1;// 粒子的生存時(shí)間容差stepCell.lifetimeRange =1.5;// 顏色// fire.color=[[UIColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:0.1]CGColor];UIImage*image = [UIImageimageNamed:[NSStringstringWithFormat:@"good%d_30x30", i]];// 粒子顯示的內(nèi)容stepCell.contents = (id)[imageCGImage];// 粒子的名字//? ? ? ? ? ? [fire setName:@"step%d", i];// 粒子的運(yùn)動(dòng)速度stepCell.velocity = arc4random_uniform(100) +100;// 粒子速度的容差stepCell.velocityRange =80;// 粒子在xy平面的發(fā)射角度stepCell.emissionLongitude = M_PI+M_PI_2;;// 粒子發(fā)射角度的容差stepCell.emissionRange = M_PI_2/6;// 縮放比例stepCell.scale =0.3;? ? [array addObject:stepCell];}emitterLayer.emitterCells = array;[self.moviePlayer.view.layer insertSublayer:emitterLayer below:self.catEarView.layer];
tip6: 彈幕
彈幕使用的也是一個(gè)第三方輪子BarrageRenderer . 這個(gè)開(kāi)源項(xiàng)目的文檔都是中文的, 用法也是很簡(jiǎn)單的.
基本配置
_renderer = [[BarrageRenderer alloc] init];// 設(shè)置彈幕的顯示區(qū)域. 基于父控件的._renderer.canvasMargin =UIEdgeInsetsMake(ALinScreenHeight *0.3,10,10,10);[self.contentView addSubview:_renderer.view];
彈幕配置
#pragma mark - 彈幕描述符生產(chǎn)方法/// 生成精靈描述 - 過(guò)場(chǎng)文字彈幕- (BarrageDescriptor *)walkTextSpriteDescriptorWithDirection:(NSInteger)direction{? ? BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];? ? descriptor.spriteName =NSStringFromClass([BarrageWalkTextSpriteclass]);? ? descriptor.params[@"text"] =self.danMuText[arc4random_uniform((uint32_t)self.danMuText.count)];? ? descriptor.params[@"textColor"] = Color(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256));? ? descriptor.params[@"speed"] = @(100* (double)random()/RAND_MAX+50);? ? descriptor.params[@"direction"] = @(direction);? ? descriptor.params[@"clickAction"] = ^{UIAlertView*alertView = [[UIAlertViewalloc]initWithTitle:@"提示"message:@"彈幕被點(diǎn)擊"delegate:nilcancelButtonTitle:@"取消"otherButtonTitles:nil];? ? ? ? [alertView show];? ? };returndescriptor;}
最后一步, 千萬(wàn)要記得start
[_renderer start];
tip7: 智能美顏效果
現(xiàn)在的直播平臺(tái), 美顏是標(biāo)配. 不然絕大多數(shù)的主播都是沒(méi)法看的.美顏算法需要用到GPU編程, 需要懂圖像處理的人. 圖像處理這一塊我不是很熟悉, 相關(guān)的文獻(xiàn)也是看得云里霧里的. 所以, 依然使用開(kāi)源的輪子: GPUImage . 這個(gè)開(kāi)源框架有近1.3W+star(7月5日數(shù)據(jù)), 真不是蓋的, 內(nèi)置125種濾鏡效果, 沒(méi)有你想不到, 只有你不會(huì)用. 我的項(xiàng)目中都有詳細(xì)的用法, 還是很簡(jiǎn)單的. 在這里摘抄一份其.h文件的注釋. 一方面方便大家修改我項(xiàng)目中的美顏效果, 另一方面也是做個(gè)備份.(具體出處我真忘了, 如果有人找到了源地址鏈接, 可以聯(lián)系我加上)
#import"GLProgram.h"http:// Base classes#import"GPUImageOpenGLESContext.h"#import"GPUImageOutput.h"#import"GPUImageView.h"#import"GPUImageVideoCamera.h"#import"GPUImageStillCamera.h"#import"GPUImageMovie.h"#import"GPUImagePicture.h"#import"GPUImageRawDataInput.h"#import"GPUImageRawDataOutput.h"#import"GPUImageMovieWriter.h"#import"GPUImageFilterPipeline.h"#import"GPUImageTextureOutput.h"#import"GPUImageFilterGroup.h"#import"GPUImageTextureInput.h"#import"GPUImageUIElement.h"#import"GPUImageBuffer.h"http:// Filters#import"GPUImageFilter.h"#import"GPUImageTwoInputFilter.h"#pragmamark - 調(diào)整顏色 Handle Color#import"GPUImageBrightnessFilter.h"http://亮度#import"GPUImageExposureFilter.h"http://曝光#import"GPUImageContrastFilter.h"http://對(duì)比度#import"GPUImageSaturationFilter.h"http://飽和度#import"GPUImageGammaFilter.h"http://伽馬線#import"GPUImageColorInvertFilter.h"http://反色#import"GPUImageSepiaFilter.h"http://褐色(懷舊)#import"GPUImageLevelsFilter.h"http://色階#import"GPUImageGrayscaleFilter.h"http://灰度#import"GPUImageHistogramFilter.h"http://色彩直方圖,顯示在圖片上#import"GPUImageHistogramGenerator.h"http://色彩直方圖#import"GPUImageRGBFilter.h"http://RGB#import"GPUImageToneCurveFilter.h"http://色調(diào)曲線#import"GPUImageMonochromeFilter.h"http://單色#import"GPUImageOpacityFilter.h"http://不透明度#import"GPUImageHighlightShadowFilter.h"http://提亮陰影#import"GPUImageFalseColorFilter.h"http://色彩替換(替換亮部和暗部色彩)#import"GPUImageHueFilter.h"http://色度#import"GPUImageChromaKeyFilter.h"http://色度鍵#import"GPUImageWhiteBalanceFilter.h"http://白平橫#import"GPUImageAverageColor.h"http://像素平均色值#import"GPUImageSolidColorGenerator.h"http://純色#import"GPUImageLuminosity.h"http://亮度平均#import"GPUImageAverageLuminanceThresholdFilter.h"http://像素色值亮度平均凹炸,圖像黑白(有類似漫畫(huà)效果)#import"GPUImageLookupFilter.h"http://lookup 色彩調(diào)整#import"GPUImageAmatorkaFilter.h"http://Amatorka lookup#import"GPUImageMissEtikateFilter.h"http://MissEtikate lookup#import"GPUImageSoftEleganceFilter.h"http://SoftElegance lookup#pragmamark - 圖像處理 Handle Image#import"GPUImageCrosshairGenerator.h"http://十字#import"GPUImageLineGenerator.h"http://線條#import"GPUImageTransformFilter.h"http://形狀變化#import"GPUImageCropFilter.h"http://剪裁#import"GPUImageSharpenFilter.h"http://銳化#import"GPUImageUnsharpMaskFilter.h"http://反遮罩銳化#import"GPUImageFastBlurFilter.h"http://模糊#import"GPUImageGaussianBlurFilter.h"http://高斯模糊#import"GPUImageGaussianSelectiveBlurFilter.h"http://高斯模糊戏阅,選擇部分清晰#import"GPUImageBoxBlurFilter.h"http://盒狀模糊#import"GPUImageTiltShiftFilter.h"http://條紋模糊,中間清晰啤它,上下兩端模糊#import"GPUImageMedianFilter.h"http://中間值奕筐,有種稍微模糊邊緣的效果#import"GPUImageBilateralFilter.h"http://雙邊模糊#import"GPUImageErosionFilter.h"http://侵蝕邊緣模糊,變黑白#import"GPUImageRGBErosionFilter.h"http://RGB侵蝕邊緣模糊变骡,有色彩#import"GPUImageDilationFilter.h"http://擴(kuò)展邊緣模糊离赫,變黑白#import"GPUImageRGBDilationFilter.h"http://RGB擴(kuò)展邊緣模糊,有色彩#import"GPUImageOpeningFilter.h"http://黑白色調(diào)模糊#import"GPUImageRGBOpeningFilter.h"http://彩色模糊#import"GPUImageClosingFilter.h"http://黑白色調(diào)模糊塌碌,暗色會(huì)被提亮#import"GPUImageRGBClosingFilter.h"http://彩色模糊渊胸,暗色會(huì)被提亮#import"GPUImageLanczosResamplingFilter.h"http://Lanczos重取樣,模糊效果#import"GPUImageNonMaximumSuppressionFilter.h"http://非最大抑制台妆,只顯示亮度最高的像素翎猛,其他為黑#import"GPUImageThresholdedNonMaximumSuppressionFilter.h"http://與上相比瓢捉,像素丟失更多#import"GPUImageSobelEdgeDetectionFilter.h"http://Sobel邊緣檢測(cè)算法(白邊,黑內(nèi)容办成,有點(diǎn)漫畫(huà)的反色效果)#import"GPUImageCannyEdgeDetectionFilter.h"http://Canny邊緣檢測(cè)算法(比上更強(qiáng)烈的黑白對(duì)比度)#import"GPUImageThresholdEdgeDetectionFilter.h"http://閾值邊緣檢測(cè)(效果與上差別不大)#import"GPUImagePrewittEdgeDetectionFilter.h"http://普瑞維特(Prewitt)邊緣檢測(cè)(效果與Sobel差不多泡态,貌似更平滑)#import"GPUImageXYDerivativeFilter.h"http://XYDerivative邊緣檢測(cè),畫(huà)面以藍(lán)色為主迂卢,綠色為邊緣某弦,帶彩色#import"GPUImageHarrisCornerDetectionFilter.h"http://Harris角點(diǎn)檢測(cè),會(huì)有綠色小十字顯示在圖片角點(diǎn)處#import"GPUImageNobleCornerDetectionFilter.h"http://Noble角點(diǎn)檢測(cè)而克,檢測(cè)點(diǎn)更多#import"GPUImageShiTomasiFeatureDetectionFilter.h"http://ShiTomasi角點(diǎn)檢測(cè)靶壮,與上差別不大#import"GPUImageMotionDetector.h"http://動(dòng)作檢測(cè)#import"GPUImageHoughTransformLineDetector.h"http://線條檢測(cè)#import"GPUImageParallelCoordinateLineTransformFilter.h"http://平行線檢測(cè)#import"GPUImageLocalBinaryPatternFilter.h"http://圖像黑白化,并有大量噪點(diǎn)#import"GPUImageLowPassFilter.h"http://用于圖像加亮#import"GPUImageHighPassFilter.h"http://圖像低于某值時(shí)顯示為黑#pragmamark - 視覺(jué)效果 Visual Effect#import"GPUImageSketchFilter.h"http://素描#import"GPUImageThresholdSketchFilter.h"http://閥值素描员萍,形成有噪點(diǎn)的素描#import"GPUImageToonFilter.h"http://卡通效果(黑色粗線描邊)#import"GPUImageSmoothToonFilter.h"http://相比上面的效果更細(xì)膩腾降,上面是粗曠的畫(huà)風(fēng)#import"GPUImageKuwaharaFilter.h"http://桑原(Kuwahara)濾波,水粉畫(huà)的模糊效果;處理時(shí)間比較長(zhǎng)碎绎,慎用#import"GPUImageMosaicFilter.h"http://黑白馬賽克#import"GPUImagePixellateFilter.h"http://像素化#import"GPUImagePolarPixellateFilter.h"http://同心圓像素化#import"GPUImageCrosshatchFilter.h"http://交叉線陰影螃壤,形成黑白網(wǎng)狀畫(huà)面#import"GPUImageColorPackingFilter.h"http://色彩丟失,模糊(類似監(jiān)控?cái)z像效果)#import"GPUImageVignetteFilter.h"http://暈影筋帖,形成黑色圓形邊緣奸晴,突出中間圖像的效果#import"GPUImageSwirlFilter.h"http://漩渦,中間形成卷曲的畫(huà)面#import"GPUImageBulgeDistortionFilter.h"http://凸起失真日麸,魚(yú)眼效果#import"GPUImagePinchDistortionFilter.h"http://收縮失真寄啼,凹面鏡#import"GPUImageStretchDistortionFilter.h"http://伸展失真,哈哈鏡#import"GPUImageGlassSphereFilter.h"http://水晶球效果#import"GPUImageSphereRefractionFilter.h"http://球形折射代箭,圖形倒立#import"GPUImagePosterizeFilter.h"http://色調(diào)分離墩划,形成噪點(diǎn)效果#import"GPUImageCGAColorspaceFilter.h"http://CGA色彩濾鏡,形成黑嗡综、淺藍(lán)乙帮、紫色塊的畫(huà)面#import"GPUImagePerlinNoiseFilter.h"http://柏林噪點(diǎn),花邊噪點(diǎn)#import"GPUImage3x3ConvolutionFilter.h"http://3x3卷積蛤高,高亮大色塊變黑蚣旱,加亮邊緣、線條等#import"GPUImageEmbossFilter.h"http://浮雕效果戴陡,帶有點(diǎn)3d的感覺(jué)#import"GPUImagePolkaDotFilter.h"http://像素圓點(diǎn)花樣#import"GPUImageHalftoneFilter.h"http://點(diǎn)染,圖像黑白化塞绿,由黑點(diǎn)構(gòu)成原圖的大致圖形#pragmamark - 混合模式 Blend#import"GPUImageMultiplyBlendFilter.h"http://通常用于創(chuàng)建陰影和深度效果#import"GPUImageNormalBlendFilter.h"http://正常#import"GPUImageAlphaBlendFilter.h"http://透明混合,通常用于在背景上應(yīng)用前景的透明度#import"GPUImageDissolveBlendFilter.h"http://溶解#import"GPUImageOverlayBlendFilter.h"http://疊加,通常用于創(chuàng)建陰影效果#import"GPUImageDarkenBlendFilter.h"http://加深混合,通常用于重疊類型#import"GPUImageLightenBlendFilter.h"http://減淡混合,通常用于重疊類型#import"GPUImageSourceOverBlendFilter.h"http://源混合#import"GPUImageColorBurnBlendFilter.h"http://色彩加深混合#import"GPUImageColorDodgeBlendFilter.h"http://色彩減淡混合#import"GPUImageScreenBlendFilter.h"http://屏幕包裹,通常用于創(chuàng)建亮點(diǎn)和鏡頭眩光#import"GPUImageExclusionBlendFilter.h"http://排除混合#import"GPUImageDifferenceBlendFilter.h"http://差異混合,通常用于創(chuàng)建更多變動(dòng)的顏色#import"GPUImageSubtractBlendFilter.h"http://差值混合,通常用于創(chuàng)建兩個(gè)圖像之間的動(dòng)畫(huà)變暗模糊效果#import"GPUImageHardLightBlendFilter.h"http://強(qiáng)光混合,通常用于創(chuàng)建陰影效果#import"GPUImageSoftLightBlendFilter.h"http://柔光混合#import"GPUImageChromaKeyBlendFilter.h"http://色度鍵混合#import"GPUImageMaskFilter.h"http://遮罩混合#import"GPUImageHazeFilter.h"http://朦朧加暗#import"GPUImageLuminanceThresholdFilter.h"http://亮度閾#import"GPUImageAdaptiveThresholdFilter.h"http://自適應(yīng)閾值#import"GPUImageAddBlendFilter.h"http://通常用于創(chuàng)建兩個(gè)圖像之間的動(dòng)畫(huà)變亮模糊效果#import"GPUImageDivideBlendFilter.h"http://通常用于創(chuàng)建兩個(gè)圖像之間的動(dòng)畫(huà)變暗模糊效果#pragmamark - 尚不清楚#import"GPUImageJFAVoroniFilter.h"#import"GPUImageVoroniConsumerFilter.h"
tip8: H264硬編碼
如果使用ijkplayer 使用硬解碼, 一句代碼即可.
// 開(kāi)啟硬解碼[option setPlayerOptionValue:@"1"forKey:@"videotoolbox"];
硬編碼的應(yīng)用場(chǎng)景: 我們要將主播的視頻數(shù)據(jù)傳送給服務(wù)器
通過(guò)攝像頭來(lái)采集圖像,然后將采集到的圖像恤批,通過(guò)硬編碼的方式進(jìn)行編碼异吻,最后編碼后的數(shù)據(jù)將其組合成H264的碼流通過(guò)網(wǎng)絡(luò)傳播。
攝像頭采集圖像, iOS系統(tǒng)提供了AVCaptureSession來(lái)采集攝像頭的圖像數(shù)據(jù). 項(xiàng)目中我是直接使用 GPUImage 中的GPUImageVideoCamera, 直接設(shè)置GPUImageVideoCamera的代理即可, 在其代理方法- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer;進(jìn)行數(shù)據(jù)編碼即可.
切記一點(diǎn): 不管是系統(tǒng)自帶的AVCaptureSession還是GPUImageVideoCamera采集到的數(shù)據(jù)都是未經(jīng)過(guò)編碼的CMSampleBuffer.
然后將采集到的數(shù)據(jù), 用iOS開(kāi)放的VideoToolbox進(jìn)行硬編碼. 關(guān)于VideoToolbox硬編解碼網(wǎng)上很多教程, 當(dāng)然最好是看Apple的官方文檔, 如果只是硬編碼, 看我的項(xiàng)目即可.
關(guān)鍵的編碼函數(shù)(來(lái)自YOLO直播負(fù)責(zé)人的開(kāi)源項(xiàng)目 BeautifyFaceDemo )
voiddidCompressH264(void*outputCallbackRefCon,void*sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags,CMSampleBufferRefsampleBuffer ){if(status !=0)return;// 采集的未編碼數(shù)據(jù)是否準(zhǔn)備好if(!CMSampleBufferDataIsReady(sampleBuffer))? ? {NSLog(@"didCompressH264 data is not ready ");return;? ? }? ? ALinH264Encoder* encoder = (__bridge ALinH264Encoder*)outputCallbackRefCon;boolkeyframe = !CFDictionaryContainsKey((CFArrayGetValueAtIndex(CMSampleBufferGetSampleAttachmentsArray(sampleBuffer,true),0)), kCMSampleAttachmentKey_NotSync);if(keyframe)// 關(guān)鍵幀{CMFormatDescriptionRefformat =CMSampleBufferGetFormatDescription(sampleBuffer);? ? ? ? size_t sparameterSetSize, sparameterSetCount;constuint8_t *sparameterSet;? ? ? ? OSStatus statusCode =CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format,0, &sparameterSet, &sparameterSetSize, &sparameterSetCount,0);if(statusCode == noErr)? ? ? ? {? ? ? ? ? ? size_t pparameterSetSize, pparameterSetCount;constuint8_t *pparameterSet;? ? ? ? ? ? OSStatus statusCode =CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format,1, &pparameterSet, &pparameterSetSize, &pparameterSetCount,0);if(statusCode == noErr)? ? ? ? ? ? {? ? ? ? ? ? ? ? encoder->sps = [NSDatadataWithBytes:sparameterSet length:sparameterSetSize];? ? ? ? ? ? ? ? encoder->pps = [NSDatadataWithBytes:pparameterSet length:pparameterSetSize];NSLog(@"sps:%@ , pps:%@", encoder->sps, encoder->pps);? ? ? ? ? ? }? ? ? ? }? ? }CMBlockBufferRefdataBuffer =CMSampleBufferGetDataBuffer(sampleBuffer);? ? size_t length, totalLength;char*dataPointer;? ? OSStatus statusCodeRet =CMBlockBufferGetDataPointer(dataBuffer,0, &length, &totalLength, &dataPointer);if(statusCodeRet == noErr) {? ? ? ? ? ? ? ? size_t bufferOffset =0;staticconstintAVCCHeaderLength=4;while(bufferOffset < totalLength -AVCCHeaderLength)? ? ? ? {? ? ? ? ? ? uint32_t NALUnitLength =0;? ? ? ? ? ? memcpy(&NALUnitLength, dataPointer + bufferOffset,AVCCHeaderLength);? ? ? ? ? ? NALUnitLength =CFSwapInt32BigToHost(NALUnitLength);NSData*data = [[NSDataalloc] initWithBytes:(dataPointer + bufferOffset +AVCCHeaderLength) length:NALUnitLength];? ? ? ? ? ? bufferOffset +=AVCCHeaderLength+ NALUnitLength;NSLog(@"sendData-->> %@ %lu", data, bufferOffset);? ? ? ? }? ? ? ? ? ? }? ? }
感觸
雖說(shuō)這個(gè)項(xiàng)目是個(gè)山寨的,?高仿的, 但是依然已經(jīng)很龐大了. 具體的細(xì)節(jié)還是需要大家自己去看我的項(xiàng)目源碼. 短短幾千字還真說(shuō)不清這么多的知識(shí)點(diǎn). blog的文章名字說(shuō)了是初窺, 還真的只是初窺, 視頻直播里面的坑太多. 且行且珍惜...
tip: 本文理論知識(shí)部分, 采集自網(wǎng)絡(luò). 請(qǐng)記住一句話talk is cheap show me the code, 重點(diǎn)在于Demo項(xiàng)目本身. 理論部分我只是一個(gè)搬運(yùn)工和總結(jié)者...
項(xiàng)目編譯環(huán)境
Xcode7(及以上)
最好是將項(xiàng)目跑在真機(jī)上. 有些地方模擬器是不支持的, 也看不到任何效果的, 比如硬編碼/智能美顏等, 這些功能模塊, 我做了限制的, 需要真機(jī)狀態(tài)才能進(jìn)行.
項(xiàng)目下載地址
請(qǐng)star和fork. 后續(xù)的bug會(huì)持續(xù)更新到github上的.
有問(wèn)題可以在簡(jiǎn)書(shū)給我留言/私信, 或者微博(簡(jiǎn)書(shū)個(gè)人上首頁(yè)有我的微博)私信我.
7月9日凌晨更新: 項(xiàng)目已經(jīng)集成視頻直播推流
blog地址詳解快速集成iOS基于RTMP的視頻推流
聯(lián)系我
小禮物走一走,來(lái)簡(jiǎn)書(shū)關(guān)注我
贊賞支持
?等9人
? 著作權(quán)歸作者所有
寫(xiě)了 12770 字诀浪,被 3932 人關(guān)注棋返,獲得了 2314 個(gè)喜歡
文能提筆控蘿莉,武能編碼調(diào)BUG
369條評(píng)論?只看作者
47樓 · 2016.07.07 09:38
666
71樓 · 2016.07.07 17:22
clang: error: linker command failed with exit code 1 (use -v to see invocation)
出現(xiàn)這個(gè)錯(cuò)誤是為什么
151樓 · 2016.07.29 15:07
在網(wǎng)絡(luò)信號(hào)弱的情況下如何保證視頻質(zhì)量呢雷猪?直播開(kāi)發(fā)技術(shù)交流群:183331015 請(qǐng)高手指教 謝謝
?可以做些處理睛竣,比如 一般CDN廠商提供的SDK都會(huì)稍作處理,ijkplayer的話求摇,需要自己改射沟。
https://github.com/daniulive/SmarterStreaming?可以看看這個(gè)
推送還好,播放的話与境,想做個(gè)好的播放器验夯,還是很難,目前大多數(shù)開(kāi)源改的直播播放器摔刁,延遲和穩(wěn)定性都控制的不太好
2017.04.28 09:51??回復(fù)
209樓 · 2016.09.11 17:34
贊博主大神挥转!請(qǐng)大神 進(jìn)群指導(dǎo)交流,直播開(kāi)發(fā)技術(shù)交流群:183331015 謝謝 博主
251樓 · 2017.03.03 08:29
ld: library not found for -lAFNetworking
clang: error: linker command failed with exit code 1 (use -v to see invocation) 報(bào)錯(cuò)
258樓 · 2017.04.19 10:35
給我報(bào)的3個(gè)錯(cuò)誤,歸類是Apple Mach-O Linker (Id) Error, 1."operator delete(void*)", referenced from: 2."operator new(unsigned long)", referenced from: 3.Linker command failed with exit code 1 (use -v to see invocation) 這3個(gè)
?我打包好,合并完模擬器和真機(jī)的framework啦...還是這樣
背鍋蝦:
?解決了嗎共屈,我也是遇到這情況
2017.08.02 10:59??回復(fù)
?按照說(shuō)明绑谣,將Framework打包并復(fù)制到指定文件夾下之后,還需要在項(xiàng)目中做關(guān)聯(lián)才可以趁俊,在 Build Phases的Link Binary里添加指定的Framework~
2017.08.25 18:57??回復(fù)
?缺少這個(gè)依賴庫(kù):libc++.tbd 在Link Binary加上就行了
2018.02.16 21:52??回復(fù)
2樓 · 2016.07.06 07:11
贊
??
3樓 · 2016.07.06 09:54
666
4樓 · 2016.07.06 10:03
666
5樓 · 2016.07.06 10:04
666剛好公司要開(kāi)始搞直播域仇,幫助很大
?@薛定諤的code?你們打算用第三方SDK嗎刑然?好用么
2016.09.12 10:03??回復(fù)
?@一位農(nóng)民工?有的領(lǐng)導(dǎo)啥也不懂就是嫌貴寺擂,,泼掠,
2016.09.24 12:25??回復(fù)
?我們公司也開(kāi)始寫(xiě)直播怔软,沒(méi)有接觸過(guò),兩位大神寫(xiě)的怎么樣了择镇,給小弟點(diǎn)建議啊
2016.12.07 11:14??回復(fù)
?添加新評(píng)論?還有3條評(píng)論挡逼,?展開(kāi)查看
被以下專題收入,發(fā)現(xiàn)更多相似內(nèi)容
面試題
iOS 開(kāi)發(fā)?
首頁(yè)投稿(暫停...
????個(gè)人喜歡腻豌,收藏
iOS
iOS進(jìn)階
iOS開(kāi)發(fā)技巧
推薦閱讀更多精彩內(nèi)容
iOS:Touch ID簡(jiǎn)易開(kāi)發(fā)教程-仿alipay
效果圖 前言 2013年9月家坎,蘋(píng)果為當(dāng)時(shí)發(fā)布的最新iPhone產(chǎn)品配備了一系列硬件升級(jí)方案。在iPhone 5s當(dāng)中吝梅,最具創(chuàng)新特性的機(jī)制無(wú)疑要數(shù)圍繞Home按鈕設(shè)計(jì)的超薄金屬圈虱疏,也就是被稱為T(mén)ouch ID的指紋傳感器。這套Local Authentication框架能夠輕松實(shí)現(xiàn)用戶身份驗(yàn)證苏携,大家可以利用它來(lái)完成應(yīng)用程序的登錄機(jī)制或者通過(guò)它保護(hù)應(yīng)用程序當(dāng)中的敏感數(shù)據(jù)做瞪。 教程 1.導(dǎo)入對(duì)應(yīng)的框架頭文件 剛才我們說(shuō)到,Touch ID指紋傳感器所屬Local Authentication框架.所以,第一步,我們需要導(dǎo)入頭文件 2.判斷設(shè)置是否支持Touch ID 或者 本機(jī)是否已經(jīng)錄入指紋 ...
前言 斷斷續(xù)續(xù)的已經(jīng)學(xué)習(xí)Swift一年多了, 從1.2到現(xiàn)在的2.2, 一直在語(yǔ)法之間徘徊, 學(xué)一段時(shí)間, 工作一忙, 再撿起來(lái)隔段時(shí)間又忘了.思來(lái)想去, 趁著這兩個(gè)月加班不是特別多, 就決定用swift仿寫(xiě)一個(gè)完整項(xiàng)目. 個(gè)人文字功底有限, 就我而言, 這款A(yù)PP做的挺唯美的... github地址 github地址 聲明 此花田小憩項(xiàng)目里面的都是真實(shí)接口, 真實(shí)數(shù)據(jù), 僅供學(xué)習(xí), 毋作其他用途!!! 項(xiàng)目部分截圖 由于項(xiàng)目的大體功能都已經(jīng)實(shí)現(xiàn)了的, 所以整個(gè)項(xiàng)目還是比較龐大的.所以, 下面羅列部分功能的截圖.由于gif錄制的時(shí)候, 會(huì)重新渲染一遍圖片, 所以導(dǎo)致項(xiàng)目中用到高斯模糊的地...
【評(píng)論你的名字】為你寫(xiě)三行情書(shū)
為你寫(xiě)詩(shī)評(píng)論規(guī)則: 1. 只能評(píng)論名字,統(tǒng)一帶姓。 2. 我會(huì)回復(fù)屬于你名字的三行詩(shī)装蓬。 3. 都是原創(chuàng)著拭,如有類似,算我抄襲牍帚。 4. 涵養(yǎng)有限儡遮,作品不喜勿噴。 5. 精力有限暗赶,回復(fù)時(shí)間不定峦萎。 其他: 認(rèn)同以上五則,期待留名忆首。 只是一個(gè)人在寫(xiě)爱榔,對(duì)我而言工作量會(huì)很巨大。 故回復(fù)期限無(wú)法保證糙及,望諒解详幽。 朋友們?nèi)缛粝埠靡部蓪?xiě)詩(shī)回復(fù)評(píng)論名字。 不用私信問(wèn)我浸锨,謝謝啦唇聘。
今天我的選擇或許哪天也會(huì)成為你的選擇迟郎!——曉多 01 此刻,我坐在新的辦公室里聪蘸,寬敞明亮宪肖,整理好一些交接的文件,加班完成了一篇材料健爬,靜靜的坐下來(lái)喝了一口水控乾。 打開(kāi)電腦來(lái)寫(xiě)這篇原本幾天就應(yīng)該動(dòng)筆的文章,為自己曾經(jīng)的生活畫(huà)上一個(gè)句號(hào)娜遵,然后一切清零重新開(kāi)始蜕衡。 而幾天前我還在待了二十多年的小城市,官方的全國(guó)排名情況公布之后设拟,這個(gè)我長(zhǎng)大的豫北小城市已經(jīng)成了五線城市慨仿。 以上學(xué)為界,大學(xué)前的十多年在這里長(zhǎng)大纳胧,這里不是我的祖籍卻是我的家镰吆。 畢業(yè)那年我回來(lái)過(guò),在當(dāng)?shù)氐膱?bào)社實(shí)習(xí)躲雅,雖然沒(méi)有基本工資但僅靠稿費(fèi)就已經(jīng)超過(guò)了不少記者鼎姊,一張報(bào)紙有時(shí)會(huì)有五篇稿子是我寫(xiě)的,經(jīng)常上頭版頭條。在報(bào)社招考的時(shí)候就知道能留下來(lái)相寇,...
《變形計(jì)》究竟給農(nóng)村孩子帶來(lái)了什么慰于?
母親這是第一次看著節(jié)目哭了整場(chǎng),稀里嘩啦的比平時(shí)我們和她發(fā)生爭(zhēng)執(zhí)的時(shí)候還動(dòng)情唤衫。 頭一次主動(dòng)叫我們老實(shí)坐在電視前婆赠,認(rèn)真的觀看節(jié)目,我們有時(shí)候看的笑了佳励,她還嚴(yán)肅的告訴我們不許笑休里!要體會(huì)不易。 01 《變形計(jì)》的故事結(jié)構(gòu)簡(jiǎn)單赃承,就是性格乖張的城市富二代和生活在邊遠(yuǎn)山區(qū)家庭落魄的農(nóng)二代互換生活的故事妙黍。 再簡(jiǎn)單不過(guò)的人設(shè)和最極致的環(huán)境設(shè)定,注定讓節(jié)目充滿著憤恨瞧剖、憐惜拭嫁、諒解、溫情和希望抓于。 小時(shí)候把《變形計(jì)》當(dāng)娛樂(lè)節(jié)目看做粤,總覺(jué)得正義上來(lái)了,想把城市小孩揍一圈捉撮,讓他不那么囂張怕品;又看著農(nóng)村小孩對(duì)新世界的驚訝眼神,倍感憂傷巾遭。 我也是一個(gè)多愁善感的人肉康,說(shuō)我是個(gè)憤青也不過(guò)分。這種貧富差異巨大的交換生活恢总,也顛覆了我...
https://github.com/ForIos/MiaoShow
?LLIOS
視頻直播初窺:高仿<喵播APP> 轉(zhuǎn)載作者 Monkey_ALin一文 效果圖 會(huì)持續(xù)發(fā)布直播方面的資料 正在做直播的或?qū)χ辈ビ信d趣的可進(jìn)直播交流群:183331015 共同學(xué)習(xí)探討 由于licecap錄制的GIF失幀太嚴(yán)重, 都模糊掉了, 再放兩張高清截圖 png1 前言...
?moon_hj
如何開(kāi)發(fā)出一款仿映客直播APP項(xiàng)目實(shí)踐篇 -【原理篇】
前言:每個(gè)成功者多是站在巨人的肩膀上迎罗!在做直播開(kāi)發(fā)時(shí) 碰到了很多問(wèn)題,在收集了許多人博客的基礎(chǔ)上做出來(lái)了成功的直播項(xiàng)目并做了整理片仿,并在最后奉上我的全部代碼。 其中采用博客的博主開(kāi)篇在此感謝尤辱,本著開(kāi)源分享的精神砂豌,我會(huì)將前輩的知識(shí)和自己開(kāi)發(fā)中遇到的問(wèn)題整理出完整的一套開(kāi)發(fā)流程,...
?遠(yuǎn)處山谷來(lái)的清風(fēng)
【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(原理篇)
目錄 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(原理篇) 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(播放篇) 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(采集篇) 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(美顏篇) 前言 大半年沒(méi)寫(xiě)博客了光督,但我一直關(guān)注著互聯(lián)網(wǎng)...
?袁崢
【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(原理篇)
目錄 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(原理篇) 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(播放篇) 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(采集篇) 【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(美顏篇) 前言 大半年沒(méi)寫(xiě)博客了阳距,但我一直關(guān)注著互聯(lián)網(wǎng)...
?小新xin
“鈴……鈴…”凌晨?jī)牲c(diǎn)一陣急促的警鈴聲在三號(hào)消防站響起,不等鈴聲響第二遍结借,他已經(jīng)從床上騰將起來(lái)筐摘,大喝一聲“出警”,其他隊(duì)員一個(gè)個(gè)都打了個(gè)激靈,迅速地穿上隔熱服咖熟,蹬起消防膠靴圃酵,緊接著聽(tīng)到腳步聲快速移動(dòng),忙而不亂馍管,他一個(gè)箭步率先抱上滑桿郭赐,后面的隊(duì)員有序緊跟,幾乎是同一時(shí)刻同樣的...
?風(fēng)吹十月
豐碩人生——30天超級(jí)孵化營(yíng)總結(jié)
1确沸、30天的孵化營(yíng)很快過(guò)去了捌锭,自己收獲多多,首先讓我看到系統(tǒng)的強(qiáng)大罗捎,也感受到了老師們的自律和付出观谦,也感受到了我們系統(tǒng)情商高的人很多,也感受到了自己的不足. 2桨菜、這次超級(jí)孵化營(yíng)的學(xué)習(xí)坎匿,讓我學(xué)習(xí)到很多知識(shí),每日干貨雷激,快樂(lè)前進(jìn)老師教的很細(xì)致替蔬,感受到老師時(shí)間規(guī)劃真好,效率真高屎暇,自己...
?豐碩人生
關(guān)于ScrollView上放滑動(dòng)控件響應(yīng)問(wèn)題
在項(xiàng)目開(kāi)發(fā)時(shí)遇到一個(gè)問(wèn)題承桥,我在UIViewController上面直接創(chuàng)建了一個(gè)UIScrollView,把UIScrollerView作為一個(gè)子視圖添加到了UIViewController根悼, 又再UIScrollerView中添加了一個(gè)UISlider的組件凶异,在手勢(shì)滑動(dòng)的...
?Johnny_Chang
1. 這兩天和好友M聊天,她說(shuō)挤巡,感覺(jué)壓力太大剩彬,快撐不住了。 注冊(cè)會(huì)計(jì)師聽(tīng)起來(lái)光鮮亮麗有逼格矿卑,個(gè)種苦楚喉恋,也只有身在其中的人,才能感同身受母廷。加班出差是常態(tài)轻黑,年度審計(jì)更是高強(qiáng)度,高壓力琴昆,一個(gè)人哪怕化身三頭六臂氓鄙,也是焦頭爛額。 我說(shuō)业舍,堅(jiān)持一下抖拦,過(guò)了年審升酣,就好些了。新的項(xiàng)目你第一次接...
?蝦米米