欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

零基础学习iOS直播之采集

程序员文章站 2024-02-13 09:34:59
直播的采集由采集的设备(摄像头、话筒)不同分为视频采集和音频采集,本篇文章会分别介绍。 1.采集步骤 创建捕捉会话(avcapturesession),ios调...

直播的采集由采集的设备(摄像头、话筒)不同分为视频采集和音频采集,本篇文章会分别介绍。

1.采集步骤

  1. 创建捕捉会话(avcapturesession),ios调用相机和话筒之前都需要创建捕捉对话,把输入输出设备添加进对话中。
  2. 往会话中添加视频输入对象(avcapturedeviceinput)。
  3. 往会话中添加音频输入对象(avcapturedeviceinput)。
  4. 往会话中添加视频输出对象(avcapturevideodataoutput)。
  5. 往会话中添加音频输出对象(avcaptureaudiodataoutput)。
  6. 添加视屏预览图层(avcapturevideopreviewlayer)。
  7. 开启会话。
  8. 推流(以后讲)。

2.效果图

零基础学习iOS直播之采集

这是后置摄像头采集的,直播一般用前置摄像头的,但是我实在没勇气放出我的自拍????。

3.代码演示

// 采集
- (void)setupcaputurevideo {
 // 1.创建捕获对话,必须要强引用,否则会释放
 _capturesession = [[avcapturesession alloc] init];
 // 2.捕获摄像头设备,默认前置摄像头
 avcapturedevice *videodevice = [self getvideodevice:avcapturedevicepositionfront];
 // 3.获取声音设备
 avcapturedevice *audiodevice = [avcapturedevice defaultdevicewithmediatype:avmediatypeaudio];
 // 4.创建对应视频设备输入对象
 _currentvideodeviceinput = [avcapturedeviceinput deviceinputwithdevice:videodevice error:nil];
 // 5.创建对应音频设备输入对象
 avcapturedeviceinput *audiodeviceinput = [avcapturedeviceinput deviceinputwithdevice:audiodevice error:nil];
 // 6.添加到会话中 注意:最好要判断是否能添加输入,会话不能添加空的
 // 6.1 添加视频
 if ([_capturesession canaddinput:_currentvideodeviceinput]) {
 [_capturesession addinput:_currentvideodeviceinput];
 }
 // 6.2 添加音频
 if ([_capturesession canaddinput:audiodeviceinput]) {
 [_capturesession addinput:audiodeviceinput];
 }
 // 7.捕获视频数据输出设备
 avcapturevideodataoutput *videooutput = [[avcapturevideodataoutput alloc] init];
 //7.1 设置代理, 捕获视频样品数据
 dispatch_queue_t videoqueue = dispatch_queue_create("video capure queue", dispatch_queue_serial);
 [videooutput setsamplebufferdelegate: self queue:videoqueue];
 // 8.设置音频数据输出设备
 avcaptureaudiodataoutput *audiooutput = [[avcaptureaudiodataoutput alloc] init];
 // 8.1 设置代理,捕获音频样品数据 注意:必须是串行队列才能捕获到数据,而且不能为空
 dispatch_queue_t audioqueue = dispatch_queue_create("audio capure queue", dispatch_queue_serial);
 [audiooutput setsamplebufferdelegate:self queue:audioqueue];
 // 9.添加到会话中 注意:最好要判断是否能添加输入,会话不能添加空的
 if ([_capturesession canaddoutput:videooutput]) {
 [_capturesession addoutput:videooutput];
 }
 if ([_capturesession canaddoutput:audiooutput]) {
 [_capturesession addoutput:audiooutput];
 }
 // 10.获取视屏输入与输出连接,用于分辨音视频数据
 _videoconnection = [videooutput connectionwithmediatype:avmediatypevideo];
 // 11.添加视屏预览图层
 _previewdlayer = [avcapturevideopreviewlayer layerwithsession:_capturesession];
 _previewdlayer.frame = [uiscreen mainscreen].bounds;
 [self.view.layer insertsublayer:_previewdlayer atindex:0];
 // 12.开启会话
 [_capturesession startrunning];
}
// 根据摄像头方向获取摄像头
- (avcapturedevice *)getvideodevice: (avcapturedeviceposition)position {
 nsarray *devices = [avcapturedevice deviceswithmediatype:avmediatypevideo];
 for (avcapturedevice *device in devices) {
 if (device.position == position) {
 return device;
 }
 }
 return nil;
}

分析:

(1)摄像头:每个手机都有且仅有两个摄像头,前置摄像头和后置摄像头,包括iphone 7 plus,它后面的两个摄像头统称为后置摄像头。所以获取的是摄像头数组,我们根据摄像头的方向获取指定的摄像头。对话里只能有一个摄像头设备。

(2)摄像头方向(avcapturedeviceposition):是一个枚举,有三个值可选择。不过如果选择

avcapturedevicepositionunspecified,那么是不能调用摄像头的。
typedef ns_enum(nsinteger, avcapturedeviceposition) {
 avcapturedevicepositionunspecified = 0, // 不指定
 avcapturedevicepositionback = 1, //后置
 avcapturedevicepositionfront = 2 // 前置
}

(3)代理:avcapturevideodataoutputsamplebufferdelegate, avcaptureaudiodataoutputsamplebufferdelegate,分别为视频和音频输出设备对象的代理,两个代理都有下面的方法:

// 获取输出设备数据,有可能是音频,有可能是视频
- (void)captureoutput:(avcaptureoutput *)captureoutput didoutputsamplebuffer:(cmsamplebufferref)samplebuffer fromconnection:(avcaptureconnection *)connection {
 if (_videoconnection == connection) {
 nslog(@"采集到视屏数据");
 }else {
 nslog(@"采集到音频数据");
 }
}

4.切换摄像头

#pragma mark - 切换摄像头
- (ibaction)togglecapture:(id)sender {
 // 1.获取当前设备方向
 avcapturedeviceposition cureentposition = _currentvideodeviceinput.device.position;
 // 2.获取需要改变的方向
 avcapturedeviceposition toggleposition = (cureentposition == avcapturedevicepositionfront ? avcapturedevicepositionback : avcapturedevicepositionfront);
 // 3.获取需要改变的摄像头设备
 avcapturedevice *toggledevice = [self getvideodevice:toggleposition];
 // 4.获取需要改变的摄像头输入设备
 avcapturedeviceinput *toggledeviceinput = [[avcapturedeviceinput alloc] initwithdevice:toggledevice error:nil];
 // 5.停止会话,否则会有一瞬间的白屏
 [_capturesession stoprunning];
 // 6.移除之前的摄像头输入设备,否则会崩溃,因为会话里只能有一个摄像头设备
 [_capturesession removeinput:_currentvideodeviceinput];
 // 7.添加新的摄像头输入设备
 [_capturesession addinput:toggledeviceinput];
 // 8.重新开始会话
 [_capturesession startrunning];
 // 记录当前摄像头输入设备
 //9.重新开始
 _currentvideodeviceinput = toggledeviceinput;
}

demo里还有其他的功能,但是感觉没什么太大用处,就不讲了,有兴趣的可以去我的github上下载看看。

demo下载

demo下载地址。下载下来运行,发现报错。

零基础学习iOS直播之采集

那是因为我没有在工程里上传ijkplayer视屏直播框架,我能上传上去,但下载太慢了,什么原因大家都懂得。我把ijkplayer视屏直播框架放到百度云上了,没有密码,下载下来之后,放到liveappdemo-master文件夹里,重新打开就可以运行了。

零基础学习iOS直播之采集

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!