iOS視音頻采集(一)

前言

這是一個關(guān)于視音頻的系列文章蹲坷,代碼不追求質(zhì)量坷剧,只把我認(rèn)為最關(guān)鍵的部分提取出來浦夷,旨在方便學(xué)習(xí)辖试,所以不建議直接用在項目之中。
本篇文章主要參考自:ObjC 中國

視頻資源獲取
UIImagePickerController使用

if UIImagePickerController.isSourceTypeAvailable(.camera) {
    let imageVc = UIImagePickerController.init()
    imageVc.sourceType = .camera
    imageVc.mediaTypes = [kUTTypeMovie as String]
    imageVc.videoQuality = .typeHigh
    imageVc.delegate = self;
    self.present(imageVc, animated: true, completion: nil)
}

AVFoundation視音頻采集
AVCaptureDevice -> AVCaptureDeviceInput -> AVCaptureSession

  AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
  self.captureSession = captureSession;
  // 攝像頭設(shè)備配置
  AVCaptureDevice *cameraDevice;
  NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
  for (AVCaptureDevice *device in devices) {
    if (device.positon == AVCaptureDevicePositionBack) {
        cameraDevice = device;
    }
  }
  AVCaptureDeviceInput *cameraDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:cameraDevice error:nil];
  // 麥克風(fēng)設(shè)備配置
  AVAudioSession *audioSession = [AVAudioSession shareInstance];
  [audioSession setCategory:AVAudioSessionCategoryPlayBack error:nil];
  NSArray *inputs = [audioSession availableInputs];
  AVAudioSessionPortDescription *builtInMic = nil;
  for (AVAudioSessionPortDescription *port in inputs) {
    if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
        builtInMic = port;
        break;
    }
  }
  for (AVAudioSessionDataSourceDescription *source in builtInMic.dataSources) {
    if ([source.orientation isEqualToString:AVAudioSessionOrientationFront]) {
        [builtInMic setPreferredDataSource:source error:nil];
        [audioSession setPreferredInput:builtInMic error:nil];
        break;
    }
  }
  AVCaptureDeviceInput *micDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio] error:nil];
  if ([captureSession canAddInput:cameraDeviceInput]) {
    [captureSession addInput:cameraDeviceInput];
  }
  if ([captureSession canAddInput:micDeviceInput]) {
    [captureSession addInput:micDeviceInput];
  }
  AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession];
  previewLayer.frame = self.view.bounds;
  [self.view.layer insertSublayer:previewLayer atIndex:0];
  self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;
  [self.captureSession startRunning];

FileOutput視音頻文件輸出
AVCaptureSession -> AVCaptureMovieFileOutput

AVCaptureMovieFileOutput *movieFileOutput = [AVCaptureMovieFileOutput new];
if ([self.captureSession canAddOutput:movieFileOutput]) {
    [self.captureSession addOutput:movieFileOutput];
}
// 開始錄像
[self.movieFileOutput startRecordingToOutputFileURL:url recordingDelegate:self];
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error {
    // 錄像結(jié)束后調(diào)用
}

Writer視音頻輸出
captureSession -> captureVideo(or Audio)DataOutput
assetWriter -> assetWriterInput
captureSession 和 writer是平級劈狐,不需要關(guān)聯(lián)

// Output
AVCaptureVideoDataOutput *videoDataOutput = [AVCaptureVideoDataOutput new];
videoDataOutput.alwaysDiscardsLateVideoFrames = NO;
[videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
videoDataOutput.videoSettings = nil;
[self.captureSession addOutput:videoDataOutput];
self.videoConnection = [videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
self.videoSettings = [videoDataOutput recommendedVideoSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie];

AVCaptureAudioDataOutput *audioDataOutput = [AVCaptureAudioDataOutput new];
[audioDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[self.captureSession addOutput:audioDataOutput];
self.audioConnection = [audioDataOutput connectionWithMediaType:AVMediaTypeAudio];
self.audioSettings = [audioDataOutput recommendedAudioSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie];
// Writer
AVAssetWriter *write = [[AVAssetWriter alloc] initWithURL:url fileType:AVFileTypeQuickTimeMovie error:nil];
    
AVAssetWriterInput *videoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:self.videoSettings];
videoInput.expectsMediaDataInRealTime = YES;
videoInput.transform = CGAffineTransformMakeRotation(M_PI_2);
if ([write canAddInput:videoInput]) {
    [write addInput:videoInput];
    self.videoInput = videoInput;
}

AVAssetWriterInput *audioInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:self.audioSettings];
audioInput.expectsMediaDataInRealTime = YES;
if ([write canAddInput:audioInput]) {
    [write addInput:audioInput];
    self.audioInput = audioInput;
}
self.writer = write;
BOOL success = [self.writer startWriting];
if (!success) {
    NSError *error = self.writer.error;
    NSLog(@"error ---------- %@", error);
}

視頻開始采集后需要在DataOutput的代理方法中使用writerInput采集buffer罐孝。
使用writer采集數(shù)據(jù)可定制性更高。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肥缔,一起剝皮案震驚了整個濱河市莲兢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌续膳,老刑警劉巖改艇,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坟岔,居然都是意外死亡遣耍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門炮车,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舵变,“玉大人,你說我怎么就攤上這事瘦穆〖拖叮” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵扛或,是天一觀的道長绵咱。 經(jīng)常有香客問我,道長熙兔,這世上最難降的妖魔是什么悲伶? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮住涉,結(jié)果婚禮上麸锉,老公的妹妹穿的比我還像新娘。我一直安慰自己舆声,他們只是感情好花沉,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布柳爽。 她就那樣靜靜地躺著,像睡著了一般碱屁。 火紅的嫁衣襯著肌膚如雪磷脯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天娩脾,我揣著相機(jī)與錄音赵誓,去河邊找鬼。 笑死柿赊,一個胖子當(dāng)著我的面吹牛架曹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闹瞧,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼展辞!你這毒婦竟也來了奥邮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤罗珍,失蹤者是張志新(化名)和其女友劉穎洽腺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體覆旱,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡蘸朋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扣唱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片藕坯。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖噪沙,靈堂內(nèi)的尸體忽然破棺而出炼彪,到底是詐尸還是另有隱情,我是刑警寧澤正歼,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布辐马,位于F島的核電站,受9級特大地震影響局义,放射性物質(zhì)發(fā)生泄漏喜爷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一萄唇、第九天 我趴在偏房一處隱蔽的房頂上張望檩帐。 院中可真熱鬧,春花似錦另萤、人聲如沸轿塔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勾缭。三九已至揍障,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間俩由,已是汗流浹背毒嫡。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留幻梯,地道東北人兜畸。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像碘梢,于是被迫代替她去往敵國和親咬摇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

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