应用中构建自定义相机UI捕获媒体需要用到AVFoundation Capture
应用中调用系统相机UI捕获媒体则用到 UIImagePickerController

Steps

捕获体系结构的主要部分是会话,输入和输出:捕获会话将一个或多个输入连接到一个或多个输出。输入是媒体源,包括内置于iOS设备或Mac中的摄像头和麦克风等捕获设备。输出从输入获取媒体以产生有用的数据,例如写入磁盘的电影文件或可用于实时处理的原始像素缓冲区。

  • 检查授权Requesting Authorization for Media Capture
  • 创建媒体捕捉会话
  • 创建媒体输入并添加入捕捉会话
  • 创建媒体输出并添加入捕捉会话
  • 创建媒体预览视图,并设置其会话
  • 捕捉会话开始工作
  • 调用输出API进行拍摄
    ps—设置媒体输入&输出&媒体预览视图时可根据需求初始化相关基本设置,e.g.前后置镜头&前置摄像头镜像翻转&视频重力

Custom-Camera-UI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface ZBPreview : UIView
@property (nonatomic, readonly) AVCaptureVideoPreviewLayer *videoPreviewLayer;
@property (nonatomic, strong) AVCaptureSession *captureSession;
@end

#import "ZBPreview.h"
@implementation ZBPreview
- (void)awakeFromNib {
[super awakeFromNib];
//保留视频的宽高比并填充图层的边界
[self.videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}

- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self.videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
return self;
}

+ (Class)layerClass {
return [AVCaptureVideoPreviewLayer class];
}

- (AVCaptureVideoPreviewLayer*)videoPreviewLayer {
return (AVCaptureVideoPreviewLayer *)self.layer;
}

- (AVCaptureSession*)captureSession {
return self.videoPreviewLayer.session;
}

- (void)setCaptureSession:(AVCaptureSession*)captureSession {
self.videoPreviewLayer.session = captureSession;
}
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#import <UIKit/UIKit.h>
#import "ZBPreview.h"
@class ZBOverlayView;


@protocol ZBOverlayViewDelegate <NSObject>
@optional
- (void)overlayViewActionTakePicture:(ZBOverlayView *)overlayView;
- (void)overlayViewActionClickedAlbum:(ZBOverlayView *)overlayView;
- (void)overlayViewActionCancelCamera:(ZBOverlayView *)overlayView;
- (void)overlayViewActionSwitchCamera:(ZBOverlayView *)overlayView;
- (void)overlayViewActionExitCamera:(ZBOverlayView *)overlayView;
@end

//相机UI视图
@interface ZBOverlayView : UIView
///预览相机视图
@property (weak, nonatomic) IBOutlet ZBPreview *previewView;
///拍摄图片视图
@property (weak, nonatomic) IBOutlet UIImageView *previewPicture;
///UI操作代理
@property (nonatomic, weak) id<ZBOverlayViewDelegate> delegate;
+ (instancetype)cameraView;
- (UIView *)targetView;
@end


#import "ZBOverlayView.h"

@implementation ZBOverlayView

+ (instancetype)cameraView {
return [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil].firstObject;
}
//放置拍摄显示照片
- (UIView *)targetView {
return nil;
}
//返回
- (IBAction)backButtonClicked:(id)sender {
if ([self.delegate respondsToSelector:@selector(overlayViewActionExitCamera:)]) {
[self.delegate overlayViewActionExitCamera:self];
}
}
//拍摄
- (IBAction)takeButtonClicked:(id)sender {
if ([self.delegate respondsToSelector:@selector(overlayViewActionTakePicture:)]) {
[self.delegate overlayViewActionTakePicture:self];
}
}
//取消
- (IBAction)cancelButtonClicked:(id)sender {
if ([self.delegate respondsToSelector:@selector(overlayViewActionCancelCamera:)]) {
[self.delegate overlayViewActionCancelCamera:self];
}
}
//相册
- (IBAction)doneButtonClicked:(id)sender {
if ([self.delegate respondsToSelector:@selector(overlayViewActionClickedAlbum:)]) {
[self.delegate overlayViewActionClickedAlbum:self];
}
}
//切换镜头
- (IBAction)positionButtonClicked:(id)sender {
if ([self.delegate respondsToSelector:@selector(overlayViewActionSwitchCamera:)]) {
[self.delegate overlayViewActionSwitchCamera:self];
}
}
@end

via-AVCam: Building a Camera App