美文网首页iOS技术收藏iOS工程实践iOS开发
iOS 仿微信小视频做的一些东西

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

作者: icc_tips | 来源:发表于2016-09-26 16:58 被阅读1608次

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

    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];

    });

    }

    }];

    }

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

    相关文章

      网友评论

      • WHZ闹哪样:链接给一下吧
      • af4e8a35bc89:有Github链接吗 完整代码上一份
      • af4e8a35bc89:点赞 链接上代码更完美
      • 纱云:好歹加个效果图呗,那么多代码哪有看下去的动力,
        菊上一枝梅:@tunny https://github.com/MrZhou1990/ZHSmallVideo
        tunny:你好,有demo吗?想要学习学习:wink:
        icc_tips:@joan_1992 恩,好的,下次注意这个问题。谢谢你 :blush:

      本文标题:iOS 仿微信小视频做的一些东西

      本文链接:https://www.haomeiwen.com/subject/xvpqyttx.html