├── img1.png
├── img2.png
├── VideoRecord
├── flashOn.png
├── flashOff.png
├── focusImg.png
├── videoPlay.png
├── changeCamer.png
├── shootFinish.png
├── UIView+Tools.h
├── AppDelegate.h
├── PlayVideoViewController.h
├── main.m
├── UIView+Tools.m
├── ShootVideoViewController.h
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── PlayVideoViewController.m
├── AppDelegate.m
└── ShootVideoViewController.m
├── README.md
├── VideoRecord.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── goodplay.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── VideoRecord.xccheckout
├── xcuserdata
│ └── goodplay.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── VideoRecord.xcscheme
└── project.pbxproj
└── VideoRecordTests
├── Info.plist
└── VideoRecordTests.m
/img1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/img1.png
--------------------------------------------------------------------------------
/img2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/img2.png
--------------------------------------------------------------------------------
/VideoRecord/flashOn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord/flashOn.png
--------------------------------------------------------------------------------
/VideoRecord/flashOff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord/flashOff.png
--------------------------------------------------------------------------------
/VideoRecord/focusImg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord/focusImg.png
--------------------------------------------------------------------------------
/VideoRecord/videoPlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord/videoPlay.png
--------------------------------------------------------------------------------
/VideoRecord/changeCamer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord/changeCamer.png
--------------------------------------------------------------------------------
/VideoRecord/shootFinish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord/shootFinish.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VideoRecord
2 | 模仿快手应用的视频录制 10秒1兆左右,清晰度也可以。
3 | 
4 | 
5 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/project.xcworkspace/xcuserdata/goodplay.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndyFightting/VideoRecord/HEAD/VideoRecord.xcodeproj/project.xcworkspace/xcuserdata/goodplay.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/VideoRecord/UIView+Tools.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Tools.h
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 14-8-25.
6 | // Copyright (c) 2014年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIView (Tools)
12 | -(void)makeCornerRadius:(float)radius borderColor:(UIColor*)bColor borderWidth:(float)bWidth;
13 | @end
14 |
--------------------------------------------------------------------------------
/VideoRecord/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/6/2.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/VideoRecord/PlayVideoViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PlayVideoViewController.h
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/4/27.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface PlayVideoViewController : UIViewController
13 |
14 | @property(nonatomic,retain) NSURL * videoURL;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/VideoRecord/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/6/2.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/project.xcworkspace/xcuserdata/goodplay.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/VideoRecord/UIView+Tools.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Tools.m
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 14-8-25.
6 | // Copyright (c) 2014年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import "UIView+Tools.h"
10 |
11 | @implementation UIView (Tools)
12 | -(void)makeCornerRadius:(float)radius borderColor:(UIColor *)bColor borderWidth:(float)bWidth{
13 | self.layer.borderWidth = bWidth;
14 |
15 | if (bColor != nil) {
16 | self.layer.borderColor = bColor.CGColor;
17 | }
18 |
19 | self.layer.cornerRadius = radius;
20 | self.layer.masksToBounds = YES;
21 | }
22 |
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/xcuserdata/goodplay.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | VideoRecord.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 58FFD6651B1D6D0000163610
16 |
17 | primary
18 |
19 |
20 | 58FFD67E1B1D6D0000163610
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/VideoRecord/ShootVideoViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ShootVideoViewController.h
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/5/4.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import "UIView+Tools.h"
12 |
13 | #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
14 | #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
15 |
16 | #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
17 |
18 | @interface ShootVideoViewController : UIViewController
19 |
20 | @property float totalTime; //视频总长度 默认10秒
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/VideoRecord/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/VideoRecordTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.good.studentApp
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/VideoRecordTests/VideoRecordTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // VideoRecordTests.m
3 | // VideoRecordTests
4 | //
5 | // Created by guimingsu on 15/6/2.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface VideoRecordTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation VideoRecordTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown {
24 | // Put teardown code here. This method is called after the invocation of each test method in the class.
25 | [super tearDown];
26 | }
27 |
28 | - (void)testExample {
29 | // This is an example of a functional test case.
30 | XCTAssert(YES, @"Pass");
31 | }
32 |
33 | - (void)testPerformanceExample {
34 | // This is an example of a performance test case.
35 | [self measureBlock:^{
36 | // Put the code you want to measure the time of here.
37 | }];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/VideoRecord/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.good.studentApp
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/project.xcworkspace/xcshareddata/VideoRecord.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 2AF0404D-3294-4949-831E-793B6547B81D
9 | IDESourceControlProjectName
10 | VideoRecord
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | C6DAC2EF68DB7339AE46E91EDD7ADBA197112D94
14 | https://github.com/AndyFightting/VideoRecord.git
15 |
16 | IDESourceControlProjectPath
17 | VideoRecord.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | C6DAC2EF68DB7339AE46E91EDD7ADBA197112D94
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/AndyFightting/VideoRecord.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | C6DAC2EF68DB7339AE46E91EDD7ADBA197112D94
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | C6DAC2EF68DB7339AE46E91EDD7ADBA197112D94
36 | IDESourceControlWCCName
37 | VideoRecord
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/VideoRecord/PlayVideoViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PlayVideoViewController.m
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/4/27.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import "PlayVideoViewController.h"
10 | #import
11 |
12 | @interface PlayVideoViewController ()
13 |
14 | @end
15 |
16 | @implementation PlayVideoViewController
17 | {
18 |
19 | AVPlayer *player;
20 | AVPlayerLayer *playerLayer;
21 | AVPlayerItem *playerItem;
22 |
23 | UIImageView* playImg;
24 |
25 | }
26 |
27 | @synthesize videoURL;
28 |
29 |
30 | - (void)viewDidLoad {
31 | [super viewDidLoad];
32 | self.view.backgroundColor = [UIColor blackColor];
33 | self.title = @"预览";
34 |
35 | float videoWidth = self.view.frame.size.width;
36 |
37 | AVAsset *movieAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil];
38 | playerItem = [AVPlayerItem playerItemWithAsset:movieAsset];
39 | player = [AVPlayer playerWithPlayerItem:playerItem];
40 |
41 | playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
42 | playerLayer.frame = CGRectMake(0, 64, videoWidth, videoWidth);
43 | playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
44 | [self.view.layer addSublayer:playerLayer];
45 |
46 | UITapGestureRecognizer *playTap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playOrPause)];
47 | [self.view addGestureRecognizer:playTap];
48 |
49 | [self pressPlayButton];
50 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playingEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
51 |
52 | playImg = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 40, 40)];
53 | playImg.center = CGPointMake(videoWidth/2, videoWidth/2);
54 | [playImg setImage:[UIImage imageNamed:@"videoPlay"]];
55 | [playerLayer addSublayer:playImg.layer];
56 | playImg.hidden = YES;
57 |
58 | }
59 |
60 | -(void)playOrPause{
61 | if (playImg.isHidden) {
62 | playImg.hidden = NO;
63 | [player pause];
64 |
65 | }else{
66 | playImg.hidden = YES;
67 | [player play];
68 | }
69 | }
70 |
71 | - (void)pressPlayButton
72 | {
73 | [playerItem seekToTime:kCMTimeZero];
74 | [player play];
75 | }
76 |
77 | - (void)playingEnd:(NSNotification *)notification
78 | {
79 | if (playImg.isHidden) {
80 | [self pressPlayButton];
81 | }
82 | }
83 |
84 | - (void)didReceiveMemoryWarning {
85 | [super didReceiveMemoryWarning];
86 | }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/VideoRecord/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/6/2.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "ShootVideoViewController.h"
11 |
12 | @interface AppDelegate ()
13 |
14 | @end
15 |
16 | @implementation AppDelegate
17 |
18 |
19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20 | // Override point for customization after application launch.
21 |
22 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
23 |
24 | ShootVideoViewController* shootVC = [[ShootVideoViewController alloc] init];
25 | UINavigationController* nav = [[UINavigationController alloc]initWithRootViewController:shootVC];
26 |
27 | self.window.rootViewController = nav;
28 | [self.window makeKeyAndVisible];
29 | return YES;
30 | }
31 |
32 | - (void)applicationWillResignActive:(UIApplication *)application {
33 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
34 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
35 | }
36 |
37 | - (void)applicationDidEnterBackground:(UIApplication *)application {
38 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
40 | }
41 |
42 | - (void)applicationWillEnterForeground:(UIApplication *)application {
43 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
44 | }
45 |
46 | - (void)applicationDidBecomeActive:(UIApplication *)application {
47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
48 | }
49 |
50 | - (void)applicationWillTerminate:(UIApplication *)application {
51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/xcuserdata/goodplay.xcuserdatad/xcschemes/VideoRecord.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/VideoRecord.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 58FFD66C1B1D6D0000163610 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FFD66B1B1D6D0000163610 /* main.m */; };
11 | 58FFD6771B1D6D0000163610 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD6761B1D6D0000163610 /* Images.xcassets */; };
12 | 58FFD6861B1D6D0000163610 /* VideoRecordTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FFD6851B1D6D0000163610 /* VideoRecordTests.m */; };
13 | 58FFD6951B1D6D4900163610 /* changeCamer.png in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD68F1B1D6D4900163610 /* changeCamer.png */; };
14 | 58FFD6961B1D6D4900163610 /* flashOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD6901B1D6D4900163610 /* flashOff.png */; };
15 | 58FFD6971B1D6D4900163610 /* flashOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD6911B1D6D4900163610 /* flashOn.png */; };
16 | 58FFD6981B1D6D4900163610 /* focusImg.png in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD6921B1D6D4900163610 /* focusImg.png */; };
17 | 58FFD6991B1D6D4900163610 /* shootFinish.png in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD6931B1D6D4900163610 /* shootFinish.png */; };
18 | 58FFD69A1B1D6D4900163610 /* videoPlay.png in Resources */ = {isa = PBXBuildFile; fileRef = 58FFD6941B1D6D4900163610 /* videoPlay.png */; };
19 | 58FFD6A11B1D6D5600163610 /* PlayVideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FFD69C1B1D6D5600163610 /* PlayVideoViewController.m */; };
20 | 58FFD6A21B1D6D5600163610 /* ShootVideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FFD69E1B1D6D5600163610 /* ShootVideoViewController.m */; };
21 | 58FFD6A31B1D6D5600163610 /* UIView+Tools.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FFD6A01B1D6D5600163610 /* UIView+Tools.m */; };
22 | 58FFD6A61B1D6D5F00163610 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FFD6A51B1D6D5F00163610 /* AppDelegate.m */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXContainerItemProxy section */
26 | 58FFD6801B1D6D0000163610 /* PBXContainerItemProxy */ = {
27 | isa = PBXContainerItemProxy;
28 | containerPortal = 58FFD65E1B1D6D0000163610 /* Project object */;
29 | proxyType = 1;
30 | remoteGlobalIDString = 58FFD6651B1D6D0000163610;
31 | remoteInfo = VideoRecord;
32 | };
33 | /* End PBXContainerItemProxy section */
34 |
35 | /* Begin PBXFileReference section */
36 | 58FFD6661B1D6D0000163610 /* VideoRecord.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VideoRecord.app; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 58FFD66A1B1D6D0000163610 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
38 | 58FFD66B1B1D6D0000163610 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
39 | 58FFD6761B1D6D0000163610 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
40 | 58FFD67F1B1D6D0000163610 /* VideoRecordTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VideoRecordTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 58FFD6841B1D6D0000163610 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
42 | 58FFD6851B1D6D0000163610 /* VideoRecordTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoRecordTests.m; sourceTree = ""; };
43 | 58FFD68F1B1D6D4900163610 /* changeCamer.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = changeCamer.png; sourceTree = ""; };
44 | 58FFD6901B1D6D4900163610 /* flashOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flashOff.png; sourceTree = ""; };
45 | 58FFD6911B1D6D4900163610 /* flashOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flashOn.png; sourceTree = ""; };
46 | 58FFD6921B1D6D4900163610 /* focusImg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = focusImg.png; sourceTree = ""; };
47 | 58FFD6931B1D6D4900163610 /* shootFinish.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = shootFinish.png; sourceTree = ""; };
48 | 58FFD6941B1D6D4900163610 /* videoPlay.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = videoPlay.png; sourceTree = ""; };
49 | 58FFD69B1B1D6D5600163610 /* PlayVideoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayVideoViewController.h; sourceTree = ""; };
50 | 58FFD69C1B1D6D5600163610 /* PlayVideoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayVideoViewController.m; sourceTree = ""; };
51 | 58FFD69D1B1D6D5600163610 /* ShootVideoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShootVideoViewController.h; sourceTree = ""; };
52 | 58FFD69E1B1D6D5600163610 /* ShootVideoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShootVideoViewController.m; sourceTree = ""; };
53 | 58FFD69F1B1D6D5600163610 /* UIView+Tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Tools.h"; sourceTree = ""; };
54 | 58FFD6A01B1D6D5600163610 /* UIView+Tools.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Tools.m"; sourceTree = ""; };
55 | 58FFD6A41B1D6D5F00163610 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
56 | 58FFD6A51B1D6D5F00163610 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
57 | /* End PBXFileReference section */
58 |
59 | /* Begin PBXFrameworksBuildPhase section */
60 | 58FFD6631B1D6D0000163610 /* Frameworks */ = {
61 | isa = PBXFrameworksBuildPhase;
62 | buildActionMask = 2147483647;
63 | files = (
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | 58FFD67C1B1D6D0000163610 /* Frameworks */ = {
68 | isa = PBXFrameworksBuildPhase;
69 | buildActionMask = 2147483647;
70 | files = (
71 | );
72 | runOnlyForDeploymentPostprocessing = 0;
73 | };
74 | /* End PBXFrameworksBuildPhase section */
75 |
76 | /* Begin PBXGroup section */
77 | 58FFD65D1B1D6D0000163610 = {
78 | isa = PBXGroup;
79 | children = (
80 | 58FFD6681B1D6D0000163610 /* VideoRecord */,
81 | 58FFD6821B1D6D0000163610 /* VideoRecordTests */,
82 | 58FFD6671B1D6D0000163610 /* Products */,
83 | );
84 | sourceTree = "";
85 | };
86 | 58FFD6671B1D6D0000163610 /* Products */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 58FFD6661B1D6D0000163610 /* VideoRecord.app */,
90 | 58FFD67F1B1D6D0000163610 /* VideoRecordTests.xctest */,
91 | );
92 | name = Products;
93 | sourceTree = "";
94 | };
95 | 58FFD6681B1D6D0000163610 /* VideoRecord */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 58FFD6A41B1D6D5F00163610 /* AppDelegate.h */,
99 | 58FFD6A51B1D6D5F00163610 /* AppDelegate.m */,
100 | 58FFD69B1B1D6D5600163610 /* PlayVideoViewController.h */,
101 | 58FFD69C1B1D6D5600163610 /* PlayVideoViewController.m */,
102 | 58FFD69D1B1D6D5600163610 /* ShootVideoViewController.h */,
103 | 58FFD69E1B1D6D5600163610 /* ShootVideoViewController.m */,
104 | 58FFD69F1B1D6D5600163610 /* UIView+Tools.h */,
105 | 58FFD6A01B1D6D5600163610 /* UIView+Tools.m */,
106 | 58FFD68F1B1D6D4900163610 /* changeCamer.png */,
107 | 58FFD6901B1D6D4900163610 /* flashOff.png */,
108 | 58FFD6911B1D6D4900163610 /* flashOn.png */,
109 | 58FFD6921B1D6D4900163610 /* focusImg.png */,
110 | 58FFD6931B1D6D4900163610 /* shootFinish.png */,
111 | 58FFD6941B1D6D4900163610 /* videoPlay.png */,
112 | 58FFD6761B1D6D0000163610 /* Images.xcassets */,
113 | 58FFD6691B1D6D0000163610 /* Supporting Files */,
114 | );
115 | path = VideoRecord;
116 | sourceTree = "";
117 | };
118 | 58FFD6691B1D6D0000163610 /* Supporting Files */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 58FFD66A1B1D6D0000163610 /* Info.plist */,
122 | 58FFD66B1B1D6D0000163610 /* main.m */,
123 | );
124 | name = "Supporting Files";
125 | sourceTree = "";
126 | };
127 | 58FFD6821B1D6D0000163610 /* VideoRecordTests */ = {
128 | isa = PBXGroup;
129 | children = (
130 | 58FFD6851B1D6D0000163610 /* VideoRecordTests.m */,
131 | 58FFD6831B1D6D0000163610 /* Supporting Files */,
132 | );
133 | path = VideoRecordTests;
134 | sourceTree = "";
135 | };
136 | 58FFD6831B1D6D0000163610 /* Supporting Files */ = {
137 | isa = PBXGroup;
138 | children = (
139 | 58FFD6841B1D6D0000163610 /* Info.plist */,
140 | );
141 | name = "Supporting Files";
142 | sourceTree = "";
143 | };
144 | /* End PBXGroup section */
145 |
146 | /* Begin PBXNativeTarget section */
147 | 58FFD6651B1D6D0000163610 /* VideoRecord */ = {
148 | isa = PBXNativeTarget;
149 | buildConfigurationList = 58FFD6891B1D6D0000163610 /* Build configuration list for PBXNativeTarget "VideoRecord" */;
150 | buildPhases = (
151 | 58FFD6621B1D6D0000163610 /* Sources */,
152 | 58FFD6631B1D6D0000163610 /* Frameworks */,
153 | 58FFD6641B1D6D0000163610 /* Resources */,
154 | );
155 | buildRules = (
156 | );
157 | dependencies = (
158 | );
159 | name = VideoRecord;
160 | productName = VideoRecord;
161 | productReference = 58FFD6661B1D6D0000163610 /* VideoRecord.app */;
162 | productType = "com.apple.product-type.application";
163 | };
164 | 58FFD67E1B1D6D0000163610 /* VideoRecordTests */ = {
165 | isa = PBXNativeTarget;
166 | buildConfigurationList = 58FFD68C1B1D6D0000163610 /* Build configuration list for PBXNativeTarget "VideoRecordTests" */;
167 | buildPhases = (
168 | 58FFD67B1B1D6D0000163610 /* Sources */,
169 | 58FFD67C1B1D6D0000163610 /* Frameworks */,
170 | 58FFD67D1B1D6D0000163610 /* Resources */,
171 | );
172 | buildRules = (
173 | );
174 | dependencies = (
175 | 58FFD6811B1D6D0000163610 /* PBXTargetDependency */,
176 | );
177 | name = VideoRecordTests;
178 | productName = VideoRecordTests;
179 | productReference = 58FFD67F1B1D6D0000163610 /* VideoRecordTests.xctest */;
180 | productType = "com.apple.product-type.bundle.unit-test";
181 | };
182 | /* End PBXNativeTarget section */
183 |
184 | /* Begin PBXProject section */
185 | 58FFD65E1B1D6D0000163610 /* Project object */ = {
186 | isa = PBXProject;
187 | attributes = {
188 | LastUpgradeCheck = 0630;
189 | ORGANIZATIONNAME = guimingsu;
190 | TargetAttributes = {
191 | 58FFD6651B1D6D0000163610 = {
192 | CreatedOnToolsVersion = 6.3.1;
193 | };
194 | 58FFD67E1B1D6D0000163610 = {
195 | CreatedOnToolsVersion = 6.3.1;
196 | TestTargetID = 58FFD6651B1D6D0000163610;
197 | };
198 | };
199 | };
200 | buildConfigurationList = 58FFD6611B1D6D0000163610 /* Build configuration list for PBXProject "VideoRecord" */;
201 | compatibilityVersion = "Xcode 3.2";
202 | developmentRegion = English;
203 | hasScannedForEncodings = 0;
204 | knownRegions = (
205 | en,
206 | Base,
207 | );
208 | mainGroup = 58FFD65D1B1D6D0000163610;
209 | productRefGroup = 58FFD6671B1D6D0000163610 /* Products */;
210 | projectDirPath = "";
211 | projectRoot = "";
212 | targets = (
213 | 58FFD6651B1D6D0000163610 /* VideoRecord */,
214 | 58FFD67E1B1D6D0000163610 /* VideoRecordTests */,
215 | );
216 | };
217 | /* End PBXProject section */
218 |
219 | /* Begin PBXResourcesBuildPhase section */
220 | 58FFD6641B1D6D0000163610 /* Resources */ = {
221 | isa = PBXResourcesBuildPhase;
222 | buildActionMask = 2147483647;
223 | files = (
224 | 58FFD69A1B1D6D4900163610 /* videoPlay.png in Resources */,
225 | 58FFD6951B1D6D4900163610 /* changeCamer.png in Resources */,
226 | 58FFD6981B1D6D4900163610 /* focusImg.png in Resources */,
227 | 58FFD6971B1D6D4900163610 /* flashOn.png in Resources */,
228 | 58FFD6961B1D6D4900163610 /* flashOff.png in Resources */,
229 | 58FFD6991B1D6D4900163610 /* shootFinish.png in Resources */,
230 | 58FFD6771B1D6D0000163610 /* Images.xcassets in Resources */,
231 | );
232 | runOnlyForDeploymentPostprocessing = 0;
233 | };
234 | 58FFD67D1B1D6D0000163610 /* Resources */ = {
235 | isa = PBXResourcesBuildPhase;
236 | buildActionMask = 2147483647;
237 | files = (
238 | );
239 | runOnlyForDeploymentPostprocessing = 0;
240 | };
241 | /* End PBXResourcesBuildPhase section */
242 |
243 | /* Begin PBXSourcesBuildPhase section */
244 | 58FFD6621B1D6D0000163610 /* Sources */ = {
245 | isa = PBXSourcesBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | 58FFD6A11B1D6D5600163610 /* PlayVideoViewController.m in Sources */,
249 | 58FFD6A21B1D6D5600163610 /* ShootVideoViewController.m in Sources */,
250 | 58FFD6A31B1D6D5600163610 /* UIView+Tools.m in Sources */,
251 | 58FFD66C1B1D6D0000163610 /* main.m in Sources */,
252 | 58FFD6A61B1D6D5F00163610 /* AppDelegate.m in Sources */,
253 | );
254 | runOnlyForDeploymentPostprocessing = 0;
255 | };
256 | 58FFD67B1B1D6D0000163610 /* Sources */ = {
257 | isa = PBXSourcesBuildPhase;
258 | buildActionMask = 2147483647;
259 | files = (
260 | 58FFD6861B1D6D0000163610 /* VideoRecordTests.m in Sources */,
261 | );
262 | runOnlyForDeploymentPostprocessing = 0;
263 | };
264 | /* End PBXSourcesBuildPhase section */
265 |
266 | /* Begin PBXTargetDependency section */
267 | 58FFD6811B1D6D0000163610 /* PBXTargetDependency */ = {
268 | isa = PBXTargetDependency;
269 | target = 58FFD6651B1D6D0000163610 /* VideoRecord */;
270 | targetProxy = 58FFD6801B1D6D0000163610 /* PBXContainerItemProxy */;
271 | };
272 | /* End PBXTargetDependency section */
273 |
274 | /* Begin XCBuildConfiguration section */
275 | 58FFD6871B1D6D0000163610 /* Debug */ = {
276 | isa = XCBuildConfiguration;
277 | buildSettings = {
278 | ALWAYS_SEARCH_USER_PATHS = NO;
279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
280 | CLANG_CXX_LIBRARY = "libc++";
281 | CLANG_ENABLE_MODULES = YES;
282 | CLANG_ENABLE_OBJC_ARC = YES;
283 | CLANG_WARN_BOOL_CONVERSION = YES;
284 | CLANG_WARN_CONSTANT_CONVERSION = YES;
285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
286 | CLANG_WARN_EMPTY_BODY = YES;
287 | CLANG_WARN_ENUM_CONVERSION = YES;
288 | CLANG_WARN_INT_CONVERSION = YES;
289 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
290 | CLANG_WARN_UNREACHABLE_CODE = YES;
291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
292 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
293 | COPY_PHASE_STRIP = NO;
294 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
295 | ENABLE_STRICT_OBJC_MSGSEND = YES;
296 | GCC_C_LANGUAGE_STANDARD = gnu99;
297 | GCC_DYNAMIC_NO_PIC = NO;
298 | GCC_NO_COMMON_BLOCKS = YES;
299 | GCC_OPTIMIZATION_LEVEL = 0;
300 | GCC_PREPROCESSOR_DEFINITIONS = (
301 | "DEBUG=1",
302 | "$(inherited)",
303 | );
304 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
305 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
306 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
307 | GCC_WARN_UNDECLARED_SELECTOR = YES;
308 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
309 | GCC_WARN_UNUSED_FUNCTION = YES;
310 | GCC_WARN_UNUSED_VARIABLE = YES;
311 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
312 | MTL_ENABLE_DEBUG_INFO = YES;
313 | ONLY_ACTIVE_ARCH = YES;
314 | PROVISIONING_PROFILE = "ed21f08b-fd34-42b1-a762-965662004bf9";
315 | SDKROOT = iphoneos;
316 | };
317 | name = Debug;
318 | };
319 | 58FFD6881B1D6D0000163610 /* Release */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ALWAYS_SEARCH_USER_PATHS = NO;
323 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
324 | CLANG_CXX_LIBRARY = "libc++";
325 | CLANG_ENABLE_MODULES = YES;
326 | CLANG_ENABLE_OBJC_ARC = YES;
327 | CLANG_WARN_BOOL_CONVERSION = YES;
328 | CLANG_WARN_CONSTANT_CONVERSION = YES;
329 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
330 | CLANG_WARN_EMPTY_BODY = YES;
331 | CLANG_WARN_ENUM_CONVERSION = YES;
332 | CLANG_WARN_INT_CONVERSION = YES;
333 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
334 | CLANG_WARN_UNREACHABLE_CODE = YES;
335 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
336 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
337 | COPY_PHASE_STRIP = NO;
338 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
339 | ENABLE_NS_ASSERTIONS = NO;
340 | ENABLE_STRICT_OBJC_MSGSEND = YES;
341 | GCC_C_LANGUAGE_STANDARD = gnu99;
342 | GCC_NO_COMMON_BLOCKS = YES;
343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
345 | GCC_WARN_UNDECLARED_SELECTOR = YES;
346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
347 | GCC_WARN_UNUSED_FUNCTION = YES;
348 | GCC_WARN_UNUSED_VARIABLE = YES;
349 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
350 | MTL_ENABLE_DEBUG_INFO = NO;
351 | PROVISIONING_PROFILE = "ed21f08b-fd34-42b1-a762-965662004bf9";
352 | SDKROOT = iphoneos;
353 | VALIDATE_PRODUCT = YES;
354 | };
355 | name = Release;
356 | };
357 | 58FFD68A1B1D6D0000163610 /* Debug */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
361 | INFOPLIST_FILE = VideoRecord/Info.plist;
362 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
363 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
364 | PRODUCT_NAME = "$(TARGET_NAME)";
365 | PROVISIONING_PROFILE = "ed21f08b-fd34-42b1-a762-965662004bf9";
366 | };
367 | name = Debug;
368 | };
369 | 58FFD68B1B1D6D0000163610 /* Release */ = {
370 | isa = XCBuildConfiguration;
371 | buildSettings = {
372 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
373 | INFOPLIST_FILE = VideoRecord/Info.plist;
374 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
375 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
376 | PRODUCT_NAME = "$(TARGET_NAME)";
377 | PROVISIONING_PROFILE = "ed21f08b-fd34-42b1-a762-965662004bf9";
378 | };
379 | name = Release;
380 | };
381 | 58FFD68D1B1D6D0000163610 /* Debug */ = {
382 | isa = XCBuildConfiguration;
383 | buildSettings = {
384 | BUNDLE_LOADER = "$(TEST_HOST)";
385 | FRAMEWORK_SEARCH_PATHS = (
386 | "$(SDKROOT)/Developer/Library/Frameworks",
387 | "$(inherited)",
388 | );
389 | GCC_PREPROCESSOR_DEFINITIONS = (
390 | "DEBUG=1",
391 | "$(inherited)",
392 | );
393 | INFOPLIST_FILE = VideoRecordTests/Info.plist;
394 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
395 | PRODUCT_NAME = "$(TARGET_NAME)";
396 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VideoRecord.app/VideoRecord";
397 | };
398 | name = Debug;
399 | };
400 | 58FFD68E1B1D6D0000163610 /* Release */ = {
401 | isa = XCBuildConfiguration;
402 | buildSettings = {
403 | BUNDLE_LOADER = "$(TEST_HOST)";
404 | FRAMEWORK_SEARCH_PATHS = (
405 | "$(SDKROOT)/Developer/Library/Frameworks",
406 | "$(inherited)",
407 | );
408 | INFOPLIST_FILE = VideoRecordTests/Info.plist;
409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
410 | PRODUCT_NAME = "$(TARGET_NAME)";
411 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VideoRecord.app/VideoRecord";
412 | };
413 | name = Release;
414 | };
415 | /* End XCBuildConfiguration section */
416 |
417 | /* Begin XCConfigurationList section */
418 | 58FFD6611B1D6D0000163610 /* Build configuration list for PBXProject "VideoRecord" */ = {
419 | isa = XCConfigurationList;
420 | buildConfigurations = (
421 | 58FFD6871B1D6D0000163610 /* Debug */,
422 | 58FFD6881B1D6D0000163610 /* Release */,
423 | );
424 | defaultConfigurationIsVisible = 0;
425 | defaultConfigurationName = Release;
426 | };
427 | 58FFD6891B1D6D0000163610 /* Build configuration list for PBXNativeTarget "VideoRecord" */ = {
428 | isa = XCConfigurationList;
429 | buildConfigurations = (
430 | 58FFD68A1B1D6D0000163610 /* Debug */,
431 | 58FFD68B1B1D6D0000163610 /* Release */,
432 | );
433 | defaultConfigurationIsVisible = 0;
434 | defaultConfigurationName = Release;
435 | };
436 | 58FFD68C1B1D6D0000163610 /* Build configuration list for PBXNativeTarget "VideoRecordTests" */ = {
437 | isa = XCConfigurationList;
438 | buildConfigurations = (
439 | 58FFD68D1B1D6D0000163610 /* Debug */,
440 | 58FFD68E1B1D6D0000163610 /* Release */,
441 | );
442 | defaultConfigurationIsVisible = 0;
443 | defaultConfigurationName = Release;
444 | };
445 | /* End XCConfigurationList section */
446 | };
447 | rootObject = 58FFD65E1B1D6D0000163610 /* Project object */;
448 | }
449 |
--------------------------------------------------------------------------------
/VideoRecord/ShootVideoViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShootVideoViewController.m
3 | // VideoRecord
4 | //
5 | // Created by guimingsu on 15/5/4.
6 | // Copyright (c) 2015年 guimingsu. All rights reserved.
7 | //
8 |
9 | #import "ShootVideoViewController.h"
10 | #import "PlayVideoViewController.h"
11 |
12 | #import
13 | #import
14 |
15 | #define TIMER_INTERVAL 0.05
16 | #define VIDEO_FOLDER @"videoFolder"
17 |
18 | typedef void(^PropertyChangeBlock)(AVCaptureDevice *captureDevice);
19 |
20 | @interface ShootVideoViewController ()//视频文件输出代理
21 |
22 | @property (strong,nonatomic) AVCaptureSession *captureSession;//负责输入和输出设置之间的数据传递
23 | @property (strong,nonatomic) AVCaptureDeviceInput *captureDeviceInput;//负责从AVCaptureDevice获得输入数据
24 | @property (strong,nonatomic) AVCaptureMovieFileOutput *captureMovieFileOutput;//视频输出流
25 | @property (strong,nonatomic) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;//相机拍摄预览图层
26 |
27 | @property (strong,nonatomic) UIView *viewContainer;//视频容器
28 | @property (strong,nonatomic) UIImageView *focusCursor; //聚焦光标
29 |
30 | @end
31 |
32 | @implementation ShootVideoViewController{
33 |
34 | NSMutableArray* urlArray;//保存视频片段的数组
35 |
36 | float currentTime; //当前视频长度
37 |
38 | NSTimer *countTimer; //计时器
39 | UIView* progressPreView; //进度条
40 | float progressStep; //进度条每次变长的最小单位
41 |
42 | float preLayerWidth;//镜头宽
43 | float preLayerHeight;//镜头高
44 | float preLayerHWRate; //高,宽比
45 |
46 | UIButton* shootBt;//录制按钮
47 | UIButton* finishBt;//结束按钮
48 |
49 | UIButton* flashBt;//闪光灯
50 | UIButton* cameraBt;//切换摄像头
51 |
52 | }
53 | @synthesize totalTime;
54 |
55 | - (void)viewDidLoad {
56 | [super viewDidLoad];
57 | // Do any additional setup after loading the view.
58 | self.view.backgroundColor = UIColorFromRGB(0x1d1e20);
59 | self.title = @"视频录制";
60 |
61 | //视频最大时长 默认10秒
62 | if (totalTime==0) {
63 | totalTime =10;
64 | }
65 |
66 | urlArray = [[NSMutableArray alloc]init];
67 |
68 | preLayerWidth = SCREEN_WIDTH;
69 | preLayerHeight = SCREEN_WIDTH;
70 | preLayerHWRate =preLayerHeight/preLayerWidth;
71 |
72 | progressStep = SCREEN_WIDTH*TIMER_INTERVAL/totalTime;
73 |
74 | [self createVideoFolderIfNotExist];
75 | [self initCapture];
76 | }
77 |
78 | -(void)initCapture{
79 |
80 | //视频高度加进度条(10)高度
81 | self.viewContainer = [[UIView alloc]initWithFrame:CGRectMake(0, 64, preLayerWidth, preLayerHeight+10)];
82 | [self.view addSubview:self.viewContainer];
83 |
84 | self.focusCursor = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 50, 50)];
85 | [self.focusCursor setImage:[UIImage imageNamed:@"focusImg"]];
86 | self.focusCursor.alpha = 0;
87 | [self.viewContainer addSubview:self.focusCursor];
88 |
89 |
90 | UIView* btView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 86, 86)];
91 | btView.center = CGPointMake(SCREEN_WIDTH/2, 64+preLayerHeight+20+43);
92 | [btView makeCornerRadius:43 borderColor:nil borderWidth:0];
93 | btView.backgroundColor = UIColorFromRGB(0xeeeeee);
94 | [self.view addSubview:btView];
95 |
96 | shootBt = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 76, 76)];
97 | shootBt.center = CGPointMake(43, 43);
98 | shootBt.backgroundColor = UIColorFromRGB(0xfa5f66);
99 | [shootBt addTarget:self action:@selector(shootButtonClick) forControlEvents:UIControlEventTouchUpInside];
100 | [shootBt makeCornerRadius:38 borderColor:UIColorFromRGB(0x28292b) borderWidth:3];
101 | [btView addSubview:shootBt];
102 |
103 | finishBt = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 60, 60)];
104 | finishBt.center = CGPointMake(SCREEN_WIDTH-35, 64+preLayerHeight+20+45);
105 | finishBt.adjustsImageWhenHighlighted = NO;
106 | [finishBt setBackgroundImage:[UIImage imageNamed:@"shootFinish"] forState:UIControlStateNormal];
107 | [finishBt addTarget:self action:@selector(finishBtTap) forControlEvents:UIControlEventTouchUpInside];
108 | finishBt.hidden = YES;
109 | [self.view addSubview:finishBt];
110 |
111 | //初始化会话
112 | _captureSession=[[AVCaptureSession alloc]init];
113 | if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) {//设置分辨率
114 | _captureSession.sessionPreset=AVCaptureSessionPreset640x480;
115 | }
116 |
117 | //获得输入设备
118 | AVCaptureDevice *captureDevice=[self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];//取得后置摄像头
119 | //添加一个音频输入设备
120 | AVCaptureDevice *audioCaptureDevice=[[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
121 |
122 | NSError *error=nil;
123 | //根据输入设备初始化设备输入对象,用于获得输入数据
124 | _captureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:captureDevice error:&error];
125 |
126 | AVCaptureDeviceInput *audioCaptureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:audioCaptureDevice error:&error];
127 |
128 | //初始化设备输出对象,用于获得输出数据
129 | _captureMovieFileOutput=[[AVCaptureMovieFileOutput alloc]init];
130 |
131 | //将设备输入添加到会话中
132 | if ([_captureSession canAddInput:_captureDeviceInput]) {
133 | [_captureSession addInput:_captureDeviceInput];
134 | [_captureSession addInput:audioCaptureDeviceInput];
135 | AVCaptureConnection *captureConnection=[_captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
136 | if ([captureConnection isVideoStabilizationSupported ]) {
137 | captureConnection.preferredVideoStabilizationMode=AVCaptureVideoStabilizationModeAuto;
138 | }
139 | }
140 |
141 | //将设备输出添加到会话中
142 | if ([_captureSession canAddOutput:_captureMovieFileOutput]) {
143 | [_captureSession addOutput:_captureMovieFileOutput];
144 | }
145 |
146 | //创建视频预览层,用于实时展示摄像头状态
147 | _captureVideoPreviewLayer=[[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession];
148 |
149 | CALayer *layer= self.viewContainer.layer;
150 | layer.masksToBounds=YES;
151 |
152 | _captureVideoPreviewLayer.frame= CGRectMake(0, 0, preLayerWidth, preLayerHeight);
153 | _captureVideoPreviewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//填充模式
154 | [layer insertSublayer:_captureVideoPreviewLayer below:self.focusCursor.layer];
155 |
156 | [self addGenstureRecognizer];
157 |
158 | //进度条
159 | progressPreView = [[UIView alloc]initWithFrame:CGRectMake(0, preLayerHeight, 0, 4)];
160 | progressPreView.backgroundColor = UIColorFromRGB(0xffc738);
161 | [progressPreView makeCornerRadius:2 borderColor:nil borderWidth:0];
162 | [self.viewContainer addSubview:progressPreView];
163 |
164 | flashBt = [[UIButton alloc]initWithFrame:CGRectMake(SCREEN_WIDTH-90, 5, 34, 34)];
165 | [flashBt setBackgroundImage:[UIImage imageNamed:@"flashOn"] forState:UIControlStateNormal];
166 | [flashBt makeCornerRadius:17 borderColor:nil borderWidth:0];
167 | [flashBt addTarget:self action:@selector(flashBtTap:) forControlEvents:UIControlEventTouchUpInside];
168 | [self.viewContainer addSubview:flashBt];
169 |
170 | cameraBt = [[UIButton alloc]initWithFrame:CGRectMake(SCREEN_WIDTH-40, 5, 34, 34)];
171 | [cameraBt setBackgroundImage:[UIImage imageNamed:@"changeCamer"] forState:UIControlStateNormal];
172 | [cameraBt makeCornerRadius:17 borderColor:nil borderWidth:0];
173 | [cameraBt addTarget:self action:@selector(changeCamera:) forControlEvents:UIControlEventTouchUpInside];
174 | [self.viewContainer addSubview:cameraBt];
175 |
176 | }
177 | -(void)flashBtTap:(UIButton*)bt{
178 | if (bt.selected == YES) {
179 | bt.selected = NO;
180 | //关闭闪光灯
181 | [flashBt setBackgroundImage:[UIImage imageNamed:@"flashOn"] forState:UIControlStateNormal];
182 | [self setTorchMode:AVCaptureTorchModeOff];
183 | }else{
184 | bt.selected = YES;
185 | //开启闪光灯
186 | [flashBt setBackgroundImage:[UIImage imageNamed:@"flashOff"] forState:UIControlStateNormal];
187 | [self setTorchMode:AVCaptureTorchModeOn];
188 | }
189 | }
190 |
191 | -(void)startTimer{
192 | shootBt.backgroundColor = UIColorFromRGB(0xf8ad6a);
193 |
194 | countTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(onTimer:) userInfo:nil repeats:YES];
195 | [countTimer fire];
196 | }
197 |
198 | -(void)stopTimer{
199 | shootBt.backgroundColor = UIColorFromRGB(0xfa5f66);
200 |
201 | [countTimer invalidate];
202 | countTimer = nil;
203 |
204 | }
205 | - (void)onTimer:(NSTimer *)timer
206 | {
207 | currentTime += TIMER_INTERVAL;
208 | float progressWidth = progressPreView.frame.size.width+progressStep;
209 | [progressPreView setFrame:CGRectMake(0, preLayerHeight, progressWidth, 4)];
210 | if (currentTime>2) {
211 | finishBt.hidden = NO;
212 | }
213 |
214 | //时间到了停止录制视频
215 | if (currentTime>=totalTime) {
216 | [countTimer invalidate];
217 | countTimer = nil;
218 | [_captureMovieFileOutput stopRecording];
219 | }
220 |
221 | }
222 | -(void)finishBtTap{
223 |
224 | currentTime=totalTime+10;
225 | [countTimer invalidate];
226 | countTimer = nil;
227 |
228 | //正在拍摄
229 | if (_captureMovieFileOutput.isRecording) {
230 | [_captureMovieFileOutput stopRecording];
231 | }else{//已经暂停了
232 | [self mergeAndExportVideosAtFileURLs:urlArray];
233 | }
234 | }
235 |
236 | -(void)viewDidAppear:(BOOL)animated{
237 | [super viewDidAppear:animated];
238 | [self.captureSession startRunning];
239 | }
240 |
241 | -(void)viewDidDisappear:(BOOL)animated{
242 | [super viewDidDisappear:animated];
243 | [self.captureSession stopRunning];
244 |
245 | //还原数据-----------
246 | [self deleteAllVideos];
247 | currentTime = 0;
248 | [progressPreView setFrame:CGRectMake(0, preLayerHeight, 0, 4)];
249 | shootBt.backgroundColor = UIColorFromRGB(0xfa5f66);
250 | finishBt.hidden = YES;
251 | }
252 |
253 | #pragma mark 视频录制
254 | - (void)shootButtonClick{
255 | //根据设备输出获得连接
256 | AVCaptureConnection *captureConnection=[self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
257 |
258 | //根据连接取得设备输出的数据
259 | if (![self.captureMovieFileOutput isRecording]) {
260 | shootBt.backgroundColor = UIColorFromRGB(0xfa5f66);
261 | //预览图层和视频方向保持一致
262 | captureConnection.videoOrientation=[self.captureVideoPreviewLayer connection].videoOrientation;
263 | [self.captureMovieFileOutput startRecordingToOutputFileURL:[NSURL fileURLWithPath:[self getVideoSaveFilePathString]] recordingDelegate:self];
264 | }
265 | else{
266 | [self stopTimer];
267 | [self.captureMovieFileOutput stopRecording];//停止录制
268 | }
269 | }
270 | #pragma mark 切换前后摄像头
271 | - (void)changeCamera:(UIButton*)bt {
272 | AVCaptureDevice *currentDevice=[self.captureDeviceInput device];
273 | AVCaptureDevicePosition currentPosition=[currentDevice position];
274 | AVCaptureDevice *toChangeDevice;
275 | AVCaptureDevicePosition toChangePosition=AVCaptureDevicePositionFront;
276 | if (currentPosition==AVCaptureDevicePositionUnspecified||currentPosition==AVCaptureDevicePositionFront) {
277 | toChangePosition=AVCaptureDevicePositionBack;
278 | flashBt.hidden = NO;
279 | }else{
280 | flashBt.hidden = YES;
281 | }
282 | toChangeDevice=[self getCameraDeviceWithPosition:toChangePosition];
283 | //获得要调整的设备输入对象
284 | AVCaptureDeviceInput *toChangeDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:toChangeDevice error:nil];
285 |
286 | //改变会话的配置前一定要先开启配置,配置完成后提交配置改变
287 | [self.captureSession beginConfiguration];
288 | //移除原有输入对象
289 | [self.captureSession removeInput:self.captureDeviceInput];
290 | //添加新的输入对象
291 | if ([self.captureSession canAddInput:toChangeDeviceInput]) {
292 | [self.captureSession addInput:toChangeDeviceInput];
293 | self.captureDeviceInput=toChangeDeviceInput;
294 | }
295 | //提交会话配置
296 | [self.captureSession commitConfiguration];
297 |
298 | //关闭闪光灯
299 | flashBt.selected = NO;
300 | [flashBt setBackgroundImage:[UIImage imageNamed:@"flashOn"] forState:UIControlStateNormal];
301 | [self setTorchMode:AVCaptureTorchModeOff];
302 |
303 | }
304 |
305 | #pragma mark - 视频输出代理
306 | -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections{
307 | NSLog(@"开始录制...");
308 | [self startTimer];
309 | }
310 | -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{
311 |
312 | [urlArray addObject:outputFileURL];
313 | //时间到了
314 | if (currentTime>=totalTime) {
315 | [self mergeAndExportVideosAtFileURLs:urlArray];
316 | }
317 | }
318 | - (void)mergeAndExportVideosAtFileURLs:(NSMutableArray *)fileURLArray
319 | {
320 | NSError *error = nil;
321 |
322 | CGSize renderSize = CGSizeMake(0, 0);
323 |
324 | NSMutableArray *layerInstructionArray = [[NSMutableArray alloc] init];
325 |
326 | AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
327 |
328 | CMTime totalDuration = kCMTimeZero;
329 |
330 | NSMutableArray *assetTrackArray = [[NSMutableArray alloc] init];
331 | NSMutableArray *assetArray = [[NSMutableArray alloc] init];
332 | for (NSURL *fileURL in fileURLArray) {
333 |
334 | AVAsset *asset = [AVAsset assetWithURL:fileURL];
335 | [assetArray addObject:asset];
336 |
337 | NSArray* tmpAry =[asset tracksWithMediaType:AVMediaTypeVideo];
338 | if (tmpAry.count>0) {
339 | AVAssetTrack *assetTrack = [tmpAry objectAtIndex:0];
340 | [assetTrackArray addObject:assetTrack];
341 | renderSize.width = MAX(renderSize.width, assetTrack.naturalSize.height);
342 | renderSize.height = MAX(renderSize.height, assetTrack.naturalSize.width);
343 | }
344 | }
345 |
346 | CGFloat renderW = MIN(renderSize.width, renderSize.height);
347 |
348 | for (int i = 0; i < [assetArray count] && i < [assetTrackArray count]; i++) {
349 |
350 | AVAsset *asset = [assetArray objectAtIndex:i];
351 | AVAssetTrack *assetTrack = [assetTrackArray objectAtIndex:i];
352 |
353 | AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
354 |
355 | NSArray*dataSourceArray= [asset tracksWithMediaType:AVMediaTypeAudio];
356 | [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
357 | ofTrack:([dataSourceArray count]>0)?[dataSourceArray objectAtIndex:0]:nil
358 | atTime:totalDuration
359 | error:nil];
360 |
361 | AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
362 |
363 | [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
364 | ofTrack:assetTrack
365 | atTime:totalDuration
366 | error:&error];
367 |
368 | AVMutableVideoCompositionLayerInstruction *layerInstruciton = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
369 |
370 | totalDuration = CMTimeAdd(totalDuration, asset.duration);
371 |
372 | CGFloat rate;
373 | rate = renderW / MIN(assetTrack.naturalSize.width, assetTrack.naturalSize.height);
374 |
375 | CGAffineTransform layerTransform = CGAffineTransformMake(assetTrack.preferredTransform.a, assetTrack.preferredTransform.b, assetTrack.preferredTransform.c, assetTrack.preferredTransform.d, assetTrack.preferredTransform.tx * rate, assetTrack.preferredTransform.ty * rate);
376 | layerTransform = CGAffineTransformConcat(layerTransform, CGAffineTransformMake(1, 0, 0, 1, 0, -(assetTrack.naturalSize.width - assetTrack.naturalSize.height) / 2.0+preLayerHWRate*(preLayerHeight-preLayerWidth)/2));
377 | layerTransform = CGAffineTransformScale(layerTransform, rate, rate);
378 |
379 | [layerInstruciton setTransform:layerTransform atTime:kCMTimeZero];
380 | [layerInstruciton setOpacity:0.0 atTime:totalDuration];
381 |
382 | [layerInstructionArray addObject:layerInstruciton];
383 | }
384 |
385 | NSString *path = [self getVideoMergeFilePathString];
386 | NSURL *mergeFileURL = [NSURL fileURLWithPath:path];
387 |
388 | AVMutableVideoCompositionInstruction *mainInstruciton = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
389 | mainInstruciton.timeRange = CMTimeRangeMake(kCMTimeZero, totalDuration);
390 | mainInstruciton.layerInstructions = layerInstructionArray;
391 | AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
392 | mainCompositionInst.instructions = @[mainInstruciton];
393 | mainCompositionInst.frameDuration = CMTimeMake(1, 100);
394 | mainCompositionInst.renderSize = CGSizeMake(renderW, renderW*preLayerHWRate);
395 |
396 | AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
397 | exporter.videoComposition = mainCompositionInst;
398 | exporter.outputURL = mergeFileURL;
399 | exporter.outputFileType = AVFileTypeMPEG4;
400 | exporter.shouldOptimizeForNetworkUse = YES;
401 | [exporter exportAsynchronouslyWithCompletionHandler:^{
402 | dispatch_async(dispatch_get_main_queue(), ^{
403 |
404 | PlayVideoViewController* view = [[PlayVideoViewController alloc]init];
405 | view.videoURL =mergeFileURL;
406 | [self.navigationController pushViewController:view animated:YES];
407 |
408 | });
409 | }];
410 |
411 |
412 | }
413 | //最后合成为 mp4
414 | - (NSString *)getVideoMergeFilePathString
415 | {
416 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
417 | NSString *path = [paths objectAtIndex:0];
418 |
419 | path = [path stringByAppendingPathComponent:VIDEO_FOLDER];
420 |
421 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
422 | formatter.dateFormat = @"yyyyMMddHHmmss";
423 | NSString *nowTimeStr = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]];
424 |
425 | NSString *fileName = [[path stringByAppendingPathComponent:nowTimeStr] stringByAppendingString:@"merge.mp4"];
426 |
427 | return fileName;
428 | }
429 |
430 | //录制保存的时候要保存为 mov
431 | - (NSString *)getVideoSaveFilePathString
432 | {
433 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
434 | NSString *path = [paths objectAtIndex:0];
435 |
436 | path = [path stringByAppendingPathComponent:VIDEO_FOLDER];
437 |
438 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
439 | formatter.dateFormat = @"yyyyMMddHHmmss";
440 | NSString *nowTimeStr = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]];
441 |
442 | NSString *fileName = [[path stringByAppendingPathComponent:nowTimeStr] stringByAppendingString:@".mov"];
443 |
444 | return fileName;
445 | }
446 |
447 | - (void)createVideoFolderIfNotExist
448 | {
449 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
450 | NSString *path = [paths objectAtIndex:0];
451 |
452 | NSString *folderPath = [path stringByAppendingPathComponent:VIDEO_FOLDER];
453 |
454 | NSFileManager *fileManager = [NSFileManager defaultManager];
455 | BOOL isDir = NO;
456 | BOOL isDirExist = [fileManager fileExistsAtPath:folderPath isDirectory:&isDir];
457 |
458 | if(!(isDirExist && isDir))
459 | {
460 | BOOL bCreateDir = [fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
461 | if(!bCreateDir){
462 | NSLog(@"创建保存视频文件夹失败");
463 | }
464 | }
465 | }
466 | - (void)deleteAllVideos
467 | {
468 | for (NSURL *videoFileURL in urlArray) {
469 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
470 | NSString *filePath = [[videoFileURL absoluteString] stringByReplacingOccurrencesOfString:@"file://" withString:@""];
471 | NSFileManager *fileManager = [NSFileManager defaultManager];
472 | if ([fileManager fileExistsAtPath:filePath]) {
473 | NSError *error = nil;
474 | [fileManager removeItemAtPath:filePath error:&error];
475 |
476 | if (error) {
477 | NSLog(@"delete All Video 删除视频文件出错:%@", error);
478 | }
479 | }
480 | });
481 | }
482 | [urlArray removeAllObjects];
483 | }
484 |
485 | #pragma mark - 私有方法
486 | -(AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position{
487 | NSArray *cameras= [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
488 | for (AVCaptureDevice *camera in cameras) {
489 | if ([camera position]==position) {
490 | return camera;
491 | }
492 | }
493 | return nil;
494 | }
495 |
496 | -(void)changeDeviceProperty:(PropertyChangeBlock)propertyChange{
497 | AVCaptureDevice *captureDevice= [self.captureDeviceInput device];
498 | NSError *error;
499 | //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁
500 | if ([captureDevice lockForConfiguration:&error]) {
501 | propertyChange(captureDevice);
502 | [captureDevice unlockForConfiguration];
503 | }else{
504 | NSLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription);
505 | }
506 | }
507 |
508 | -(void)setTorchMode:(AVCaptureTorchMode )torchMode{
509 | [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
510 | if ([captureDevice isTorchModeSupported:torchMode]) {
511 | [captureDevice setTorchMode:torchMode];
512 | }
513 | }];
514 | }
515 |
516 | -(void)setFocusMode:(AVCaptureFocusMode )focusMode{
517 | [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
518 | if ([captureDevice isFocusModeSupported:focusMode]) {
519 | [captureDevice setFocusMode:focusMode];
520 | }
521 | }];
522 | }
523 |
524 | -(void)setExposureMode:(AVCaptureExposureMode)exposureMode{
525 | [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
526 | if ([captureDevice isExposureModeSupported:exposureMode]) {
527 | [captureDevice setExposureMode:exposureMode];
528 | }
529 | }];
530 | }
531 |
532 | -(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{
533 | [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
534 | if ([captureDevice isFocusModeSupported:focusMode]) {
535 | [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];
536 | }
537 | if ([captureDevice isFocusPointOfInterestSupported]) {
538 | [captureDevice setFocusPointOfInterest:point];
539 | }
540 | if ([captureDevice isExposureModeSupported:exposureMode]) {
541 | [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];
542 | }
543 | if ([captureDevice isExposurePointOfInterestSupported]) {
544 | [captureDevice setExposurePointOfInterest:point];
545 | }
546 | }];
547 | }
548 |
549 | -(void)addGenstureRecognizer{
550 | UITapGestureRecognizer *tapGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapScreen:)];
551 | [self.viewContainer addGestureRecognizer:tapGesture];
552 | }
553 | -(void)tapScreen:(UITapGestureRecognizer *)tapGesture{
554 | CGPoint point= [tapGesture locationInView:self.viewContainer];
555 | //将UI坐标转化为摄像头坐标
556 | CGPoint cameraPoint= [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];
557 | [self setFocusCursorWithPoint:point];
558 | [self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];
559 | }
560 |
561 | -(void)setFocusCursorWithPoint:(CGPoint)point{
562 | self.focusCursor.center=point;
563 | self.focusCursor.transform=CGAffineTransformMakeScale(1.5, 1.5);
564 | self.focusCursor.alpha=1.0;
565 | [UIView animateWithDuration:1.0 animations:^{
566 | self.focusCursor.transform=CGAffineTransformIdentity;
567 | } completion:^(BOOL finished) {
568 | self.focusCursor.alpha=0;
569 |
570 | }];
571 | }
572 | @end
573 |
--------------------------------------------------------------------------------