├── FSJCompression ├── Assets.xcassets │ ├── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── PrefixHeader.pch ├── ViewController.h ├── FSJCompression.xcdatamodeld │ ├── .xccurrentversion │ └── FSJCompression.xcdatamodel │ │ └── contents ├── Controllers │ ├── FSJMainViewController.h │ ├── Tools │ │ ├── FSVideoImageTool.h │ │ ├── FSPathTool.h │ │ ├── FSPathTool.m │ │ └── FSVideoImageTool.m │ └── FSJMainViewController.m ├── ViewController.m ├── AppDelegate.h ├── main.m ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── Info.plist └── AppDelegate.m ├── Libs ├── FSJCompression.h ├── FSJCompressionBlockHeader.h ├── FSJCompressionImageTool.h ├── FSJCompressionImageTool.m ├── FSJCompressionVideoTool.h └── FSJCompressionVideoTool.m ├── Podfile ├── FSJCompressionTests ├── Info.plist └── FSJCompressionTests.m ├── FSJCompressionUITests ├── Info.plist └── FSJCompressionUITests.m ├── .gitignore ├── README.md ├── LICENSE ├── FSJCompression.podspec └── FSJCompression.xcodeproj └── project.pbxproj /FSJCompression/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Libs/FSJCompression.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompression.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | // 视频压缩 10 | #import "FSJCompressionVideoTool.h" 11 | -------------------------------------------------------------------------------- /FSJCompression/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "FSJUtilityGlobal.h" 10 | #import "Masonry.h" 11 | -------------------------------------------------------------------------------- /FSJCompression/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /FSJCompression/FSJCompression.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | FSJCompression.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /FSJCompression/Controllers/FSJMainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSJMainViewController.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface FSJMainViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /FSJCompression/FSJCompression.xcdatamodeld/FSJCompression.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Libs/FSJCompressionBlockHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionBlockHeader.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void (^ FSJCompressionProgressBlock)(CGFloat progress); 12 | typedef void (^ FSJCompressionCompleteBlock)(BOOL isSuccess, NSURL * _Nullable outputURL); 13 | -------------------------------------------------------------------------------- /FSJCompression/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /FSJCompression/Controllers/Tools/FSVideoImageTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSVideoImageTool.h 3 | // FSGPUImage 4 | // 5 | // Created by 燕来秋 on 2020/7/14. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface FSVideoImageTool : NSObject 15 | 16 | + (void)getVideoURL:(PHAsset *)phAsset block:(void (^)(NSURL *URL))block; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /FSJCompression/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (readonly, strong) NSPersistentContainer *persistentContainer; 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | - (void)saveContext; 18 | 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /Libs/FSJCompressionImageTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionImageTool.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/9/4. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 图片压缩 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface FSJCompressionImageTool : NSObject 14 | 15 | /// 图片尺寸压缩 16 | /// @param image 图片 17 | /// @param size 压缩尺寸 18 | - (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /FSJCompression/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'FSJCompression' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | pod 'FSJUtility' 9 | pod 'Masonry', '~> 1.1.0' 10 | pod 'TZImagePickerController' 11 | pod 'CHGAdapter', '~> 1.1.4' 12 | pod 'MBProgressHUD' 13 | 14 | # Pods for FSJCompression 15 | 16 | target 'FSJCompressionTests' do 17 | inherit! :search_paths 18 | # Pods for testing 19 | end 20 | 21 | target 'FSJCompressionUITests' do 22 | # Pods for testing 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /FSJCompression/Controllers/Tools/FSPathTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSPathTool.h 3 | // FSGPUImage 4 | // 5 | // Created by 燕来秋 on 2020/7/14. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define DNRecordTmpFloder @"FS_Record_Tmp" 12 | #define DNRecordCompoundFolder @"FS_Video_Compound" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface FSPathTool : NSObject 17 | 18 | // 创建/获取Document下的目录 19 | + (NSString *)folderPathWithName:(NSString *)name; 20 | 21 | /// 目录下的文件 22 | /// @param name 目录名字 23 | /// @param fileName 文件名字 (可为空) 24 | + (NSString *)folderVideoPathWithName:(NSString *)name fileName:(NSString * __nullable)fileName; 25 | 26 | // 名字 27 | + (NSString *)createName; 28 | 29 | 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /FSJCompressionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /FSJCompressionUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 26 | # Carthage/Checkouts 27 | 28 | Carthage/Build 29 | 30 | # We recommend against adding the Pods directory to your .gitignore. However 31 | # you should judge for yourself, the pros and cons are mentioned at: 32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 33 | # 34 | # Note: if you ignore the Pods directory, make sure to uncomment 35 | # `pod install` in .travis.yml 36 | # 37 | # Pods/ 38 | -------------------------------------------------------------------------------- /FSJCompressionTests/FSJCompressionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionTests.m 3 | // FSJCompressionTests 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FSJCompressionTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation FSJCompressionTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FSJCompression 2 | 3 | [![CI Status](https://img.shields.io/travis/fanshij@163.com/FSJCompression.svg?style=flat)](https://travis-ci.org/fanshij@163.com/FSJCompression) 4 | [![Version](https://img.shields.io/cocoapods/v/FSJCompression.svg?style=flat)](https://cocoapods.org/pods/FSJCompression) 5 | [![License](https://img.shields.io/cocoapods/l/FSJCompression.svg?style=flat)](https://cocoapods.org/pods/FSJCompression) 6 | [![Platform](https://img.shields.io/cocoapods/p/FSJCompression.svg?style=flat)](https://cocoapods.org/pods/FSJCompression) 7 | 8 | ## Example 9 | 10 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 11 | 12 | ## Requirements 13 | 14 | ## Installation 15 | 16 | FSJCompression is available through [CocoaPods](https://cocoapods.org). To install 17 | it, simply add the following line to your Podfile: 18 | 19 | ```ruby 20 | pod 'FSJCompression' 21 | ``` 22 | 23 | ## Author 24 | 25 | fanshij@163.com, fanshij@163.com 26 | 27 | ## License 28 | 29 | FSJCompression is available under the MIT license. See the LICENSE file for more info. 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 fanshij@163.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Libs/FSJCompressionImageTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionImageTool.m 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/9/4. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "FSJCompressionImageTool.h" 10 | 11 | @implementation FSJCompressionImageTool 12 | 13 | /// 缩放图片至新尺寸 14 | - (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size { 15 | if (image.size.width > size.width) { 16 | UIGraphicsBeginImageContext(size); 17 | [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; 18 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 19 | UIGraphicsEndImageContext(); 20 | return newImage; 21 | 22 | /* 好像不怎么管用:https://mp.weixin.qq.com/s/CiqMlEIp1Ir2EJSDGgMooQ 23 | CGFloat maxPixelSize = MAX(size.width, size.height); 24 | CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)UIImageJPEGRepresentation(image, 0.9), nil); 25 | NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue, 26 | (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize] 27 | }; 28 | CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options); 29 | UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:2 orientation:image.imageOrientation]; 30 | CGImageRelease(imageRef); 31 | CFRelease(sourceRef); 32 | return newImage; 33 | */ 34 | } else { 35 | return image; 36 | } 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /FSJCompressionUITests/FSJCompressionUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionUITests.m 3 | // FSJCompressionUITests 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FSJCompressionUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation FSJCompressionUITests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | 20 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | - (void)tearDown { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | } 29 | 30 | - (void)testExample { 31 | // UI tests must launch the application that they test. 32 | XCUIApplication *app = [[XCUIApplication alloc] init]; 33 | [app launch]; 34 | 35 | // Use recording to get started writing UI tests. 36 | // Use XCTAssert and related functions to verify your tests produce the correct results. 37 | } 38 | 39 | - (void)testLaunchPerformance { 40 | if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { 41 | // This measures how long it takes to launch your application. 42 | [self measureWithMetrics:@[XCTOSSignpostMetric.applicationLaunchMetric] block:^{ 43 | [[[XCUIApplication alloc] init] launch]; 44 | }]; 45 | } 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /FSJCompression/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /FSJCompression/Controllers/Tools/FSPathTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSPathTool.m 3 | // FSGPUImage 4 | // 5 | // Created by 燕来秋 on 2020/7/14. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "FSPathTool.h" 10 | 11 | @implementation FSPathTool 12 | 13 | #pragma mark - 路径 14 | + (NSString *)rootPath { 15 | NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 16 | return cacheFolder; 17 | } 18 | 19 | + (NSString *)folderPathWithName:(NSString *)folder { 20 | NSString *path = [NSString stringWithFormat:@"%@/%@",[self rootPath],folder]; 21 | if (folder == nil) { 22 | path = [self rootPath]; 23 | } 24 | if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:nil]) { 25 | [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil]; 26 | } 27 | return path; 28 | } 29 | 30 | + (NSString *)folderVideoPathWithName:(NSString *)name fileName:(NSString *)fileName { 31 | NSString *videoFolder = [self folderPathWithName:name]; 32 | NSString *nameString = fileName; 33 | if (nameString == nil) { 34 | NSString *nowTimeStr = [self createName]; 35 | nameString = [NSString stringWithFormat:@"%@.mp4",nowTimeStr]; 36 | } 37 | NSString *urlString = [NSString stringWithFormat:@"%@/%@", videoFolder, nameString]; 38 | return urlString; 39 | } 40 | 41 | + (NSString *)createName { 42 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 43 | formatter.dateFormat = @"yyyyMMddHHmmssSSS"; 44 | NSString *nowTimeStr = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]]; 45 | return nowTimeStr; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /FSJCompression/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSPhotoLibraryUsageDescription 24 | 发送图片需要获取相册权限 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /FSJCompression/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FSJCompression.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint FSJCompression.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'FSJCompression' 11 | s.version = '0.1.5' 12 | s.summary = 'A short description of FSJCompression.' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | TODO: Add long description of the pod here. 22 | DESC 23 | 24 | s.homepage = 'https://github.com/smallMas/FSJCompression' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'fanshij@163.com' => 'fanshij@163.com' } 28 | s.source = { :git => 'https://github.com/smallMas/FSJCompression.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '8.0' 32 | 33 | #s.source_files = 'FSJCompression/Classes/**/*' 34 | # 从podspec同级目录开始 35 | s.source_files = 'Libs/**/*.{m,h}' 36 | 37 | # s.resource_bundles = { 38 | # 'FSJCompression' => ['FSJCompression/Assets/*.png'] 39 | # } 40 | 41 | # s.public_header_files = 'Pod/Classes/**/*.h' 42 | # s.frameworks = 'UIKit', 'MapKit' 43 | # s.dependency 'AFNetworking', '~> 2.3' 44 | end 45 | -------------------------------------------------------------------------------- /FSJCompression/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /FSJCompression/Controllers/Tools/FSVideoImageTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSVideoImageTool.m 3 | // FSGPUImage 4 | // 5 | // Created by 燕来秋 on 2020/7/14. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "FSVideoImageTool.h" 10 | #import 11 | #import "FSPathTool.h" 12 | 13 | @implementation FSVideoImageTool 14 | 15 | + (void)getVideoURL:(PHAsset *)phAsset block:(void (^)(NSURL *URL))block { 16 | PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init]; 17 | options.version = PHVideoRequestOptionsVersionOriginal; 18 | __block NSURL *url = nil; 19 | __weak typeof(self) wself = self; 20 | [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) { 21 | if ([asset isKindOfClass:[AVURLAsset class]]) { 22 | AVURLAsset *urlAsset = (AVURLAsset*)asset; 23 | NSNumber *size; 24 | [urlAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil]; 25 | NSData *data = [[NSData alloc] initWithContentsOfURL:urlAsset.URL]; 26 | url = [wself getVideoFilePath]; 27 | BOOL is = [[NSFileManager defaultManager] createFileAtPath:url.path contents:data attributes:nil]; 28 | if (is) { 29 | NSLog(@"视频保存沙盒成功"); 30 | if (block) { 31 | block(url); 32 | } 33 | }else { 34 | NSLog(@"视频保存沙盒失败"); 35 | if (block) { 36 | block(nil); 37 | } 38 | } 39 | } 40 | }]; 41 | } 42 | 43 | + (NSURL *)getVideoFilePath { 44 | return [self getVideoFilePathWithName:nil]; 45 | } 46 | 47 | + (NSURL *)getVideoFilePathWithName:(NSString *)name { 48 | NSString *videoFolder = [FSPathTool folderPathWithName:DNRecordTmpFloder]; 49 | NSString *nameString = name; 50 | if (nameString == nil) { 51 | NSString *nowTimeStr = [FSPathTool createName]; 52 | nameString = [NSString stringWithFormat:@"%@.mp4",nowTimeStr]; 53 | } 54 | NSString *urlString = [NSString stringWithFormat:@"%@/%@", videoFolder, nameString]; 55 | return [NSURL fileURLWithPath:urlString]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /FSJCompression/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "FSJMainViewController.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 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 22 | self.window.backgroundColor = [UIColor whiteColor]; 23 | 24 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[FSJMainViewController new]]; 25 | self.window.rootViewController = nav; 26 | 27 | [self.window makeKeyAndVisible]; 28 | 29 | return YES; 30 | } 31 | 32 | #pragma mark - Core Data stack 33 | 34 | @synthesize persistentContainer = _persistentContainer; 35 | 36 | - (NSPersistentContainer *)persistentContainer { 37 | // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it. 38 | @synchronized (self) { 39 | if (_persistentContainer == nil) { 40 | _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"FSJCompression"]; 41 | [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { 42 | if (error != nil) { 43 | // Replace this implementation with code to handle the error appropriately. 44 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 45 | 46 | /* 47 | Typical reasons for an error here include: 48 | * The parent directory does not exist, cannot be created, or disallows writing. 49 | * The persistent store is not accessible, due to permissions or data protection when the device is locked. 50 | * The device is out of space. 51 | * The store could not be migrated to the current model version. 52 | Check the error message to determine what the actual problem was. 53 | */ 54 | NSLog(@"Unresolved error %@, %@", error, error.userInfo); 55 | abort(); 56 | } 57 | }]; 58 | } 59 | } 60 | 61 | return _persistentContainer; 62 | } 63 | 64 | #pragma mark - Core Data Saving support 65 | 66 | - (void)saveContext { 67 | NSManagedObjectContext *context = self.persistentContainer.viewContext; 68 | NSError *error = nil; 69 | if ([context hasChanges] && ![context save:&error]) { 70 | // Replace this implementation with code to handle the error appropriately. 71 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 72 | NSLog(@"Unresolved error %@, %@", error, error.userInfo); 73 | abort(); 74 | } 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Libs/FSJCompressionVideoTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionVideoTool.h 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSJCompressionBlockHeader.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface FSJCompressionVideoTool : NSObject 15 | 16 | 17 | /* 18 | * 自定义视频压缩 19 | * videoUrl 原视频url路径 必传 20 | * outputURL 输出url路径,不传默认/Library/Caches/videoTest.mp4 21 | * outputBiteRate 压缩视频至指定比特率(bps) 可传nil 默认1500kbps 22 | * outputFrameRate 压缩视频至指定帧率 可传nil 默认30fps 23 | * outputWidth 压缩视频至指定宽度 可传nil 默认960 24 | * outputWidth 压缩视频至指定高度 可传nil 默认540 25 | * progressBlock 压缩进度回调 26 | * compressComplete 压缩后的视频信息回调 (id responseObjc) 可自行打印查看 27 | **/ 28 | + (void)compressVideoWithVideoUrl:(NSURL *)videoUrl 29 | outputURL:(NSURL *)outputURL 30 | withBiteRate:(NSNumber * _Nullable)outputBiteRate 31 | withFrameRate:(NSNumber * _Nullable)outputFrameRate 32 | withVideoWidth:(NSNumber * _Nullable)outputWidth 33 | withVideoHeight:(NSNumber * _Nullable)outputHeight 34 | progressBlock:(FSJCompressionProgressBlock)progressBlock 35 | compressComplete:(FSJCompressionCompleteBlock)compressComplete; 36 | 37 | /* 38 | * 自定义视频压缩 默认1500kbps 默认30fps 默认960 默认540 39 | * videoUrl 原视频url路径 必传 40 | * outputURL 输出url路径,不传默认/Library/Caches/videoTest.mp4 41 | * progressBlock 压缩进度回调 42 | * compressComplete 压缩后的视频信息回调 (id responseObjc) 可自行打印查看 43 | **/ 44 | + (void)compressVideoWithVideoUrl:(NSURL *)videoUrl 45 | outputURL:(NSURL *)outputURL 46 | progressBlock:(FSJCompressionProgressBlock)progressBlock 47 | compressComplete:(FSJCompressionCompleteBlock)compressComplete; 48 | 49 | #pragma mark - 生成视频 50 | /// 生成视频并压缩 51 | /// @param asset AVAsset 52 | /// @param outputURL 输出url路径,不传默认/Library/Caches/videoTest.mp4 53 | /// @param outputBiteRate 压缩视频至指定比特率(bps) 可传nil 默认1500kbps 54 | /// @param outputFrameRate 压缩视频至指定帧率 可传nil 默认30fps 55 | /// @param outputWidth 压缩视频至指定宽度 可传nil 默认960 56 | /// @param outputHeight 压缩视频至指定高度 可传nil 默认540 57 | /// @param transform 方向 58 | /// @param progressBlock 进度回调 59 | /// @param compressComplete 视频信息回调 (id responseObjc) 可自行打印查看 60 | + (void)compressVideoWithVideoAsset:(AVURLAsset *)asset 61 | outputURL:(NSURL *)outputURL 62 | withBiteRate:(NSNumber * _Nullable)outputBiteRate 63 | withFrameRate:(NSNumber * _Nullable)outputFrameRate 64 | withVideoWidth:(NSNumber * _Nullable)outputWidth 65 | withVideoHeight:(NSNumber * _Nullable)outputHeight 66 | transform:(CGAffineTransform)transform 67 | progressBlock:(FSJCompressionProgressBlock)progressBlock 68 | compressComplete:(FSJCompressionCompleteBlock)compressComplete; 69 | 70 | /// 生成视频并压缩 默认1500kbps 默认30fps 默认960 默认540 71 | /// @param asset AVAsset 72 | /// @param outputURL 输出url路径,不传默认/Library/Caches/videoTest.mp4 73 | /// @param transform 方向 74 | /// @param progressBlock 进度回调 75 | /// @param compressComplete 视频信息回调 (id responseObjc) 可自行打印查看 76 | + (void)compressVideoWithVideoAsset:(AVURLAsset *)asset 77 | outputURL:(NSURL *)outputURL 78 | transform:(CGAffineTransform)transform 79 | progressBlock:(FSJCompressionProgressBlock)progressBlock 80 | compressComplete:(FSJCompressionCompleteBlock)compressComplete; 81 | @end 82 | 83 | NS_ASSUME_NONNULL_END 84 | -------------------------------------------------------------------------------- /FSJCompression/Controllers/FSJMainViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSJMainViewController.m 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "FSJMainViewController.h" 10 | #import "TZImagePickerController.h" 11 | #import "FSVideoImageTool.h" 12 | #import "FSPathTool.h" 13 | #import "FSJCompression.h" 14 | 15 | @interface FSJMainViewController () 16 | 17 | @property (nonatomic, strong) UIButton *albumBtn; 18 | 19 | @end 20 | 21 | @implementation FSJMainViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | // Do any additional setup after loading the view. 26 | [self.view addSubview:self.albumBtn]; 27 | 28 | [self.albumBtn mas_makeConstraints:^(MASConstraintMaker *make) { 29 | make.width.mas_equalTo(100); 30 | make.height.mas_equalTo(50); 31 | make.center.mas_equalTo(self.view); 32 | }]; 33 | } 34 | 35 | - (UIButton *)albumBtn { 36 | if (!_albumBtn) { 37 | _albumBtn = [UIButton fsj_createWithType:UIButtonTypeCustom target:self action:@selector(albumAction:)]; 38 | [_albumBtn setBackgroundColor:[UIColor redColor]]; 39 | [_albumBtn setTitle:@"相册" forState:UIControlStateNormal]; 40 | [_albumBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 41 | } 42 | return _albumBtn; 43 | } 44 | 45 | - (void)albumAction:(id)sender { 46 | TZImagePickerController *_imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; 47 | // 2. Set the appearance 48 | // 2. 在这里设置imagePickerVc的外观 49 | 50 | // 3. 设置是否可以选择视频/图片/原图 51 | _imagePickerVc.allowPickingVideo = YES; // 是否允许选择视频 52 | _imagePickerVc.allowPickingImage = NO; //是否允许选择图片 53 | _imagePickerVc.allowPickingOriginalPhoto = NO;// 是否允许选择原片 54 | _imagePickerVc.allowPickingGif = NO; //是否允许选择GIF 55 | _imagePickerVc.allowCrop = YES; 56 | _imagePickerVc.timeout = 2; 57 | _imagePickerVc.cropRect = CGRectMake(0, 0, FSJSCREENWIDTH, FSJSCREENWIDTH); 58 | _imagePickerVc.cropRectPortrait = CGRectMake(0, 0, FSJSCREENWIDTH, FSJSCREENWIDTH); 59 | // 4. 照片排列按修改时间升序 60 | _imagePickerVc.sortAscendingByModificationDate = YES; 61 | _imagePickerVc.showSelectBtn = NO; 62 | _imagePickerVc.needCircleCrop = NO; 63 | // _imagePickerVc.photoWidth = SCREENWIDTH*2; 64 | _imagePickerVc.circleCropRadius = FSJSCREENWIDTH/2; 65 | _imagePickerVc.statusBarStyle = UIStatusBarStyleDefault; 66 | // _imagePickerVc.barItemTextColor = DSColorFromHex(0x323232); 67 | // _imagePickerVc.naviTitleColor = DSColorFromHex(0x323232); 68 | _imagePickerVc.navigationItem.leftBarButtonItem.tintColor = [UIColor blackColor]; 69 | 70 | _imagePickerVc.navigationBar.barTintColor = self.navigationController.navigationBar.barTintColor; 71 | // _imagePickerVc.navigationBar.tintColor = DSColorFromHex(0x323232); 72 | UIBarButtonItem *tzBarItem, *BarItem; 73 | tzBarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]]; 74 | BarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UIImagePickerController class]]]; 75 | //设置返回图片,防止图片被渲染变蓝,以原图显示 76 | _imagePickerVc.navigationBar.backIndicatorTransitionMaskImage = [[UIImage imageNamed:@"public_icon_white_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 77 | _imagePickerVc.navigationBar.backIndicatorImage = [[UIImage imageNamed:@"public_icon_white_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 78 | NSDictionary *titleTextAttributes = [tzBarItem titleTextAttributesForState:UIControlStateNormal]; 79 | [BarItem setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal]; 80 | _imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; 81 | [self presentViewController:_imagePickerVc animated:YES completion:nil]; 82 | } 83 | 84 | #pragma mark - TZImagePickerControllerDelegate 85 | - (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(PHAsset *)asset { 86 | NSLog(@"asset >>> %@",asset); 87 | 88 | FSJ_WEAK_SELF 89 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 90 | [FSVideoImageTool getVideoURL:asset block:^(NSURL * _Nonnull URL) { 91 | FSJ_STRONG_SELF 92 | dispatch_async(dispatch_get_main_queue(), ^{ 93 | if (URL) { 94 | [self compressionURL:URL]; 95 | } 96 | }); 97 | }]; 98 | }); 99 | } 100 | 101 | - (void)compressionURL:(NSURL *)URL { 102 | NSString *outPutPath = [FSPathTool folderVideoPathWithName:DNRecordCompoundFolder fileName:nil]; 103 | NSURL *outPutURL = [NSURL fileURLWithPath:outPutPath]; 104 | [FSJCompressionVideoTool compressVideoWithVideoUrl:URL outputURL:outPutURL withBiteRate:nil withFrameRate:nil withVideoWidth:nil withVideoHeight:nil progressBlock:^(CGFloat progress) { 105 | NSLog(@"progress >>> %f",progress); 106 | } compressComplete:^(BOOL isSuccess, NSURL * _Nullable outputURL) { 107 | NSLog(@"isSuccess >>> %d outputURL : %@",isSuccess,outputURL); 108 | }]; 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /Libs/FSJCompressionVideoTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSJCompressionVideoTool.m 3 | // FSJCompression 4 | // 5 | // Created by 燕来秋 on 2020/8/17. 6 | // Copyright © 2020 燕来秋. All rights reserved. 7 | // 8 | 9 | #import "FSJCompressionVideoTool.h" 10 | #import 11 | 12 | /* 13 | 参考: 14 | https://www.jianshu.com/p/ea502efb0f15 15 | https://github.com/BMWMWM/iOS-AVFoundation-VideoCustomComPressed/blob/master/AVFoundationVideoCustomComPressedDemo/VideoCompress.m 16 | */ 17 | 18 | @implementation FSJCompressionVideoTool 19 | /* 20 | * 自定义视频压缩 21 | * videoUrl 原视频url路径 必传 22 | * outputURL 输出url路径,不传默认/Library/Caches/videoTest.mp4 23 | * outputBiteRate 压缩视频至指定比特率(bps) 可传nil 默认1500kbps 24 | * outputFrameRate 压缩视频至指定帧率 可传nil 默认30fps 25 | * outputWidth 压缩视频至指定宽度 可传nil 默认960 26 | * outputWidth 压缩视频至指定高度 可传nil 默认540 27 | * progressBlock 压缩进度回调 28 | * compressComplete 压缩后的视频信息回调 (id responseObjc) 可自行打印查看 29 | **/ 30 | + (void)compressVideoWithVideoUrl:(NSURL *)videoUrl 31 | outputURL:(NSURL *)outputURL 32 | withBiteRate:(NSNumber * _Nullable)outputBiteRate 33 | withFrameRate:(NSNumber * _Nullable)outputFrameRate 34 | withVideoWidth:(NSNumber * _Nullable)outputWidth 35 | withVideoHeight:(NSNumber * _Nullable)outputHeight 36 | progressBlock:(FSJCompressionProgressBlock)progressBlock 37 | compressComplete:(FSJCompressionCompleteBlock)compressComplete { 38 | if (!videoUrl) { 39 | if (compressComplete) { 40 | compressComplete(NO, nil); 41 | } 42 | return; 43 | } 44 | NSLog(@"压缩视频 : %@",videoUrl.path); 45 | NSInteger compressBiteRate = outputBiteRate ? [outputBiteRate integerValue] : 1500 * 1024; 46 | NSInteger compressFrameRate = outputFrameRate ? [outputFrameRate integerValue] : 30; 47 | NSInteger compressWidth = outputWidth ? [outputWidth integerValue] : 960; 48 | NSInteger compressHeight = outputHeight ? [outputHeight integerValue] : 540; 49 | //取出原视频详细资料 50 | AVURLAsset *asset = [AVURLAsset assetWithURL:videoUrl]; 51 | //视频时长 S 52 | CMTime time = [asset duration]; 53 | NSInteger seconds = ceil(time.value/time.timescale); 54 | if (seconds < 3) { 55 | if (compressComplete) { 56 | compressComplete(NO, nil); 57 | } 58 | return; 59 | } 60 | //压缩前原视频大小MB 61 | unsigned long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:videoUrl.path error:nil].fileSize; 62 | float fileSizeMB = fileSize / (1024.0*1024.0); 63 | //取出asset中的视频文件 64 | AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject; 65 | //压缩前原视频宽高 66 | NSInteger videoWidth = videoTrack.naturalSize.width; 67 | NSInteger videoHeight = videoTrack.naturalSize.height; 68 | 69 | //压缩前原视频比特率 70 | NSInteger kbps = videoTrack.estimatedDataRate / 1024; 71 | //压缩前原视频帧率 72 | // NSInteger frameRate = [videoTrack nominalFrameRate]; 73 | NSLog(@"原视频大小 : %f videoWidth : %ld videoHeight : %ld",fileSizeMB,(long)videoWidth,(long)videoHeight); 74 | //原视频比特率小于指定比特率 不压缩 返回原视频 75 | if (kbps <= (compressBiteRate / 1024)) { 76 | NSLog(@"原视频的比特率小于压缩的比特率,所以不压缩"); 77 | if (compressComplete) { 78 | compressComplete(NO, videoUrl); 79 | } 80 | return; 81 | } 82 | //指定压缩视频沙盒根目录 83 | NSURL *outPutPathURL = outputURL; 84 | if (outPutPathURL == nil) { 85 | NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; 86 | //添加文件完整路径 87 | NSString *outputUrlStr = [[cachesDir stringByAppendingPathComponent:@"videoTest"] stringByAppendingPathExtension:@"mp4"]; 88 | outPutPathURL = [NSURL fileURLWithPath:outputUrlStr]; 89 | } 90 | 91 | //如果指定路径下已存在其他文件 先移除指定文件 92 | if ([[NSFileManager defaultManager] fileExistsAtPath:outPutPathURL.path]) { 93 | BOOL removeSuccess = [[NSFileManager defaultManager] removeItemAtPath:outPutPathURL.path error:nil]; 94 | if (!removeSuccess) { 95 | if (compressComplete) { 96 | compressComplete(NO, videoUrl); 97 | } 98 | return; 99 | } 100 | } 101 | //创建视频文件读取者 102 | AVAssetReader *reader = [AVAssetReader assetReaderWithAsset:asset error:nil]; 103 | AVAssetReaderTrackOutput *videoOutput = nil; 104 | if (videoTrack) { 105 | //从指定文件读取视频 106 | videoOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:[self configVideoOutput]]; 107 | //将读取到的视频信息添加到读者队列中 108 | if ([reader canAddOutput:videoOutput]) { 109 | [reader addOutput:videoOutput]; 110 | } 111 | } 112 | 113 | //取出原视频中音频详细资料 114 | AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject; 115 | AVAssetReaderTrackOutput *audioOutput = nil; 116 | if (audioTrack) { 117 | //从音频资料中读取音频 118 | audioOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:[self configAudioOutput]]; 119 | //将读取到的音频信息添加到读者队列中 120 | if ([reader canAddOutput:audioOutput]) { 121 | [reader addOutput:audioOutput]; 122 | } 123 | } 124 | 125 | //视频文件写入者 126 | AVAssetWriter *writer = [AVAssetWriter assetWriterWithURL:outPutPathURL fileType:AVFileTypeMPEG4 error:nil]; 127 | //根据指定配置创建写入的视频文件 128 | AVAssetWriterInput *videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:[self videoCompressSettingsWithBitRate:compressBiteRate withFrameRate:compressFrameRate withWidth:compressWidth WithHeight:compressHeight withOriginalWidth:videoWidth withOriginalHeight:videoHeight]]; 129 | // 视频方向 130 | videoInput.transform = videoTrack.preferredTransform; 131 | 132 | //根据指定配置创建写入的音频文件 133 | AVAssetWriterInput *audioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:[self audioCompressSettings]]; 134 | if ([writer canAddInput:videoInput]) { 135 | [writer addInput:videoInput]; 136 | } 137 | if ([writer canAddInput:audioInput]) { 138 | [writer addInput:audioInput]; 139 | } 140 | 141 | [reader startReading]; 142 | [writer startWriting]; 143 | [writer startSessionAtSourceTime:kCMTimeZero]; 144 | //创建视频写入队列 145 | dispatch_queue_t videoQueue = dispatch_queue_create("Video Queue", DISPATCH_QUEUE_SERIAL); 146 | //创建音频写入队列 147 | dispatch_queue_t audioQueue = dispatch_queue_create("Audio Queue", DISPATCH_QUEUE_SERIAL); 148 | //创建一个线程组 149 | dispatch_group_t group = dispatch_group_create(); 150 | //进入线程组 151 | dispatch_group_enter(group); 152 | 153 | long long allTimeStamp = asset.duration.value; 154 | //队列准备好后 usingBlock 155 | [videoInput requestMediaDataWhenReadyOnQueue:videoQueue usingBlock:^{ 156 | BOOL completedOrFailed = NO; 157 | while ([videoInput isReadyForMoreMediaData] && !completedOrFailed) { 158 | @autoreleasepool { 159 | CMSampleBufferRef sampleBuffer = [videoOutput copyNextSampleBuffer]; 160 | if (sampleBuffer != NULL) { 161 | [videoInput appendSampleBuffer:sampleBuffer]; 162 | 163 | // 获取进度 164 | CMTime timeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 165 | CGFloat progress = (CGFloat)timeStamp.value/(CGFloat)allTimeStamp; 166 | if (progressBlock) { 167 | progressBlock(progress); 168 | } 169 | 170 | CFRelease(sampleBuffer); 171 | } else { 172 | completedOrFailed = YES; 173 | [videoInput markAsFinished]; 174 | dispatch_group_leave(group); 175 | } 176 | } 177 | } 178 | }]; 179 | dispatch_group_enter(group); 180 | //队列准备好后 usingBlock 181 | [audioInput requestMediaDataWhenReadyOnQueue:audioQueue usingBlock:^{ 182 | BOOL completedOrFailed = NO; 183 | while ([audioInput isReadyForMoreMediaData] && !completedOrFailed) { 184 | @autoreleasepool { 185 | CMSampleBufferRef sampleBuffer = [audioOutput copyNextSampleBuffer]; 186 | if (sampleBuffer != NULL) { 187 | BOOL success = [audioInput appendSampleBuffer:sampleBuffer]; 188 | CFRelease(sampleBuffer); 189 | completedOrFailed = !success; 190 | } else { 191 | completedOrFailed = YES; 192 | } 193 | } 194 | } 195 | if (completedOrFailed) { 196 | [audioInput markAsFinished]; 197 | dispatch_group_leave(group); 198 | } 199 | }]; 200 | //完成压缩 201 | dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 202 | if ([reader status] == AVAssetReaderStatusReading) { 203 | [reader cancelReading]; 204 | } 205 | 206 | switch (writer.status) { 207 | case AVAssetWriterStatusWriting: 208 | { 209 | if (progressBlock) { 210 | progressBlock(1); 211 | } 212 | unsigned long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:outPutPathURL.path error:nil].fileSize; 213 | float fileSizeMB = fileSize / (1024.0*1024.0); 214 | NSLog(@"视频压缩成功 大小 : %f %@",fileSizeMB,outPutPathURL); 215 | 216 | [writer finishWritingWithCompletionHandler:^{ 217 | if (compressComplete) { 218 | compressComplete(YES, outPutPathURL); 219 | } 220 | }]; 221 | } 222 | break; 223 | case AVAssetWriterStatusCancelled: 224 | break; 225 | case AVAssetWriterStatusFailed: 226 | NSLog(@"压缩失败 : %@", writer.error); 227 | break; 228 | case AVAssetWriterStatusCompleted: 229 | { 230 | if (progressBlock) { 231 | progressBlock(1); 232 | } 233 | 234 | unsigned long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:outPutPathURL.path error:nil].fileSize; 235 | float fileSizeMB = fileSize / (1024.0*1024.0); 236 | NSLog(@"视频压缩成功 大小 : %f %@",fileSizeMB,outPutPathURL); 237 | 238 | [writer finishWritingWithCompletionHandler:^{ 239 | if (compressComplete) { 240 | compressComplete(YES, outPutPathURL); 241 | } 242 | }]; 243 | } 244 | break; 245 | default: 246 | break; 247 | } 248 | }); 249 | } 250 | 251 | + (void)compressVideoWithVideoUrl:(NSURL *)videoUrl 252 | outputURL:(NSURL *)outputURL 253 | progressBlock:(FSJCompressionProgressBlock)progressBlock 254 | compressComplete:(FSJCompressionCompleteBlock)compressComplete { 255 | [self compressVideoWithVideoUrl:videoUrl outputURL:outputURL withBiteRate:nil withFrameRate:nil withVideoWidth:nil withVideoHeight:nil progressBlock:progressBlock compressComplete:compressComplete]; 256 | } 257 | 258 | + (NSDictionary *)videoCompressSettingsWithBitRate:(NSInteger)biteRate withFrameRate:(NSInteger)frameRate withWidth:(NSInteger)width WithHeight:(NSInteger)height withOriginalWidth:(NSInteger)originalWidth withOriginalHeight:(NSInteger)originalHeight{ 259 | /* 260 | * AVVideoAverageBitRateKey: 比特率(码率)每秒传输的文件大小 kbps 261 | * AVVideoExpectedSourceFrameRateKey:帧率 每秒播放的帧数 262 | * AVVideoProfileLevelKey:画质水平 263 | BP-Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC; 264 | EP-Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC; 265 | MP-Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),也支持CAVLC 和CABAC 的支持; 266 | HP-High profile:高级画质。在main Profile 的基础上增加了8×8内部预测、自定义量化、 无损视频编码和更多的YUV 格式; 267 | **/ 268 | NSInteger returnWidth = originalWidth > originalHeight ? width : height; 269 | NSInteger returnHeight = originalWidth > originalHeight ? height : width; 270 | 271 | NSDictionary *compressProperties = @{ 272 | AVVideoAverageBitRateKey : @(biteRate), 273 | AVVideoExpectedSourceFrameRateKey : @(frameRate), 274 | AVVideoProfileLevelKey : AVVideoProfileLevelH264HighAutoLevel 275 | }; 276 | if (@available(iOS 11.0, *)) { 277 | NSDictionary *compressSetting = @{ 278 | AVVideoCodecKey : AVVideoCodecTypeH264, 279 | AVVideoWidthKey : @(returnWidth), 280 | AVVideoHeightKey : @(returnHeight), 281 | AVVideoCompressionPropertiesKey : compressProperties, 282 | AVVideoScalingModeKey : AVVideoScalingModeResizeAspectFill 283 | }; 284 | return compressSetting; 285 | }else { 286 | NSDictionary *compressSetting = @{ 287 | AVVideoCodecKey : AVVideoCodecH264, 288 | AVVideoWidthKey : @(returnWidth), 289 | AVVideoHeightKey : @(returnHeight), 290 | AVVideoCompressionPropertiesKey : compressProperties, 291 | AVVideoScalingModeKey : AVVideoScalingModeResizeAspectFill 292 | }; 293 | return compressSetting; 294 | } 295 | } 296 | //音频设置 297 | + (NSDictionary *)audioCompressSettings{ 298 | AudioChannelLayout stereoChannelLayout = { 299 | .mChannelLayoutTag = kAudioChannelLayoutTag_Stereo, 300 | .mChannelBitmap = kAudioChannelBit_Left, 301 | .mNumberChannelDescriptions = 0, 302 | }; 303 | NSData *channelLayoutAsData = [NSData dataWithBytes:&stereoChannelLayout length:offsetof(AudioChannelLayout, mChannelDescriptions)]; 304 | NSDictionary *audioCompressSettings = @{ 305 | AVFormatIDKey : @(kAudioFormatMPEG4AAC), 306 | AVEncoderBitRateKey : @(128000), 307 | AVSampleRateKey : @(44100), 308 | AVNumberOfChannelsKey : @(2), 309 | AVChannelLayoutKey : channelLayoutAsData 310 | }; 311 | return audioCompressSettings; 312 | } 313 | /** 音频解码 */ 314 | + (NSDictionary *)configAudioOutput 315 | { 316 | NSDictionary *audioOutputSetting = @{ 317 | AVFormatIDKey: @(kAudioFormatLinearPCM) 318 | }; 319 | return audioOutputSetting; 320 | } 321 | /** 视频解码 */ 322 | + (NSDictionary *)configVideoOutput 323 | { 324 | NSDictionary *videoOutputSetting = @{ 325 | (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_422YpCbCr8], 326 | (__bridge NSString *)kCVPixelBufferIOSurfacePropertiesKey:[NSDictionary dictionary] 327 | }; 328 | 329 | return videoOutputSetting; 330 | } 331 | 332 | #pragma mark - 生成视频 333 | + (void)compressVideoWithVideoAsset:(AVURLAsset *)asset 334 | outputURL:(NSURL *)outputURL 335 | withBiteRate:(NSNumber * _Nullable)outputBiteRate 336 | withFrameRate:(NSNumber * _Nullable)outputFrameRate 337 | withVideoWidth:(NSNumber * _Nullable)outputWidth 338 | withVideoHeight:(NSNumber * _Nullable)outputHeight 339 | transform:(CGAffineTransform)transform 340 | progressBlock:(FSJCompressionProgressBlock)progressBlock 341 | compressComplete:(FSJCompressionCompleteBlock)compressComplete { 342 | if (!asset) { 343 | if (compressComplete) { 344 | compressComplete(NO, nil); 345 | } 346 | return; 347 | } 348 | NSInteger compressBiteRate = outputBiteRate ? [outputBiteRate integerValue] : 1500 * 1024; 349 | NSInteger compressFrameRate = outputFrameRate ? [outputFrameRate integerValue] : 30; 350 | NSInteger compressWidth = outputWidth ? [outputWidth integerValue] : 960; 351 | NSInteger compressHeight = outputHeight ? [outputHeight integerValue] : 540; 352 | //视频时长 S 353 | CMTime time = [asset duration]; 354 | NSInteger seconds = ceil(time.value/time.timescale); 355 | if (seconds < 3) { 356 | if (compressComplete) { 357 | compressComplete(NO, nil); 358 | } 359 | return; 360 | } 361 | //取出asset中的视频文件 362 | AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject; 363 | //压缩前原视频宽高 364 | NSInteger videoWidth = videoTrack.naturalSize.width; 365 | NSInteger videoHeight = videoTrack.naturalSize.height; 366 | 367 | //压缩前原视频比特率 368 | NSInteger kbps = videoTrack.estimatedDataRate / 1024; 369 | //原视频比特率小于指定比特率 不压缩 返回原视频 370 | if (kbps <= (compressBiteRate / 1024)) { 371 | NSLog(@"原视频的比特率小于压缩的比特率,所以不压缩"); 372 | if (compressComplete) { 373 | compressComplete(NO, nil); 374 | } 375 | return; 376 | } 377 | //指定压缩视频沙盒根目录 378 | NSURL *outPutPathURL = outputURL; 379 | if (outPutPathURL == nil) { 380 | NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; 381 | //添加文件完整路径 382 | NSString *outputUrlStr = [[cachesDir stringByAppendingPathComponent:@"videoTest"] stringByAppendingPathExtension:@"mp4"]; 383 | outPutPathURL = [NSURL fileURLWithPath:outputUrlStr]; 384 | } 385 | 386 | //如果指定路径下已存在其他文件 先移除指定文件 387 | if ([[NSFileManager defaultManager] fileExistsAtPath:outPutPathURL.path]) { 388 | BOOL removeSuccess = [[NSFileManager defaultManager] removeItemAtPath:outPutPathURL.path error:nil]; 389 | if (!removeSuccess) { 390 | if (compressComplete) { 391 | compressComplete(NO, nil); 392 | } 393 | return; 394 | } 395 | } 396 | //创建视频文件读取者 397 | AVAssetReader *reader = [AVAssetReader assetReaderWithAsset:asset error:nil]; 398 | AVAssetReaderTrackOutput *videoOutput = nil; 399 | if (videoTrack) { 400 | //从指定文件读取视频 401 | videoOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:[self configVideoOutput]]; 402 | //将读取到的视频信息添加到读者队列中 403 | if ([reader canAddOutput:videoOutput]) { 404 | [reader addOutput:videoOutput]; 405 | } 406 | } 407 | 408 | //取出原视频中音频详细资料 409 | AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject; 410 | AVAssetReaderTrackOutput *audioOutput = nil; 411 | if (audioTrack) { 412 | //从音频资料中读取音频 413 | audioOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:[self configAudioOutput]]; 414 | //将读取到的音频信息添加到读者队列中 415 | if ([reader canAddOutput:audioOutput]) { 416 | [reader addOutput:audioOutput]; 417 | } 418 | } 419 | 420 | //视频文件写入者 421 | AVAssetWriter *writer = [AVAssetWriter assetWriterWithURL:outPutPathURL fileType:AVFileTypeMPEG4 error:nil]; 422 | //根据指定配置创建写入的视频文件 423 | AVAssetWriterInput *videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:[self videoCompressSettingsWithBitRate:compressBiteRate withFrameRate:compressFrameRate withWidth:compressWidth WithHeight:compressHeight withOriginalWidth:videoWidth withOriginalHeight:videoHeight]]; 424 | // 视频方向 425 | videoInput.transform = transform;//videoTrack.preferredTransform; 426 | 427 | //根据指定配置创建写入的音频文件 428 | AVAssetWriterInput *audioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:[self audioCompressSettings]]; 429 | if ([writer canAddInput:videoInput]) { 430 | [writer addInput:videoInput]; 431 | } 432 | if ([writer canAddInput:audioInput]) { 433 | [writer addInput:audioInput]; 434 | } 435 | 436 | [reader startReading]; 437 | [writer startWriting]; 438 | [writer startSessionAtSourceTime:kCMTimeZero]; 439 | //创建视频写入队列 440 | dispatch_queue_t videoQueue = dispatch_queue_create("Video Queue", DISPATCH_QUEUE_SERIAL); 441 | //创建音频写入队列 442 | dispatch_queue_t audioQueue = dispatch_queue_create("Audio Queue", DISPATCH_QUEUE_SERIAL); 443 | //创建一个线程组 444 | dispatch_group_t group = dispatch_group_create(); 445 | //进入线程组 446 | dispatch_group_enter(group); 447 | 448 | NSLog(@"开始压缩视频"); 449 | CGFloat allSecond = (CGFloat)asset.duration.value / (CGFloat)asset.duration.timescale; 450 | //队列准备好后 usingBlock 451 | [videoInput requestMediaDataWhenReadyOnQueue:videoQueue usingBlock:^{ 452 | BOOL completedOrFailed = NO; 453 | while ([videoInput isReadyForMoreMediaData] && !completedOrFailed) { 454 | @autoreleasepool { 455 | CMSampleBufferRef sampleBuffer = [videoOutput copyNextSampleBuffer]; 456 | if (sampleBuffer != NULL) { 457 | [videoInput appendSampleBuffer:sampleBuffer]; 458 | 459 | // 获取进度 460 | CMTime timeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 461 | CGFloat second = (CGFloat)timeStamp.value / (CGFloat)timeStamp.timescale; 462 | CGFloat progress = (CGFloat)second/(CGFloat)allSecond; 463 | if (progressBlock) { 464 | progressBlock(progress); 465 | } 466 | 467 | CFRelease(sampleBuffer); 468 | } else { 469 | completedOrFailed = YES; 470 | [videoInput markAsFinished]; 471 | dispatch_group_leave(group); 472 | } 473 | } 474 | } 475 | }]; 476 | dispatch_group_enter(group); 477 | //队列准备好后 usingBlock 478 | [audioInput requestMediaDataWhenReadyOnQueue:audioQueue usingBlock:^{ 479 | BOOL completedOrFailed = NO; 480 | while ([audioInput isReadyForMoreMediaData] && !completedOrFailed) { 481 | @autoreleasepool { 482 | CMSampleBufferRef sampleBuffer = [audioOutput copyNextSampleBuffer]; 483 | if (sampleBuffer != NULL) { 484 | BOOL success = [audioInput appendSampleBuffer:sampleBuffer]; 485 | CFRelease(sampleBuffer); 486 | completedOrFailed = !success; 487 | } else { 488 | completedOrFailed = YES; 489 | } 490 | } 491 | } 492 | if (completedOrFailed) { 493 | [audioInput markAsFinished]; 494 | dispatch_group_leave(group); 495 | } 496 | }]; 497 | //完成压缩 498 | dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 499 | if ([reader status] == AVAssetReaderStatusReading) { 500 | [reader cancelReading]; 501 | } 502 | 503 | switch (writer.status) { 504 | case AVAssetWriterStatusWriting: 505 | { 506 | if (progressBlock) { 507 | progressBlock(1); 508 | } 509 | unsigned long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:outPutPathURL.path error:nil].fileSize; 510 | float fileSizeMB = fileSize / (1024.0*1024.0); 511 | NSLog(@"视频压缩成功 大小 : %f %@",fileSizeMB,outPutPathURL); 512 | 513 | [writer finishWritingWithCompletionHandler:^{ 514 | if (compressComplete) { 515 | compressComplete(YES, outPutPathURL); 516 | } 517 | }]; 518 | } 519 | break; 520 | case AVAssetWriterStatusCancelled: 521 | break; 522 | case AVAssetWriterStatusFailed: 523 | NSLog(@"压缩失败 : %@", writer.error); 524 | break; 525 | case AVAssetWriterStatusCompleted: 526 | { 527 | if (progressBlock) { 528 | progressBlock(1); 529 | } 530 | 531 | unsigned long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:outPutPathURL.path error:nil].fileSize; 532 | float fileSizeMB = fileSize / (1024.0*1024.0); 533 | NSLog(@"视频压缩成功 大小 : %f %@",fileSizeMB,outPutPathURL); 534 | 535 | [writer finishWritingWithCompletionHandler:^{ 536 | if (compressComplete) { 537 | compressComplete(YES, outPutPathURL); 538 | } 539 | }]; 540 | } 541 | break; 542 | default: 543 | break; 544 | } 545 | }); 546 | } 547 | 548 | + (void)compressVideoWithVideoAsset:(AVURLAsset *)asset 549 | outputURL:(NSURL *)outputURL 550 | transform:(CGAffineTransform)transform 551 | progressBlock:(FSJCompressionProgressBlock)progressBlock 552 | compressComplete:(FSJCompressionCompleteBlock)compressComplete { 553 | [self compressVideoWithVideoAsset:asset outputURL:outputURL withBiteRate:nil withFrameRate:nil withVideoWidth:nil withVideoHeight:nil transform:transform progressBlock:progressBlock compressComplete:compressComplete]; 554 | } 555 | 556 | @end 557 | -------------------------------------------------------------------------------- /FSJCompression.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 08C309F4FCDF5CC9A89D717B /* Pods_FSJCompression_FSJCompressionUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BABA5E6E97C4C2F80135828B /* Pods_FSJCompression_FSJCompressionUITests.framework */; }; 11 | 2D5F217E2D9A2610BF6687CE /* Pods_FSJCompression.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D39EE4987B42A3FABF3375 /* Pods_FSJCompression.framework */; }; 12 | 80322DF8F225E3BE83A65823 /* Pods_FSJCompressionTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C99E546BFCC0E837B79E506 /* Pods_FSJCompressionTests.framework */; }; 13 | E937791224EA26FA00107537 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E937791124EA26FA00107537 /* AppDelegate.m */; }; 14 | E937791824EA26FA00107537 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E937791724EA26FA00107537 /* ViewController.m */; }; 15 | E937791B24EA26FA00107537 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E937791924EA26FA00107537 /* Main.storyboard */; }; 16 | E937791E24EA26FA00107537 /* FSJCompression.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = E937791C24EA26FA00107537 /* FSJCompression.xcdatamodeld */; }; 17 | E937792024EA26FD00107537 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E937791F24EA26FD00107537 /* Assets.xcassets */; }; 18 | E937792324EA26FD00107537 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E937792124EA26FD00107537 /* LaunchScreen.storyboard */; }; 19 | E937792624EA26FD00107537 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E937792524EA26FD00107537 /* main.m */; }; 20 | E937793024EA26FD00107537 /* FSJCompressionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E937792F24EA26FD00107537 /* FSJCompressionTests.m */; }; 21 | E937793B24EA26FD00107537 /* FSJCompressionUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E937793A24EA26FD00107537 /* FSJCompressionUITests.m */; }; 22 | E937794C24EA282700107537 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = E937794924EA282600107537 /* LICENSE */; }; 23 | E937794D24EA282700107537 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = E937794A24EA282600107537 /* README.md */; }; 24 | E937795224EA284400107537 /* FSJCompressionVideoTool.m in Sources */ = {isa = PBXBuildFile; fileRef = E937795124EA284400107537 /* FSJCompressionVideoTool.m */; }; 25 | E937795724EA294600107537 /* FSJMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E937795624EA294600107537 /* FSJMainViewController.m */; }; 26 | E937795D24EA2AEE00107537 /* FSVideoImageTool.m in Sources */ = {isa = PBXBuildFile; fileRef = E937795C24EA2AEE00107537 /* FSVideoImageTool.m */; }; 27 | E937796024EA2B3200107537 /* FSPathTool.m in Sources */ = {isa = PBXBuildFile; fileRef = E937795F24EA2B3200107537 /* FSPathTool.m */; }; 28 | E937796224EA2D0500107537 /* FSJCompression.podspec in Resources */ = {isa = PBXBuildFile; fileRef = E937796124EA2D0500107537 /* FSJCompression.podspec */; }; 29 | E9772A2125020F570043339C /* FSJCompressionImageTool.m in Sources */ = {isa = PBXBuildFile; fileRef = E9772A2025020F570043339C /* FSJCompressionImageTool.m */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | E937792C24EA26FD00107537 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = E937790524EA26FA00107537 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = E937790C24EA26FA00107537; 38 | remoteInfo = FSJCompression; 39 | }; 40 | E937793724EA26FD00107537 /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = E937790524EA26FA00107537 /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = E937790C24EA26FA00107537; 45 | remoteInfo = FSJCompression; 46 | }; 47 | /* End PBXContainerItemProxy section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | 01A49A738AD35FAB6C55A804 /* Pods-FSJCompressionTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FSJCompressionTests.release.xcconfig"; path = "Target Support Files/Pods-FSJCompressionTests/Pods-FSJCompressionTests.release.xcconfig"; sourceTree = ""; }; 51 | 09D39EE4987B42A3FABF3375 /* Pods_FSJCompression.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FSJCompression.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 1C99E546BFCC0E837B79E506 /* Pods_FSJCompressionTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FSJCompressionTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 2385A1B4E1233FF137EE0BB6 /* Pods-FSJCompression-FSJCompressionUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FSJCompression-FSJCompressionUITests.release.xcconfig"; path = "Target Support Files/Pods-FSJCompression-FSJCompressionUITests/Pods-FSJCompression-FSJCompressionUITests.release.xcconfig"; sourceTree = ""; }; 54 | 60D55E6B3FC07D221C1BC910 /* Pods-FSJCompression.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FSJCompression.release.xcconfig"; path = "Target Support Files/Pods-FSJCompression/Pods-FSJCompression.release.xcconfig"; sourceTree = ""; }; 55 | 6C81677887A7847AF7D0426A /* Pods-FSJCompression-FSJCompressionUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FSJCompression-FSJCompressionUITests.debug.xcconfig"; path = "Target Support Files/Pods-FSJCompression-FSJCompressionUITests/Pods-FSJCompression-FSJCompressionUITests.debug.xcconfig"; sourceTree = ""; }; 56 | A9692FDFD13812EB9BE44FF0 /* Pods-FSJCompression.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FSJCompression.debug.xcconfig"; path = "Target Support Files/Pods-FSJCompression/Pods-FSJCompression.debug.xcconfig"; sourceTree = ""; }; 57 | BABA5E6E97C4C2F80135828B /* Pods_FSJCompression_FSJCompressionUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FSJCompression_FSJCompressionUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | BEEA25E88C9FD29800FC4830 /* Pods-FSJCompressionTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FSJCompressionTests.debug.xcconfig"; path = "Target Support Files/Pods-FSJCompressionTests/Pods-FSJCompressionTests.debug.xcconfig"; sourceTree = ""; }; 59 | E937790D24EA26FA00107537 /* FSJCompression.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FSJCompression.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | E937791024EA26FA00107537 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 61 | E937791124EA26FA00107537 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 62 | E937791624EA26FA00107537 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 63 | E937791724EA26FA00107537 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 64 | E937791A24EA26FA00107537 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 65 | E937791D24EA26FA00107537 /* FSJCompression.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = FSJCompression.xcdatamodel; sourceTree = ""; }; 66 | E937791F24EA26FD00107537 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 67 | E937792224EA26FD00107537 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 68 | E937792424EA26FD00107537 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69 | E937792524EA26FD00107537 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 70 | E937792B24EA26FD00107537 /* FSJCompressionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FSJCompressionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | E937792F24EA26FD00107537 /* FSJCompressionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSJCompressionTests.m; sourceTree = ""; }; 72 | E937793124EA26FD00107537 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 73 | E937793624EA26FD00107537 /* FSJCompressionUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FSJCompressionUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 74 | E937793A24EA26FD00107537 /* FSJCompressionUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSJCompressionUITests.m; sourceTree = ""; }; 75 | E937793C24EA26FD00107537 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 76 | E937794924EA282600107537 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; 77 | E937794A24EA282600107537 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 78 | E937795024EA284400107537 /* FSJCompressionVideoTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSJCompressionVideoTool.h; sourceTree = ""; }; 79 | E937795124EA284400107537 /* FSJCompressionVideoTool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSJCompressionVideoTool.m; sourceTree = ""; }; 80 | E937795324EA286F00107537 /* FSJCompressionBlockHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSJCompressionBlockHeader.h; sourceTree = ""; }; 81 | E937795524EA294600107537 /* FSJMainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSJMainViewController.h; sourceTree = ""; }; 82 | E937795624EA294600107537 /* FSJMainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSJMainViewController.m; sourceTree = ""; }; 83 | E937795824EA299B00107537 /* PrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; 84 | E937795924EA2A6F00107537 /* FSJCompression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSJCompression.h; sourceTree = ""; }; 85 | E937795B24EA2AEE00107537 /* FSVideoImageTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSVideoImageTool.h; sourceTree = ""; }; 86 | E937795C24EA2AEE00107537 /* FSVideoImageTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSVideoImageTool.m; sourceTree = ""; }; 87 | E937795E24EA2B3200107537 /* FSPathTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSPathTool.h; sourceTree = ""; }; 88 | E937795F24EA2B3200107537 /* FSPathTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSPathTool.m; sourceTree = ""; }; 89 | E937796124EA2D0500107537 /* FSJCompression.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = FSJCompression.podspec; sourceTree = SOURCE_ROOT; }; 90 | E9772A1F25020F570043339C /* FSJCompressionImageTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSJCompressionImageTool.h; sourceTree = ""; }; 91 | E9772A2025020F570043339C /* FSJCompressionImageTool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSJCompressionImageTool.m; sourceTree = ""; }; 92 | /* End PBXFileReference section */ 93 | 94 | /* Begin PBXFrameworksBuildPhase section */ 95 | E937790A24EA26FA00107537 /* Frameworks */ = { 96 | isa = PBXFrameworksBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | 2D5F217E2D9A2610BF6687CE /* Pods_FSJCompression.framework in Frameworks */, 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | E937792824EA26FD00107537 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | 80322DF8F225E3BE83A65823 /* Pods_FSJCompressionTests.framework in Frameworks */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | E937793324EA26FD00107537 /* Frameworks */ = { 112 | isa = PBXFrameworksBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 08C309F4FCDF5CC9A89D717B /* Pods_FSJCompression_FSJCompressionUITests.framework in Frameworks */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXFrameworksBuildPhase section */ 120 | 121 | /* Begin PBXGroup section */ 122 | 1EDFB3124F012451EEE6FE99 /* Frameworks */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 09D39EE4987B42A3FABF3375 /* Pods_FSJCompression.framework */, 126 | BABA5E6E97C4C2F80135828B /* Pods_FSJCompression_FSJCompressionUITests.framework */, 127 | 1C99E546BFCC0E837B79E506 /* Pods_FSJCompressionTests.framework */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | B14B064C74B790268995DB69 /* Pods */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | A9692FDFD13812EB9BE44FF0 /* Pods-FSJCompression.debug.xcconfig */, 136 | 60D55E6B3FC07D221C1BC910 /* Pods-FSJCompression.release.xcconfig */, 137 | 6C81677887A7847AF7D0426A /* Pods-FSJCompression-FSJCompressionUITests.debug.xcconfig */, 138 | 2385A1B4E1233FF137EE0BB6 /* Pods-FSJCompression-FSJCompressionUITests.release.xcconfig */, 139 | BEEA25E88C9FD29800FC4830 /* Pods-FSJCompressionTests.debug.xcconfig */, 140 | 01A49A738AD35FAB6C55A804 /* Pods-FSJCompressionTests.release.xcconfig */, 141 | ); 142 | path = Pods; 143 | sourceTree = ""; 144 | }; 145 | E937790424EA26FA00107537 = { 146 | isa = PBXGroup; 147 | children = ( 148 | E937790F24EA26FA00107537 /* FSJCompression */, 149 | E937792E24EA26FD00107537 /* FSJCompressionTests */, 150 | E937793924EA26FD00107537 /* FSJCompressionUITests */, 151 | E937790E24EA26FA00107537 /* Products */, 152 | B14B064C74B790268995DB69 /* Pods */, 153 | 1EDFB3124F012451EEE6FE99 /* Frameworks */, 154 | ); 155 | sourceTree = ""; 156 | }; 157 | E937790E24EA26FA00107537 /* Products */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | E937790D24EA26FA00107537 /* FSJCompression.app */, 161 | E937792B24EA26FD00107537 /* FSJCompressionTests.xctest */, 162 | E937793624EA26FD00107537 /* FSJCompressionUITests.xctest */, 163 | ); 164 | name = Products; 165 | sourceTree = ""; 166 | }; 167 | E937790F24EA26FA00107537 /* FSJCompression */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | E937795424EA293500107537 /* Controllers */, 171 | E937794F24EA283200107537 /* Libs */, 172 | E937794824EA281000107537 /* PodspecMetadata */, 173 | E937791024EA26FA00107537 /* AppDelegate.h */, 174 | E937791124EA26FA00107537 /* AppDelegate.m */, 175 | E937791624EA26FA00107537 /* ViewController.h */, 176 | E937791724EA26FA00107537 /* ViewController.m */, 177 | E937791924EA26FA00107537 /* Main.storyboard */, 178 | E937791F24EA26FD00107537 /* Assets.xcassets */, 179 | E937792124EA26FD00107537 /* LaunchScreen.storyboard */, 180 | E937792424EA26FD00107537 /* Info.plist */, 181 | E937792524EA26FD00107537 /* main.m */, 182 | E937791C24EA26FA00107537 /* FSJCompression.xcdatamodeld */, 183 | E937795824EA299B00107537 /* PrefixHeader.pch */, 184 | ); 185 | path = FSJCompression; 186 | sourceTree = ""; 187 | }; 188 | E937792E24EA26FD00107537 /* FSJCompressionTests */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | E937792F24EA26FD00107537 /* FSJCompressionTests.m */, 192 | E937793124EA26FD00107537 /* Info.plist */, 193 | ); 194 | path = FSJCompressionTests; 195 | sourceTree = ""; 196 | }; 197 | E937793924EA26FD00107537 /* FSJCompressionUITests */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | E937793A24EA26FD00107537 /* FSJCompressionUITests.m */, 201 | E937793C24EA26FD00107537 /* Info.plist */, 202 | ); 203 | path = FSJCompressionUITests; 204 | sourceTree = ""; 205 | }; 206 | E937794824EA281000107537 /* PodspecMetadata */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | E937796124EA2D0500107537 /* FSJCompression.podspec */, 210 | E937794924EA282600107537 /* LICENSE */, 211 | E937794A24EA282600107537 /* README.md */, 212 | ); 213 | path = PodspecMetadata; 214 | sourceTree = SOURCE_ROOT; 215 | }; 216 | E937794F24EA283200107537 /* Libs */ = { 217 | isa = PBXGroup; 218 | children = ( 219 | E937795024EA284400107537 /* FSJCompressionVideoTool.h */, 220 | E937795124EA284400107537 /* FSJCompressionVideoTool.m */, 221 | E937795324EA286F00107537 /* FSJCompressionBlockHeader.h */, 222 | E937795924EA2A6F00107537 /* FSJCompression.h */, 223 | E9772A1F25020F570043339C /* FSJCompressionImageTool.h */, 224 | E9772A2025020F570043339C /* FSJCompressionImageTool.m */, 225 | ); 226 | path = Libs; 227 | sourceTree = SOURCE_ROOT; 228 | }; 229 | E937795424EA293500107537 /* Controllers */ = { 230 | isa = PBXGroup; 231 | children = ( 232 | E937795A24EA2AEE00107537 /* Tools */, 233 | E937795524EA294600107537 /* FSJMainViewController.h */, 234 | E937795624EA294600107537 /* FSJMainViewController.m */, 235 | ); 236 | path = Controllers; 237 | sourceTree = ""; 238 | }; 239 | E937795A24EA2AEE00107537 /* Tools */ = { 240 | isa = PBXGroup; 241 | children = ( 242 | E937795E24EA2B3200107537 /* FSPathTool.h */, 243 | E937795F24EA2B3200107537 /* FSPathTool.m */, 244 | E937795B24EA2AEE00107537 /* FSVideoImageTool.h */, 245 | E937795C24EA2AEE00107537 /* FSVideoImageTool.m */, 246 | ); 247 | path = Tools; 248 | sourceTree = ""; 249 | }; 250 | /* End PBXGroup section */ 251 | 252 | /* Begin PBXNativeTarget section */ 253 | E937790C24EA26FA00107537 /* FSJCompression */ = { 254 | isa = PBXNativeTarget; 255 | buildConfigurationList = E937793F24EA26FD00107537 /* Build configuration list for PBXNativeTarget "FSJCompression" */; 256 | buildPhases = ( 257 | F98A3AEF840D1438E8A49BA7 /* [CP] Check Pods Manifest.lock */, 258 | E937790924EA26FA00107537 /* Sources */, 259 | E937790A24EA26FA00107537 /* Frameworks */, 260 | E937790B24EA26FA00107537 /* Resources */, 261 | B3133AF1599357F5B2D92D73 /* [CP] Embed Pods Frameworks */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | ); 267 | name = FSJCompression; 268 | productName = FSJCompression; 269 | productReference = E937790D24EA26FA00107537 /* FSJCompression.app */; 270 | productType = "com.apple.product-type.application"; 271 | }; 272 | E937792A24EA26FD00107537 /* FSJCompressionTests */ = { 273 | isa = PBXNativeTarget; 274 | buildConfigurationList = E937794224EA26FD00107537 /* Build configuration list for PBXNativeTarget "FSJCompressionTests" */; 275 | buildPhases = ( 276 | D45CD43D38AAA6B334F13655 /* [CP] Check Pods Manifest.lock */, 277 | E937792724EA26FD00107537 /* Sources */, 278 | E937792824EA26FD00107537 /* Frameworks */, 279 | E937792924EA26FD00107537 /* Resources */, 280 | ); 281 | buildRules = ( 282 | ); 283 | dependencies = ( 284 | E937792D24EA26FD00107537 /* PBXTargetDependency */, 285 | ); 286 | name = FSJCompressionTests; 287 | productName = FSJCompressionTests; 288 | productReference = E937792B24EA26FD00107537 /* FSJCompressionTests.xctest */; 289 | productType = "com.apple.product-type.bundle.unit-test"; 290 | }; 291 | E937793524EA26FD00107537 /* FSJCompressionUITests */ = { 292 | isa = PBXNativeTarget; 293 | buildConfigurationList = E937794524EA26FD00107537 /* Build configuration list for PBXNativeTarget "FSJCompressionUITests" */; 294 | buildPhases = ( 295 | 95B7BAEAC1D3196AF5C5C1F0 /* [CP] Check Pods Manifest.lock */, 296 | E937793224EA26FD00107537 /* Sources */, 297 | E937793324EA26FD00107537 /* Frameworks */, 298 | E937793424EA26FD00107537 /* Resources */, 299 | 3A4200822D3A863F08C8C084 /* [CP] Embed Pods Frameworks */, 300 | ); 301 | buildRules = ( 302 | ); 303 | dependencies = ( 304 | E937793824EA26FD00107537 /* PBXTargetDependency */, 305 | ); 306 | name = FSJCompressionUITests; 307 | productName = FSJCompressionUITests; 308 | productReference = E937793624EA26FD00107537 /* FSJCompressionUITests.xctest */; 309 | productType = "com.apple.product-type.bundle.ui-testing"; 310 | }; 311 | /* End PBXNativeTarget section */ 312 | 313 | /* Begin PBXProject section */ 314 | E937790524EA26FA00107537 /* Project object */ = { 315 | isa = PBXProject; 316 | attributes = { 317 | LastUpgradeCheck = 1160; 318 | ORGANIZATIONNAME = "燕来秋"; 319 | TargetAttributes = { 320 | E937790C24EA26FA00107537 = { 321 | CreatedOnToolsVersion = 11.6; 322 | }; 323 | E937792A24EA26FD00107537 = { 324 | CreatedOnToolsVersion = 11.6; 325 | TestTargetID = E937790C24EA26FA00107537; 326 | }; 327 | E937793524EA26FD00107537 = { 328 | CreatedOnToolsVersion = 11.6; 329 | TestTargetID = E937790C24EA26FA00107537; 330 | }; 331 | }; 332 | }; 333 | buildConfigurationList = E937790824EA26FA00107537 /* Build configuration list for PBXProject "FSJCompression" */; 334 | compatibilityVersion = "Xcode 9.3"; 335 | developmentRegion = en; 336 | hasScannedForEncodings = 0; 337 | knownRegions = ( 338 | en, 339 | Base, 340 | ); 341 | mainGroup = E937790424EA26FA00107537; 342 | productRefGroup = E937790E24EA26FA00107537 /* Products */; 343 | projectDirPath = ""; 344 | projectRoot = ""; 345 | targets = ( 346 | E937790C24EA26FA00107537 /* FSJCompression */, 347 | E937792A24EA26FD00107537 /* FSJCompressionTests */, 348 | E937793524EA26FD00107537 /* FSJCompressionUITests */, 349 | ); 350 | }; 351 | /* End PBXProject section */ 352 | 353 | /* Begin PBXResourcesBuildPhase section */ 354 | E937790B24EA26FA00107537 /* Resources */ = { 355 | isa = PBXResourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | E937792324EA26FD00107537 /* LaunchScreen.storyboard in Resources */, 359 | E937792024EA26FD00107537 /* Assets.xcassets in Resources */, 360 | E937794D24EA282700107537 /* README.md in Resources */, 361 | E937796224EA2D0500107537 /* FSJCompression.podspec in Resources */, 362 | E937794C24EA282700107537 /* LICENSE in Resources */, 363 | E937791B24EA26FA00107537 /* Main.storyboard in Resources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | E937792924EA26FD00107537 /* Resources */ = { 368 | isa = PBXResourcesBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | ); 372 | runOnlyForDeploymentPostprocessing = 0; 373 | }; 374 | E937793424EA26FD00107537 /* Resources */ = { 375 | isa = PBXResourcesBuildPhase; 376 | buildActionMask = 2147483647; 377 | files = ( 378 | ); 379 | runOnlyForDeploymentPostprocessing = 0; 380 | }; 381 | /* End PBXResourcesBuildPhase section */ 382 | 383 | /* Begin PBXShellScriptBuildPhase section */ 384 | 3A4200822D3A863F08C8C084 /* [CP] Embed Pods Frameworks */ = { 385 | isa = PBXShellScriptBuildPhase; 386 | buildActionMask = 2147483647; 387 | files = ( 388 | ); 389 | inputFileListPaths = ( 390 | "${PODS_ROOT}/Target Support Files/Pods-FSJCompression-FSJCompressionUITests/Pods-FSJCompression-FSJCompressionUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", 391 | ); 392 | name = "[CP] Embed Pods Frameworks"; 393 | outputFileListPaths = ( 394 | "${PODS_ROOT}/Target Support Files/Pods-FSJCompression-FSJCompressionUITests/Pods-FSJCompression-FSJCompressionUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", 395 | ); 396 | runOnlyForDeploymentPostprocessing = 0; 397 | shellPath = /bin/sh; 398 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FSJCompression-FSJCompressionUITests/Pods-FSJCompression-FSJCompressionUITests-frameworks.sh\"\n"; 399 | showEnvVarsInLog = 0; 400 | }; 401 | 95B7BAEAC1D3196AF5C5C1F0 /* [CP] Check Pods Manifest.lock */ = { 402 | isa = PBXShellScriptBuildPhase; 403 | buildActionMask = 2147483647; 404 | files = ( 405 | ); 406 | inputFileListPaths = ( 407 | ); 408 | inputPaths = ( 409 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 410 | "${PODS_ROOT}/Manifest.lock", 411 | ); 412 | name = "[CP] Check Pods Manifest.lock"; 413 | outputFileListPaths = ( 414 | ); 415 | outputPaths = ( 416 | "$(DERIVED_FILE_DIR)/Pods-FSJCompression-FSJCompressionUITests-checkManifestLockResult.txt", 417 | ); 418 | runOnlyForDeploymentPostprocessing = 0; 419 | shellPath = /bin/sh; 420 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 421 | showEnvVarsInLog = 0; 422 | }; 423 | B3133AF1599357F5B2D92D73 /* [CP] Embed Pods Frameworks */ = { 424 | isa = PBXShellScriptBuildPhase; 425 | buildActionMask = 2147483647; 426 | files = ( 427 | ); 428 | inputFileListPaths = ( 429 | "${PODS_ROOT}/Target Support Files/Pods-FSJCompression/Pods-FSJCompression-frameworks-${CONFIGURATION}-input-files.xcfilelist", 430 | ); 431 | name = "[CP] Embed Pods Frameworks"; 432 | outputFileListPaths = ( 433 | "${PODS_ROOT}/Target Support Files/Pods-FSJCompression/Pods-FSJCompression-frameworks-${CONFIGURATION}-output-files.xcfilelist", 434 | ); 435 | runOnlyForDeploymentPostprocessing = 0; 436 | shellPath = /bin/sh; 437 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FSJCompression/Pods-FSJCompression-frameworks.sh\"\n"; 438 | showEnvVarsInLog = 0; 439 | }; 440 | D45CD43D38AAA6B334F13655 /* [CP] Check Pods Manifest.lock */ = { 441 | isa = PBXShellScriptBuildPhase; 442 | buildActionMask = 2147483647; 443 | files = ( 444 | ); 445 | inputFileListPaths = ( 446 | ); 447 | inputPaths = ( 448 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 449 | "${PODS_ROOT}/Manifest.lock", 450 | ); 451 | name = "[CP] Check Pods Manifest.lock"; 452 | outputFileListPaths = ( 453 | ); 454 | outputPaths = ( 455 | "$(DERIVED_FILE_DIR)/Pods-FSJCompressionTests-checkManifestLockResult.txt", 456 | ); 457 | runOnlyForDeploymentPostprocessing = 0; 458 | shellPath = /bin/sh; 459 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 460 | showEnvVarsInLog = 0; 461 | }; 462 | F98A3AEF840D1438E8A49BA7 /* [CP] Check Pods Manifest.lock */ = { 463 | isa = PBXShellScriptBuildPhase; 464 | buildActionMask = 2147483647; 465 | files = ( 466 | ); 467 | inputFileListPaths = ( 468 | ); 469 | inputPaths = ( 470 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 471 | "${PODS_ROOT}/Manifest.lock", 472 | ); 473 | name = "[CP] Check Pods Manifest.lock"; 474 | outputFileListPaths = ( 475 | ); 476 | outputPaths = ( 477 | "$(DERIVED_FILE_DIR)/Pods-FSJCompression-checkManifestLockResult.txt", 478 | ); 479 | runOnlyForDeploymentPostprocessing = 0; 480 | shellPath = /bin/sh; 481 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 482 | showEnvVarsInLog = 0; 483 | }; 484 | /* End PBXShellScriptBuildPhase section */ 485 | 486 | /* Begin PBXSourcesBuildPhase section */ 487 | E937790924EA26FA00107537 /* Sources */ = { 488 | isa = PBXSourcesBuildPhase; 489 | buildActionMask = 2147483647; 490 | files = ( 491 | E937795224EA284400107537 /* FSJCompressionVideoTool.m in Sources */, 492 | E937795724EA294600107537 /* FSJMainViewController.m in Sources */, 493 | E937792624EA26FD00107537 /* main.m in Sources */, 494 | E9772A2125020F570043339C /* FSJCompressionImageTool.m in Sources */, 495 | E937796024EA2B3200107537 /* FSPathTool.m in Sources */, 496 | E937795D24EA2AEE00107537 /* FSVideoImageTool.m in Sources */, 497 | E937791E24EA26FA00107537 /* FSJCompression.xcdatamodeld in Sources */, 498 | E937791824EA26FA00107537 /* ViewController.m in Sources */, 499 | E937791224EA26FA00107537 /* AppDelegate.m in Sources */, 500 | ); 501 | runOnlyForDeploymentPostprocessing = 0; 502 | }; 503 | E937792724EA26FD00107537 /* Sources */ = { 504 | isa = PBXSourcesBuildPhase; 505 | buildActionMask = 2147483647; 506 | files = ( 507 | E937793024EA26FD00107537 /* FSJCompressionTests.m in Sources */, 508 | ); 509 | runOnlyForDeploymentPostprocessing = 0; 510 | }; 511 | E937793224EA26FD00107537 /* Sources */ = { 512 | isa = PBXSourcesBuildPhase; 513 | buildActionMask = 2147483647; 514 | files = ( 515 | E937793B24EA26FD00107537 /* FSJCompressionUITests.m in Sources */, 516 | ); 517 | runOnlyForDeploymentPostprocessing = 0; 518 | }; 519 | /* End PBXSourcesBuildPhase section */ 520 | 521 | /* Begin PBXTargetDependency section */ 522 | E937792D24EA26FD00107537 /* PBXTargetDependency */ = { 523 | isa = PBXTargetDependency; 524 | target = E937790C24EA26FA00107537 /* FSJCompression */; 525 | targetProxy = E937792C24EA26FD00107537 /* PBXContainerItemProxy */; 526 | }; 527 | E937793824EA26FD00107537 /* PBXTargetDependency */ = { 528 | isa = PBXTargetDependency; 529 | target = E937790C24EA26FA00107537 /* FSJCompression */; 530 | targetProxy = E937793724EA26FD00107537 /* PBXContainerItemProxy */; 531 | }; 532 | /* End PBXTargetDependency section */ 533 | 534 | /* Begin PBXVariantGroup section */ 535 | E937791924EA26FA00107537 /* Main.storyboard */ = { 536 | isa = PBXVariantGroup; 537 | children = ( 538 | E937791A24EA26FA00107537 /* Base */, 539 | ); 540 | name = Main.storyboard; 541 | sourceTree = ""; 542 | }; 543 | E937792124EA26FD00107537 /* LaunchScreen.storyboard */ = { 544 | isa = PBXVariantGroup; 545 | children = ( 546 | E937792224EA26FD00107537 /* Base */, 547 | ); 548 | name = LaunchScreen.storyboard; 549 | sourceTree = ""; 550 | }; 551 | /* End PBXVariantGroup section */ 552 | 553 | /* Begin XCBuildConfiguration section */ 554 | E937793D24EA26FD00107537 /* Debug */ = { 555 | isa = XCBuildConfiguration; 556 | buildSettings = { 557 | ALWAYS_SEARCH_USER_PATHS = NO; 558 | CLANG_ANALYZER_NONNULL = YES; 559 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 560 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 561 | CLANG_CXX_LIBRARY = "libc++"; 562 | CLANG_ENABLE_MODULES = YES; 563 | CLANG_ENABLE_OBJC_ARC = YES; 564 | CLANG_ENABLE_OBJC_WEAK = YES; 565 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 566 | CLANG_WARN_BOOL_CONVERSION = YES; 567 | CLANG_WARN_COMMA = YES; 568 | CLANG_WARN_CONSTANT_CONVERSION = YES; 569 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 570 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 571 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 572 | CLANG_WARN_EMPTY_BODY = YES; 573 | CLANG_WARN_ENUM_CONVERSION = YES; 574 | CLANG_WARN_INFINITE_RECURSION = YES; 575 | CLANG_WARN_INT_CONVERSION = YES; 576 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 577 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 578 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 579 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 580 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 581 | CLANG_WARN_STRICT_PROTOTYPES = YES; 582 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 583 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 584 | CLANG_WARN_UNREACHABLE_CODE = YES; 585 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 586 | COPY_PHASE_STRIP = NO; 587 | DEBUG_INFORMATION_FORMAT = dwarf; 588 | ENABLE_STRICT_OBJC_MSGSEND = YES; 589 | ENABLE_TESTABILITY = YES; 590 | GCC_C_LANGUAGE_STANDARD = gnu11; 591 | GCC_DYNAMIC_NO_PIC = NO; 592 | GCC_NO_COMMON_BLOCKS = YES; 593 | GCC_OPTIMIZATION_LEVEL = 0; 594 | GCC_PREPROCESSOR_DEFINITIONS = ( 595 | "DEBUG=1", 596 | "$(inherited)", 597 | ); 598 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 599 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 600 | GCC_WARN_UNDECLARED_SELECTOR = YES; 601 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 602 | GCC_WARN_UNUSED_FUNCTION = YES; 603 | GCC_WARN_UNUSED_VARIABLE = YES; 604 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 605 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 606 | MTL_FAST_MATH = YES; 607 | ONLY_ACTIVE_ARCH = YES; 608 | SDKROOT = iphoneos; 609 | }; 610 | name = Debug; 611 | }; 612 | E937793E24EA26FD00107537 /* Release */ = { 613 | isa = XCBuildConfiguration; 614 | buildSettings = { 615 | ALWAYS_SEARCH_USER_PATHS = NO; 616 | CLANG_ANALYZER_NONNULL = YES; 617 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 618 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 619 | CLANG_CXX_LIBRARY = "libc++"; 620 | CLANG_ENABLE_MODULES = YES; 621 | CLANG_ENABLE_OBJC_ARC = YES; 622 | CLANG_ENABLE_OBJC_WEAK = YES; 623 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 624 | CLANG_WARN_BOOL_CONVERSION = YES; 625 | CLANG_WARN_COMMA = YES; 626 | CLANG_WARN_CONSTANT_CONVERSION = YES; 627 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 628 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 629 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 630 | CLANG_WARN_EMPTY_BODY = YES; 631 | CLANG_WARN_ENUM_CONVERSION = YES; 632 | CLANG_WARN_INFINITE_RECURSION = YES; 633 | CLANG_WARN_INT_CONVERSION = YES; 634 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 635 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 636 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 637 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 638 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 639 | CLANG_WARN_STRICT_PROTOTYPES = YES; 640 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 641 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 642 | CLANG_WARN_UNREACHABLE_CODE = YES; 643 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 644 | COPY_PHASE_STRIP = NO; 645 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 646 | ENABLE_NS_ASSERTIONS = NO; 647 | ENABLE_STRICT_OBJC_MSGSEND = YES; 648 | GCC_C_LANGUAGE_STANDARD = gnu11; 649 | GCC_NO_COMMON_BLOCKS = YES; 650 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 651 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 652 | GCC_WARN_UNDECLARED_SELECTOR = YES; 653 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 654 | GCC_WARN_UNUSED_FUNCTION = YES; 655 | GCC_WARN_UNUSED_VARIABLE = YES; 656 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 657 | MTL_ENABLE_DEBUG_INFO = NO; 658 | MTL_FAST_MATH = YES; 659 | SDKROOT = iphoneos; 660 | VALIDATE_PRODUCT = YES; 661 | }; 662 | name = Release; 663 | }; 664 | E937794024EA26FD00107537 /* Debug */ = { 665 | isa = XCBuildConfiguration; 666 | baseConfigurationReference = A9692FDFD13812EB9BE44FF0 /* Pods-FSJCompression.debug.xcconfig */; 667 | buildSettings = { 668 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 669 | CODE_SIGN_STYLE = Automatic; 670 | DEVELOPMENT_TEAM = DE2G8ZL556; 671 | GCC_PREFIX_HEADER = FSJCompression/PrefixHeader.pch; 672 | INFOPLIST_FILE = FSJCompression/Info.plist; 673 | LD_RUNPATH_SEARCH_PATHS = ( 674 | "$(inherited)", 675 | "@executable_path/Frameworks", 676 | ); 677 | PRODUCT_BUNDLE_IDENTIFIER = com.shengba.www; 678 | PRODUCT_NAME = "$(TARGET_NAME)"; 679 | TARGETED_DEVICE_FAMILY = "1,2"; 680 | }; 681 | name = Debug; 682 | }; 683 | E937794124EA26FD00107537 /* Release */ = { 684 | isa = XCBuildConfiguration; 685 | baseConfigurationReference = 60D55E6B3FC07D221C1BC910 /* Pods-FSJCompression.release.xcconfig */; 686 | buildSettings = { 687 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 688 | CODE_SIGN_STYLE = Automatic; 689 | DEVELOPMENT_TEAM = 334V4U3KT6; 690 | GCC_PREFIX_HEADER = FSJCompression/PrefixHeader.pch; 691 | INFOPLIST_FILE = FSJCompression/Info.plist; 692 | LD_RUNPATH_SEARCH_PATHS = ( 693 | "$(inherited)", 694 | "@executable_path/Frameworks", 695 | ); 696 | PRODUCT_BUNDLE_IDENTIFIER = com.shengba.www; 697 | PRODUCT_NAME = "$(TARGET_NAME)"; 698 | TARGETED_DEVICE_FAMILY = "1,2"; 699 | }; 700 | name = Release; 701 | }; 702 | E937794324EA26FD00107537 /* Debug */ = { 703 | isa = XCBuildConfiguration; 704 | baseConfigurationReference = BEEA25E88C9FD29800FC4830 /* Pods-FSJCompressionTests.debug.xcconfig */; 705 | buildSettings = { 706 | BUNDLE_LOADER = "$(TEST_HOST)"; 707 | CODE_SIGN_STYLE = Automatic; 708 | INFOPLIST_FILE = FSJCompressionTests/Info.plist; 709 | IPHONEOS_DEPLOYMENT_TARGET = 13.6; 710 | LD_RUNPATH_SEARCH_PATHS = ( 711 | "$(inherited)", 712 | "@executable_path/Frameworks", 713 | "@loader_path/Frameworks", 714 | ); 715 | PRODUCT_BUNDLE_IDENTIFIER = com.FSJCompressionTests; 716 | PRODUCT_NAME = "$(TARGET_NAME)"; 717 | TARGETED_DEVICE_FAMILY = "1,2"; 718 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FSJCompression.app/FSJCompression"; 719 | }; 720 | name = Debug; 721 | }; 722 | E937794424EA26FD00107537 /* Release */ = { 723 | isa = XCBuildConfiguration; 724 | baseConfigurationReference = 01A49A738AD35FAB6C55A804 /* Pods-FSJCompressionTests.release.xcconfig */; 725 | buildSettings = { 726 | BUNDLE_LOADER = "$(TEST_HOST)"; 727 | CODE_SIGN_STYLE = Automatic; 728 | INFOPLIST_FILE = FSJCompressionTests/Info.plist; 729 | IPHONEOS_DEPLOYMENT_TARGET = 13.6; 730 | LD_RUNPATH_SEARCH_PATHS = ( 731 | "$(inherited)", 732 | "@executable_path/Frameworks", 733 | "@loader_path/Frameworks", 734 | ); 735 | PRODUCT_BUNDLE_IDENTIFIER = com.FSJCompressionTests; 736 | PRODUCT_NAME = "$(TARGET_NAME)"; 737 | TARGETED_DEVICE_FAMILY = "1,2"; 738 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FSJCompression.app/FSJCompression"; 739 | }; 740 | name = Release; 741 | }; 742 | E937794624EA26FD00107537 /* Debug */ = { 743 | isa = XCBuildConfiguration; 744 | baseConfigurationReference = 6C81677887A7847AF7D0426A /* Pods-FSJCompression-FSJCompressionUITests.debug.xcconfig */; 745 | buildSettings = { 746 | CODE_SIGN_STYLE = Automatic; 747 | INFOPLIST_FILE = FSJCompressionUITests/Info.plist; 748 | LD_RUNPATH_SEARCH_PATHS = ( 749 | "$(inherited)", 750 | "@executable_path/Frameworks", 751 | "@loader_path/Frameworks", 752 | ); 753 | PRODUCT_BUNDLE_IDENTIFIER = com.FSJCompressionUITests; 754 | PRODUCT_NAME = "$(TARGET_NAME)"; 755 | TARGETED_DEVICE_FAMILY = "1,2"; 756 | TEST_TARGET_NAME = FSJCompression; 757 | }; 758 | name = Debug; 759 | }; 760 | E937794724EA26FD00107537 /* Release */ = { 761 | isa = XCBuildConfiguration; 762 | baseConfigurationReference = 2385A1B4E1233FF137EE0BB6 /* Pods-FSJCompression-FSJCompressionUITests.release.xcconfig */; 763 | buildSettings = { 764 | CODE_SIGN_STYLE = Automatic; 765 | INFOPLIST_FILE = FSJCompressionUITests/Info.plist; 766 | LD_RUNPATH_SEARCH_PATHS = ( 767 | "$(inherited)", 768 | "@executable_path/Frameworks", 769 | "@loader_path/Frameworks", 770 | ); 771 | PRODUCT_BUNDLE_IDENTIFIER = com.FSJCompressionUITests; 772 | PRODUCT_NAME = "$(TARGET_NAME)"; 773 | TARGETED_DEVICE_FAMILY = "1,2"; 774 | TEST_TARGET_NAME = FSJCompression; 775 | }; 776 | name = Release; 777 | }; 778 | /* End XCBuildConfiguration section */ 779 | 780 | /* Begin XCConfigurationList section */ 781 | E937790824EA26FA00107537 /* Build configuration list for PBXProject "FSJCompression" */ = { 782 | isa = XCConfigurationList; 783 | buildConfigurations = ( 784 | E937793D24EA26FD00107537 /* Debug */, 785 | E937793E24EA26FD00107537 /* Release */, 786 | ); 787 | defaultConfigurationIsVisible = 0; 788 | defaultConfigurationName = Release; 789 | }; 790 | E937793F24EA26FD00107537 /* Build configuration list for PBXNativeTarget "FSJCompression" */ = { 791 | isa = XCConfigurationList; 792 | buildConfigurations = ( 793 | E937794024EA26FD00107537 /* Debug */, 794 | E937794124EA26FD00107537 /* Release */, 795 | ); 796 | defaultConfigurationIsVisible = 0; 797 | defaultConfigurationName = Release; 798 | }; 799 | E937794224EA26FD00107537 /* Build configuration list for PBXNativeTarget "FSJCompressionTests" */ = { 800 | isa = XCConfigurationList; 801 | buildConfigurations = ( 802 | E937794324EA26FD00107537 /* Debug */, 803 | E937794424EA26FD00107537 /* Release */, 804 | ); 805 | defaultConfigurationIsVisible = 0; 806 | defaultConfigurationName = Release; 807 | }; 808 | E937794524EA26FD00107537 /* Build configuration list for PBXNativeTarget "FSJCompressionUITests" */ = { 809 | isa = XCConfigurationList; 810 | buildConfigurations = ( 811 | E937794624EA26FD00107537 /* Debug */, 812 | E937794724EA26FD00107537 /* Release */, 813 | ); 814 | defaultConfigurationIsVisible = 0; 815 | defaultConfigurationName = Release; 816 | }; 817 | /* End XCConfigurationList section */ 818 | 819 | /* Begin XCVersionGroup section */ 820 | E937791C24EA26FA00107537 /* FSJCompression.xcdatamodeld */ = { 821 | isa = XCVersionGroup; 822 | children = ( 823 | E937791D24EA26FA00107537 /* FSJCompression.xcdatamodel */, 824 | ); 825 | currentVersion = E937791D24EA26FA00107537 /* FSJCompression.xcdatamodel */; 826 | path = FSJCompression.xcdatamodeld; 827 | sourceTree = ""; 828 | versionGroupType = wrapper.xcdatamodel; 829 | }; 830 | /* End XCVersionGroup section */ 831 | }; 832 | rootObject = E937790524EA26FA00107537 /* Project object */; 833 | } 834 | --------------------------------------------------------------------------------