音視頻采集

1跃须、iOS直播技術(shù)的流程

   直播技術(shù)的流程大致可以分為幾個(gè)步驟:數(shù)據(jù)采集眷篇、圖像處理(實(shí)時(shí)濾鏡)座咆、視頻編碼徽惋、封包案淋、上傳座韵、云端(轉(zhuǎn)碼险绘、錄制、分發(fā))誉碴、直播播放器宦棺。  

數(shù)據(jù)采集:通過攝像頭和麥克風(fēng)獲得實(shí)時(shí)的音視頻數(shù)據(jù);
圖像處理:將數(shù)據(jù)采集的輸入流進(jìn)行實(shí)時(shí)濾鏡黔帕,得到我們美化之后的視頻幀代咸;
視頻編碼:編碼分為軟編碼和硬編碼。現(xiàn)在一般的編碼方式都是H.264成黄,比較新的H.265據(jù)說壓縮率比較高呐芥,但算法也相當(dāng)要復(fù)雜一些逻杖,使用還不夠廣泛。軟編碼是利用CPU進(jìn)行編碼思瘟,硬編碼就是使用GPU進(jìn)行編碼荸百,軟編碼支持現(xiàn)在所有的系統(tǒng)版本,由于蘋果在iOS8才開放硬編碼的API滨攻,故硬編碼只支持iOS8以上的系統(tǒng)够话;
封包:現(xiàn)在直播推流中,一般采用的格式是FLV光绕;
上傳:常用的協(xié)議是利用RTMP協(xié)議進(jìn)行推流女嘲;
云端:進(jìn)行流的轉(zhuǎn)碼、分發(fā)和錄制诞帐;
直播播放器:負(fù)責(zé)拉流欣尼、解碼、播放停蕉。

用一張騰訊云的圖來說明上面的流程:

2014909-fc4efbc9b1ffdd45.png

2媒至、獲取系統(tǒng)的授權(quán)
直播的第一步就是采集數(shù)據(jù),包含視頻和音頻數(shù)據(jù)谷徙,由于iOS權(quán)限的要求拒啰,需要先獲取訪問攝像頭和麥克風(fēng)的權(quán)限:

請(qǐng)求獲取訪問攝像頭權(quán)限

__weak typeof(self) _self = self; 
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; 
switch (status) { 
       case AVAuthorizationStatusNotDetermined:{ 
          // 許可對(duì)話沒有出現(xiàn),發(fā)起授權(quán)許可
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { 
               if (granted) { 
                   dispatch_async(dispatch_get_main_queue(), ^{ 
                          [_self.session setRunning:YES];
                    }); 
                } 
              }]; 
              break; 
        } 
       case AVAuthorizationStatusAuthorized:{ 
         // 已經(jīng)開啟授權(quán)完慧,可繼續(xù)
            [_self.session setRunning:YES]; 
             break; 
       } 
      case AVAuthorizationStatusDenied: 
      case AVAuthorizationStatusRestricted: 
      // 用戶明確地拒絕授權(quán)谋旦,或者相機(jī)設(shè)備無法訪問 
            break; 
       default: 
             break; 
  }

請(qǐng)求獲取訪問麥克風(fēng)權(quán)限

AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    switch (status) {
        case AVAuthorizationStatusNotDetermined:{
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
            }];
            break;
        }
        case AVAuthorizationStatusAuthorized:{
            break;
        }
        case AVAuthorizationStatusDenied:
        case AVAuthorizationStatusRestricted:
            break;
        default:
            break;
    }

3、配置采樣參數(shù)

音頻:需要配置碼率屈尼、采樣率册着;
視頻:需要配置視頻分辨率、視頻的幀率脾歧、視頻的碼率甲捏。
4、音視頻的錄制
音頻的錄制

self.taskQueue = dispatch_queue_create("audioCapture.Queue",NULL);
      AVAudioSession  *session = [AVAudioSession sharedInstance];
      [session setActive:YES withOptions:kAudioSessionSetActiveFlag_NotifyOthersOnDeactivation error:nil];
      [[NSNotificationCenter defaultCenter] addObserver:self 
                                               selector: @selector(handleRouteChange:)
                                                   name: AVAudioSessionRouteChangeNotification
                                                 object:session];
[[NSNotificationCenter defaultCenter] addObserver:self 
                                               selector: @selector(handleInterruption:)
                                                   name: AVAudioSessionInterruptionNotification
                                                 object:session];
       NSError *error = nil;
      [session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers error:nil];
      [session setMode:AVAudioSessionModeVideoRecording error:&error];
      if(![session setActive:YES error:&error]){
          [self handleAudioComponentCreationFailure];
      }
      AudioComponentDescription acd;
       acd.componentType = kAudioUnitType_Output;
       acd.componentSubType = kAudioUnitSubType_RemoteIO;
       acd.componentManufacturer = kAudioUnitManufacturer_Apple;
       acd.componentFlags = 0;
       acd.componentFlagsMask = 0;
       self.component = AudioComponentFindNext(NULL, &acd);
       OSStatus status = noErr;
       status = AudioComponentInstanceNew(self.component, &_componetInstance);
       if (noErr != status) {
           [self handleAudioComponentCreationFailure];
       }
       UInt32 flagOne = 1;
       AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flagOne, sizeof(flagOne));
       AudioStreamBasicDescription desc = {0};
       desc.mSampleRate = _configuration.audioSampleRate;
       desc.mFormatID = kAudioFormatLinearPCM;
       desc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
       desc.mChannelsPerFrame = (UInt32)_configuration.numberOfChannels;
       desc.mFramesPerPacket = 1;
       desc.mBitsPerChannel = 16;
       desc.mBytesPerFrame = desc.mBitsPerChannel / 8 * desc.mChannelsPerFrame;
       desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;
       AURenderCallbackStruct cb; 
       cb.inputProcRefCon = (__bridge void *)(self); 
       cb.inputProc = handleInputBuffer; 
       status = AudioUnitSetProperty(self.componetInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &desc, sizeof(desc)); 
       status = AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, sizeof(cb)); 
       status = AudioUnitInitialize(self.componetInstance); 
       if (noErr != status) { 
            [self handleAudioComponentCreationFailure]; 
        } 
       [session setPreferredSampleRate:_configuration.audioSampleRate error:nil]; 
       [session setActive:YES error:nil];





視頻的錄制:調(diào)用GPUImage中的GPUImageVideoCamera

_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:_configuration.avSessionPreset cameraPosition:AVCaptureDevicePositionFront];
_videoCamera.outputImageOrientation = _configuration.orientation; 
_videoCamera.horizontallyMirrorFrontFacingCamera = NO; 
_videoCamera.horizontallyMirrorRearFacingCamera = NO; 
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate; 
_gpuImageView = [[GPUImageView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 
[_gpuImageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill]; [_gpuImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; [_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];


轉(zhuǎn)載自:https://chenhu1001.github.io

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鞭执,一起剝皮案震驚了整個(gè)濱河市司顿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兄纺,老刑警劉巖大溜,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異估脆,居然都是意外死亡钦奋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來付材,“玉大人朦拖,你說我怎么就攤上這事⊙嵯危” “怎么了贞谓?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長葵诈。 經(jīng)常有香客問我裸弦,道長,這世上最難降的妖魔是什么作喘? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮泞坦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贰锁。我一直安慰自己,他們只是感情好豌熄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布授嘀。 她就那樣靜靜地躺著,像睡著了一般锣险。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上芯肤,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音崖咨,去河邊找鬼锻拘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛击蹲,可吹牛的內(nèi)容都是我干的署拟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芯丧,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤骗露,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后萧锉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柿隙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年鲫凶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禀崖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片螟炫。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昼钻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情然评,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布碗淌,位于F島的核電站,受9級(jí)特大地震影響贯莺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缕探,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爹耗。 院中可真熱鬧,春花似錦潭兽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枚碗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肮雨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工怨规, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人波丰。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像呀舔,于是被迫代替她去往敵國和親弥虐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 學(xué)習(xí)過音視頻的都知道霜瘪,不常用的話就會(huì)容易忘記。因此颖对,記下以前學(xué)些的點(diǎn)滴。(這不是入門貼) 主要分為以下主題做學(xué)習(xí)記...
    vedon_fu閱讀 7,168評(píng)論 9 18
  • 項(xiàng)目暫時(shí)告一段落缤底,也是一知半解番捂,不過我的分享可以幫助我這樣菜鳥了个唧。先來下知識(shí)結(jié)構(gòu): 1设预、h264 視頻編碼處理的最...
    JiangSy閱讀 4,365評(píng)論 4 12
  • iOS視頻直播---主要的概念(一) 第一部分: 視頻采集----AVCaptureSession 1.1 視頻采...
    simuty閱讀 3,131評(píng)論 3 16
  • 學(xué)校是孩子一天當(dāng)中最重要的活動(dòng)場所,我們做家長的都認(rèn)為學(xué)校是最安全的地方宾符∧鸾眨可是誰成想最安全的地方也是最危險(xiǎn)的...
    fuwl閱讀 300評(píng)論 0 0
  • 今天是第二天魏烫,上午團(tuán)建肝箱,雖然第三名,但大家都盡力了狭园!老師說成績不是最重要的读处,重在參與糊治。在一上午的活動(dòng)中罚舱,大...
    伽有兒女閱讀 196評(píng)論 0 1