iOS 仿微信小视频做的一些东西

在写这个的时候查了好多资料,看了大家写的都基本一样,今天就当笔记一样分享给大家。

1:写一“按下去”按钮;

#import#import "AnnularProgress.h"

@interface PhotographBtu : UIView

@property(nonatomic, strong)AnnularProgress *photoTimeProgressView;

@property(nonatomic, strong)UIButton  *photoBtu;

@end


#import "PhotographBtu.h"

#define  photoBtuWiDTH 100

@implementation PhotographBtu

-(instancetype)init{

self = [super init];

if (self) {

[self createPhotoBtu];

}

return self;

}

-(instancetype)initWithFrame:(CGRect)frame{

self = [super initWithFrame:frame];

if (self) {

[self createPhotoBtu];}

return self;

}

-(void)awakeFromNib{

[super awakeFromNib];}

-(void)createPhotoBtu{

self.photoBtu = [UIButton buttonWithType:UIButtonTypeCustom];

NSLog(@"%f====%f",self.center.x ,self.center.y);

self.photoBtu.center = self.center;

[self.photoBtu setTitle:@"按住拍" forState:UIControlStateNormal];

[self.photoBtu setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

self.photoBtu.titleLabel.font = [UIFont systemFontOfSize:14];

self.photoBtu.frame = CGRectMake(self.frame.size.width/2-photoBtuWiDTH/2,self.frame.size.height/2-photoBtuWiDTH/2, photoBtuWiDTH, photoBtuWiDTH);

self.photoBtu.backgroundColor = [UIColor whiteColor];

self.photoBtu.layer.masksToBounds = YES;

self.photoBtu.layer.cornerRadius = 50;

[self addSubview:self.photoBtu];

self.photoTimeProgressView = [[AnnularProgress alloc] initWithFrame:CGRectMake(0, 0,150, 150)];

self.photoTimeProgressView.persentage = 0;

// self.photoTimeProgressView.backgroundColor = [UIColor blueColor];

[self addSubview:self.photoTimeProgressView];}



AnnularProgress.h

#import

typedef NS_ENUM (NSInteger, STClockWiseType) {

STClockWiseYes,

STClockWiseNo

};

@interface  AnnularProgress: UIView

@property (assign, nonatomic) CGFloat persentage;

// 起始颜色

+ (UIColor *)startColor;

// 中间颜色

+ (UIColor *)centerColor;

// 结束颜色

+ (UIColor *)endColor;

// 背景色

+ (UIColor *)backgroundColor;

// 线宽

+ (CGFloat)lineWidth;

// 起始角度(根据顺时针计算,逆时针则是结束角度)

+ (CGFloat)startAngle;

// 结束角度(根据顺时针计算,逆时针则是起始角度)

+ (CGFloat)endAngle;

// 进度条起始方向(YES为顺时针,NO为逆时针)

+ (STClockWiseType)clockWiseType;

@end


#import "AnnularProgress.h"

#define SELF_WIDTH CGRectGetWidth(self.bounds)

#define SELF_HEIGHT CGRectGetHeight(self.bounds)

#define DEGREES_TO_RADOANS(x) (M_PI * (x) / 180.0) // 将角度转为弧度

@interface AnnularProgress ()

@property (strong, nonatomic) CAShapeLayer *colorMaskLayer; // 渐变色遮罩

@property (strong, nonatomic) CAShapeLayer *colorLayer; // 渐变色

@property (strong, nonatomic) CAShapeLayer *blueMaskLayer; // 蓝色背景遮罩

@end

@implementation AnnularProgress

-(instancetype)initWithFrame:(CGRect)frame{

self = [super initWithFrame:frame];

if (self) {

self.backgroundColor = [AnnularProgress backgroundColor];

[self setupColorLayer];

[self setupColorMaskLayer];

[self setupBlueMaskLayer];

}

return self;

}

- (void)awakeFromNib {

[super awakeFromNib];

self.backgroundColor = [AnnularProgress backgroundColor];

[self setupColorLayer];

[self setupColorMaskLayer];

[self setupBlueMaskLayer];

}

/**

*  设置整个蓝色view的遮罩

*/

- (void)setupBlueMaskLayer {

CAShapeLayer *layer = [self generateMaskLayer];

self.layer.mask = layer;

self.blueMaskLayer = layer;

}

/**

*  设置渐变色,渐变色由左右两个部分组成,左边部分由黄到绿,右边部分由黄到红

*/

- (void)setupColorLayer {

self.colorLayer = [CAShapeLayer layer];

self.colorLayer.frame = self.bounds;

[self.layer addSublayer:self.colorLayer];

CAGradientLayer *leftLayer = [CAGradientLayer layer];

leftLayer.frame = CGRectMake(0, 0, SELF_WIDTH / 2, SELF_HEIGHT);

// 分段设置渐变色

leftLayer.locations = @[@0.3, @0.9, @1];

leftLayer.colors = @[(id)[AnnularProgress centerColor].CGColor, (id)[AnnularProgress startColor].CGColor];

[self.colorLayer addSublayer:leftLayer];

CAGradientLayer *rightLayer = [CAGradientLayer layer];

rightLayer.frame = CGRectMake(SELF_WIDTH / 2, 0, SELF_WIDTH / 2, SELF_HEIGHT);

rightLayer.locations = @[@0.3, @0.9, @1];

rightLayer.colors = @[(id)[AnnularProgress centerColor].CGColor, (id)[AnnularProgress endColor].CGColor];

[self.colorLayer addSublayer:rightLayer];

}

/**

*  设置渐变色的遮罩

*/

- (void)setupColorMaskLayer {

CAShapeLayer *layer = [self generateMaskLayer];

layer.lineWidth = [AnnularProgress lineWidth] + 0.5; // 渐变遮罩线宽较大,防止蓝色遮罩有边露出来

self.colorLayer.mask = layer;

self.colorMaskLayer = layer;

}

/**

*  生成一个圆环形的遮罩层

*  因为蓝色遮罩与渐变遮罩的配置都相同,所以封装出来

*

*  @return 环形遮罩

*/

- (CAShapeLayer *)generateMaskLayer {

CAShapeLayer *layer = [CAShapeLayer layer];

layer.frame = self.bounds;

// 创建一个圆心为父视图中点的圆,半径为父视图宽的2/5

UIBezierPath *path = nil;

if ([AnnularProgress clockWiseType]) {

path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(SELF_WIDTH / 2, SELF_HEIGHT / 2) radius:SELF_WIDTH / 2.5 startAngle:[AnnularProgress startAngle] endAngle:[AnnularProgress endAngle] clockwise:YES];

} else {

path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(SELF_WIDTH / 2, SELF_HEIGHT / 2) radius:SELF_WIDTH / 2.5 startAngle:[AnnularProgress endAngle] endAngle:[AnnularProgress startAngle] clockwise:NO];

}

layer.lineWidth = [AnnularProgress lineWidth];

layer.path = path.CGPath;

layer.fillColor = [UIColor clearColor].CGColor; // 填充色为透明(不设置为黑色)

layer.strokeColor = [UIColor blackColor].CGColor; // 随便设置一个边框颜色

layer.lineCap = kCALineCapRound; // 设置线为圆角

return layer;

}

/**

*  在修改百分比的时候,修改彩色遮罩的大小

*

*  @param persentage 百分比

*/

- (void)setPersentage:(CGFloat)persentage {

_persentage = persentage;

self.colorMaskLayer.strokeEnd = persentage;

}

+ (UIColor *)startColor {

return [UIColor whiteColor];

}

+ (UIColor *)centerColor {

return [UIColor whiteColor];

}

+ (UIColor *)endColor {

return [UIColor whiteColor];

}

+ (UIColor *)backgroundColor {

return [UIColor grayColor];

}

+ (CGFloat)lineWidth {

return 10;

}

+ (CGFloat)startAngle {

return DEGREES_TO_RADOANS(-90);

}

+ (CGFloat)endAngle {

return DEGREES_TO_RADOANS(270);

}

+ (STClockWiseType)clockWiseType {

return STClockWiseNo;

}

@end


这样就做出一个需要的按钮,接下来讲一下视频录制的主要方法。


1:导入俩个库:AssetsLibray.framework,AVKit.framework

2:授权摄像头的使用

//获取授权

- (void)getAuthorization

{

/*

AVAuthorizationStatusNotDetermined = 0,// 未进行授权选择

AVAuthorizationStatusRestricted,    // 未授权,且用户无法更新,如家长控制情况下

AVAuthorizationStatusDenied,       // 用户拒绝App使用

AVAuthorizationStatusAuthorized,    // 已授权,可使用

*/

//此处获取摄像头授权

switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])

{

case AVAuthorizationStatusAuthorized:      //已授权,可使用    The client is authorized to access the hardware supporting a media type.

{

NSLog(@"授权摄像头使用成功");

[self setupAVCaptureInfo];

break;

}

case AVAuthorizationStatusNotDetermined:    //未进行授权选择    Indicates that the user has not yet made a choice regarding whether the client can access the hardware.

{

//则再次请求授权

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {

if(granted){    //用户授权成功

[self setupAVCaptureInfo];

return;

} else {        //用户拒绝授权

[self pop];

[self showMsgWithTitle:@"出错了" andContent:@"用户拒绝授权摄像头的使用权,返回上一页.请打开\n设置-->隐私/通用等权限设置"];

return;

}

}];

break;

}

default:                                    //用户拒绝授权/未授权

{

[self pop];

[self showMsgWithTitle:@"出错了" andContent:@"拒绝授权,返回上一页.请检查下\n设置-->隐私/通用等权限设置"];

break;}}}}

3:设置视频的分辨率

_captureSession = [[AVCaptureSession alloc] init];

//设置视频分辨率

/*  通常支持如下格式

(

AVAssetExportPresetLowQuality,

AVAssetExportPreset960x540,

AVAssetExportPreset640x480,

AVAssetExportPresetMediumQuality,

AVAssetExportPreset1920x1080,

AVAssetExportPreset1280x720,

AVAssetExportPresetHighestQuality,

AVAssetExportPresetAppleM4A

)*/

//注意,这个地方设置的模式/分辨率大小将影响你后面拍摄照片/视频的大小,

if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) {

[_captureSession setSessionPreset:AVCaptureSessionPreset640x480];}

4:获取摄像头输入设备

// 获取摄像头输入设备, 创建 AVCaptureDeviceInput 对象

/* MediaType

AVF_EXPORT NSString *const AVMediaTypeVideo                NS_AVAILABLE(10_7, 4_0);      //视频

AVF_EXPORT NSString *const AVMediaTypeAudio                NS_AVAILABLE(10_7, 4_0);      //音频

AVF_EXPORT NSString *const AVMediaTypeText                  NS_AVAILABLE(10_7, 4_0);

AVF_EXPORT NSString *const AVMediaTypeClosedCaption        NS_AVAILABLE(10_7, 4_0);

AVF_EXPORT NSString *const AVMediaTypeSubtitle              NS_AVAILABLE(10_7, 4_0);

AVF_EXPORT NSString *const AVMediaTypeTimecode              NS_AVAILABLE(10_7, 4_0);

AVF_EXPORT NSString *const AVMediaTypeMetadata              NS_AVAILABLE(10_8, 6_0);

AVF_EXPORT NSString *const AVMediaTypeMuxed                NS_AVAILABLE(10_7, 4_0);

*/

/* AVCaptureDevicePosition

typedef NS_ENUM(NSInteger, AVCaptureDevicePosition) {

AVCaptureDevicePositionUnspecified        = 0,

AVCaptureDevicePositionBack                = 1,            //后置摄像头

AVCaptureDevicePositionFront              = 2            //前置摄像头

} NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED;

*/

_videoDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionBack];

5:切换闪光灯

BOOL con1 = [_videoDevice hasTorch];    //支持手电筒模式

BOOL con2 = [_videoDevice hasFlash];    //支持闪光模式

if (con1 && con2)

{

[self changeDevicePropertySafety:^(AVCaptureDevice *captureDevice) {

if (_videoDevice.flashMode == AVCaptureFlashModeOn)        //闪光灯开

{

[_videoDevice setFlashMode:AVCaptureFlashModeOff];

[_videoDevice setTorchMode:AVCaptureTorchModeOff];

}else if (_videoDevice.flashMode == AVCaptureFlashModeOff)  //闪光灯关

{

[_videoDevice setFlashMode:AVCaptureFlashModeOn];

[_videoDevice setTorchMode:AVCaptureTorchModeOn];

}

//            else{                                                      //闪光灯自动

//                [_videoDevice setFlashMode:AVCaptureFlashModeAuto];

//                [_videoDevice setTorchMode:AVCaptureTorchModeAuto];

//            }

NSLog(@"现在的闪光模式是AVCaptureFlashModeOn么?是你就扣1, %zd",_videoDevice.flashMode == AVCaptureFlashModeOn);

}];

sender.selected=!sender.isSelected;

}else{

NSLog(@"不能切换闪光模式");}

6:切换前后镜头

switch (_videoDevice.position) {

case AVCaptureDevicePositionBack:

_videoDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionFront];

break;

case AVCaptureDevicePositionFront:

_videoDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionBack];

break;

default:

return;

break;

}

[self changeDevicePropertySafety:^(AVCaptureDevice *captureDevice) {

NSError *error;

AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_videoDevice error:&error];

if (newVideoInput != nil) {

//必选先 remove 才能询问 canAdd

[_captureSession removeInput:_videoInput];

if ([_captureSession canAddInput:newVideoInput]) {

[_captureSession addInput:newVideoInput];

_videoInput = newVideoInput;

}else{

[_captureSession addInput:_videoInput];

}} else if (error) {

NSLog(@"切换前/后摄像头失败, error = %@", error);}}];


7:聚焦 

-(void)singleTap:(UITapGestureRecognizer *)tapGesture{

NSLog(@"单击");

CGPoint point= [tapGesture locationInView:self.videoView];

//将UI坐标转化为摄像头坐标,摄像头聚焦点范围0~1

CGPoint cameraPoint= [_captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];

[self setFocusCursorAnimationWithPoint:point];

[self changeDevicePropertySafety:^(AVCaptureDevice *captureDevice) {

/*

@constant AVCaptureFocusModeLocked 锁定在当前焦距

Indicates that the focus should be locked at the lens' current position.

@constant AVCaptureFocusModeAutoFocus 自动对焦一次,然后切换到焦距锁定

Indicates that the device should autofocus once and then change the focus mode to AVCaptureFocusModeLocked.

@constant AVCaptureFocusModeContinuousAutoFocus 当需要时.自动调整焦距

Indicates that the device should automatically focus when needed.

*/

//聚焦

if ([captureDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {

[captureDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];

NSLog(@"聚焦模式修改为%zd",AVCaptureFocusModeContinuousAutoFocus);

}else{

NSLog(@"聚焦模式修改失败");

}

//聚焦点的位置

if ([captureDevice isFocusPointOfInterestSupported]) {

[captureDevice setFocusPointOfInterest:cameraPoint];

}

/*

@constant AVCaptureExposureModeLocked  曝光锁定在当前值

Indicates that the exposure should be locked at its current value.

@constant AVCaptureExposureModeAutoExpose 曝光自动调整一次然后锁定

Indicates that the device should automatically adjust exposure once and then change the exposure mode to AVCaptureExposureModeLocked.

@constant AVCaptureExposureModeContinuousAutoExposure 曝光自动调整

Indicates that the device should automatically adjust exposure when needed.

@constant AVCaptureExposureModeCustom 曝光只根据设定的值来

Indicates that the device should only adjust exposure according to user provided ISO, exposureDuration values.

*/

//曝光模式

if ([captureDevice isExposureModeSupported:AVCaptureExposureModeAutoExpose]) {

[captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];

}else{

NSLog(@"曝光模式修改失败");

}

//曝光点的位置

if ([captureDevice isExposurePointOfInterestSupported]) {

[captureDevice setExposurePointOfInterest:cameraPoint];

}

}];}


8:压缩,保存

// 压缩视频

- (void)compressVideo:(UIButton *)sender

{

NSLog(@"压缩前大小 %f MB",[self fileSize:_videoUrl]);

//    创建AVAsset对象

AVAsset* asset = [AVAsset assetWithURL:_videoUrl];

/*  创建AVAssetExportSession对象

压缩的质量

AVAssetExportPresetLowQuality  最low的画质最好不要选择实在是看不清楚

AVAssetExportPresetMediumQuality  使用到压缩的话都说用这个

AVAssetExportPresetHighestQuality  最清晰的画质

*/

AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];

//优化网络

session.shouldOptimizeForNetworkUse = YES;

//转换后的格式

//拼接输出文件路径 为了防止同名 可以根据日期拼接名字 或者对名字进行MD5加密

NSString* path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"hello.mp4"];

//判断文件是否存在,如果已经存在删除

[[NSFileManager defaultManager]removeItemAtPath:path error:nil];

//设置输出路径

session.outputURL = [NSURL fileURLWithPath:path];

//设置输出类型  这里可以更改输出的类型 具体可以看文档描述

session.outputFileType = AVFileTypeMPEG4;

[session exportAsynchronouslyWithCompletionHandler:^{

NSLog(@"%@",[NSThread currentThread]);

//压缩完成

if (session.status==AVAssetExportSessionStatusCompleted) {

//在主线程中刷新UI界面,弹出控制器通知用户压缩完成

dispatch_async(dispatch_get_main_queue(), ^{

NSLog(@"导出完成");

NSURL *CompressURL = session.outputURL;

NSLog(@"压缩完毕,压缩后大小 %f MB",[self fileSize:CompressURL]);

[self upLoad:CompressURL];

[self saveVideo:session.outputURL];

});

}

}];

}

主要是这些代码。。。。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 1.NSTimer //暂停if ([timer isValid]) {[timer setFireDate:[N...
    俊月阅读 1,247评论 0 0
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,438评论 6 30
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,083评论 5 13
  • 1、禁止手机睡眠[UIApplication sharedApplication].idleTimerDisabl...
    DingGa阅读 1,112评论 1 6
  • 作者:Tong,欢迎交流。邮箱:wangtotang@gmail.comGitHub:https://github...
    糊涂_糖阅读 1,581评论 0 1