78 Commits

Author SHA1 Message Date
Ahmed Bekhit b923fac2f9 Merge pull request #130 from fattalgazi/swift_5
Update README.md
2021-07-13 16:54:09 -04:00
isa 9e103afc7b Update README.md 2021-07-13 22:33:57 +03:00
Ahmed Bekhit b7e1facded Merge pull request #122 from seriyvolk83/audio_crash_fix
Fixing potential crash #101
2020-12-09 17:47:19 -05:00
Ahmed Bekhit 63c9ebb500 Merge pull request #117 from Jlack6/patch-1
Update README.md
2020-12-09 17:46:13 -05:00
Ahmed Bekhit 3162fa72fb Update README.md 2020-11-19 16:10:43 +03:00
Alexander Volkov 0c9a76a77a Handling flag properly 2020-11-10 12:16:49 +03:00
Alexander Volkov e2ba1ac1c3 Adding check 2020-11-10 12:08:45 +03:00
Alexander Volkov 092413fb42 Fixing potential crash 2020-11-10 11:54:57 +03:00
James Lack 7596d066a6 Update README.md
Added ScribScrab to the Apps using ARVideoKit
2020-09-11 09:23:50 -04:00
Ahmed Bekhit 275f850486 Merge pull request #115 from mattbierner/patch-1
Add In The Walls app
2020-08-30 16:07:01 -04:00
Ahmed Bekhit e150e00203 Update README.md 2020-08-21 17:24:48 -04:00
Matt Bierner e2d5e537e3 Add In The Walls app
Adds [In The Walls](https://apps.apple.com/us/app/id1522257130) to the readme. We use this library for recording video
2020-08-05 19:43:35 -07:00
Ahmed Bekhit 1ef5e99fe7 Merge pull request #113 from shaj04/ARRenderer_content_mode_bugfix
adjust when to set renderer.ARcontentMode
2020-08-01 20:31:52 -04:00
Ahmed Bekhit 62a6c6a89a Update README.md 2020-07-30 21:50:13 -04:00
shajie e8dae8c989 adjust when to set renderer.ARcontentMode 2020-06-12 19:00:46 +08:00
Ahmed Bekhit 2d87e3e7e7 Merge pull request #111 from AFathi/CocoaPodsUpdate-patch-1
Update to latest version
2020-04-25 15:58:46 -04:00
Giacomo 74a3159c70 Update to latest version 2020-04-23 15:27:12 +02:00
Ahmed Bekhit 589e6e77d4 Merge pull request #108 from 0k1019/feature/MaxDevice
Fix iPhone X Max, XS Max, 11Pro Max size recording size problem.
2020-04-15 17:20:06 -04:00
Youngho Kwon d1c840e383 Update isNotch function consider when landscape mode. 2020-04-09 16:12:18 +09:00
Youngho Kwon ae9c620621 Fix iPhone X Max, XS Max, 11Pro Max size recording size problem. Renewing "isiPhone10" extension to "isNotch". 2020-03-24 15:41:44 +09:00
Ahmed Bekhit 8eabd31931 Merge pull request #105 from GiacomoLeopizzi/swift_package_manager
Swift package manager
2020-02-27 11:26:27 -05:00
Giacomo 6c0465b521 Merge pull request #2 from GiacomoLeopizzi/swift_5
Update
2020-02-26 16:58:54 +01:00
Giacomo d77170b2ba Merge pull request #1 from AFathi/swift_5
Update
2020-02-26 16:56:11 +01:00
Giacomo 419c434503 Readme updated 2020-02-26 16:42:59 +01:00
Giacomo d952f66094 Remove not needed files 2020-02-26 16:34:41 +01:00
Giacomo c6b94a485a SwiftPM 2020-02-26 16:26:20 +01:00
Ahmed Bekhit 24d9220fad Merge pull request #104 from GiacomoLeopizzi/weak_delegate
Added weak
2020-02-20 15:39:03 -08:00
Giacomo 62ed6bc6b7 Added weak 2020-02-20 23:40:53 +01:00
Giacomo 187c505359 Merge branch 'view_aspect_ratio' into swift_package_manager 2020-02-13 12:11:48 +02:00
Giacomo 2c1a98a12a Dynamic library 2020-02-13 12:09:05 +02:00
Giacomo 2eef6c5b44 Swift package manager 2020-02-13 11:50:54 +02:00
Ahmed Bekhit cabc5535f0 Merge pull request #100 from GiacomoLeopizzi/view_aspect_ratio
Support for custom aspect ratio
2020-02-09 10:44:13 -08:00
Giacomo e9a88d4a2b Support for custom aspect ratio 2020-02-09 14:21:27 +01:00
Ahmed Bekhit 7cc44e3eae Update README.md 2020-01-10 13:39:31 -05:00
Ahmed Bekhit dcddd6b7c3 Update + validate podspec file 2020-01-10 13:01:26 -05:00
Ahmed Bekhit 8e6f8bd448 Update podspec file 2020-01-10 12:40:55 -05:00
Ahmed Bekhit a56f372be8 Update podspec file 2020-01-10 12:36:22 -05:00
Ahmed Bekhit e01e55fa65 Merge pull request #98 from bartosy-ymija/swift_5
Add SCNTechnique retaining support
2019-11-21 13:28:24 -05:00
Bartosy 3b74f31e22 Ensure nil safety 2019-11-20 20:04:30 +01:00
Bartosy 5d19bc6959 Add technique retaining support 2019-11-20 13:51:01 +01:00
Ahmed Bekhit b87b020996 Merge pull request #95 from maxxfrazer/swift_5
Rebasing with Xcode 11 fixes
2019-09-08 14:33:28 -04:00
Ahmed Bekhit 7acb7a2dfd Update example project Swift version 2019-09-08 15:58:04 +01:00
Saul Moreno Abril 84c501810f Update to Swift 5.0 2019-09-08 15:58:04 +01:00
Ahmed Bekhit f2f64a6580 Merge pull request #94 from wolfcon/fix/xcode-11-error-for-PHLivePhotoPlus
Fix PHLivePhoto in Xcode 11 (iOS 13 SDK) error : `'init()' has been xplicitly marked unavailable here (Photos.PHLivePhoto)`
2019-08-21 08:26:16 -04:00
Frank e388eaa21e Fix PHLivePhoto in Xcode 11 (iOS 13 SDK) error : 'init()' has been explicitly marked unavailable here (Photos.PHLivePhoto) 2019-08-21 17:48:36 +08:00
Ahmed Bekhit 95994f707f Update example project Swift version 2019-06-25 22:24:27 -04:00
Ahmed Bekhit 507ec687c3 Change didCancel protocol to optional 2019-06-25 22:21:49 -04:00
Ahmed Bekhit d79e2d4829 Merge pull request #72 from asam139/feature/cancel_recording
Cancel recording
2019-06-25 22:14:54 -04:00
Ahmed Bekhit 387c864e71 Merge branch 'swift_4_2' into feature/cancel_recording 2019-06-25 22:14:29 -04:00
Ahmed Bekhit c44194230b Update README.md 2019-06-25 22:08:09 -04:00
Ahmed Bekhit 7870134192 Update README.md 2019-06-25 22:07:56 -04:00
Ahmed Bekhit 3cb80cba01 Update README.md 2019-05-13 09:13:59 -04:00
Ahmed Bekhit 658fb4ca07 Update README.md 2019-05-13 09:13:41 -04:00
Ahmed Bekhit 94e3dddfea Merge @asam139 contribution
Fix memory issues and enhance performance
2019-05-04 11:50:00 -04:00
Saul Moreno Abril d3f52c26f4 Fix crash: it checks resumeFrameTime is not nil 2019-05-03 16:10:49 +01:00
Saul Moreno Abril 4dd890a885 Fix memory leak using leak for delegate's WritAR 2019-05-01 15:49:53 +01:00
Saul Moreno Abril a320a51e90 Use weak proxy for CADisplayLink to broke the leak memory 2019-05-01 15:31:52 +01:00
Saul Moreno Abril 1ab12173f4 Move var as private and not global 2019-05-01 15:31:46 +01:00
Saul Moreno Abril a513e4157f Fix leak memory parent view must be weak reference 2019-05-01 15:07:05 +01:00
Saul Moreno Abril 54ad883307 Update to Swift 5.0 2019-03-30 12:27:11 +01:00
Ahmed Bekhit 11b1d4738b Update README.md 2019-03-06 10:38:01 -05:00
AFathi 7a63dbe34a minor bug fixes 2019-03-01 17:22:19 -05:00
Ahmed Bekhit 05ee09b1ce Merge pull request #73 from asam139/feature/current_duration
Add delegate to get progress of duration of current recording
2019-03-01 16:52:44 -05:00
Ahmed Bekhit 30afffd79f Merge pull request #77 from Svrf/fix-bug-when-crash
Fix bug when app crashes after stop video recording
2019-03-01 16:50:21 -05:00
Andrey Evstratenko 3b6e4f60c8 fix bug when app crashes 2019-02-27 15:58:59 +03:00
Saul Moreno Abril 7b5326adcb Add delegate to get progress of duration of current recording 2019-01-15 19:09:26 +01:00
Saul Moreno Abril e6d24ec1b4 Fix grammar 2019-01-15 19:02:59 +01:00
Saul Moreno Abril 5c419c3031 Add method to cancel recording (deleting current url) 2019-01-10 20:51:51 +01:00
Ahmed Bekhit 0653f11cfd Merge pull request #71 from asam139/fix/deprecated_swift_version_file
Deprecated swift_version file
2019-01-06 21:28:38 -05:00
Saul Moreno Abril bc70751aff Remove the ".swift-version" file which is now deprecated and only use the "swift_version" attribute within your podspec. 2019-01-05 19:52:56 +01:00
Ahmed Bekhit ebb2d0a485 Merge pull request #70 from youllbejustfine/swift_4_2
Bypassing pixel buffer attributes - Resolving recording issues that occurred on iPhone X and higher devices
2018-12-17 11:54:41 -05:00
Lukas Steinman 483bf4563b Bypassing pixel buffer attributes to resolve recordings not working on iPhone X/XS/XMax devices. 2018-12-17 12:21:48 -04:00
Ahmed Bekhit 2015b4db0e Update README.md 2018-09-26 23:08:47 -04:00
AFathi 85e846ef25 swift4.2 fixes xcode10 GM 2018-09-25 16:51:07 -04:00
AFathi 8420a3808f fixes for final xcode10 version 2018-09-25 16:26:11 -04:00
AFathi 1fb3a03593 Swift project update to 4.2 2018-09-20 12:08:58 -04:00
AFathi cd0d7f34cf Swift 4.2 Support 2018-09-20 12:02:07 -04:00
AFathi 6a4290e17b swift 4.2 branch 2018-09-20 11:45:09 -04:00
22 changed files with 264 additions and 143 deletions
+1
View File
@@ -65,3 +65,4 @@ fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
.DS_Store
+4 -7
View File
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = "ARVideoKit"
s.version = "1.5.12"
s.version = "1.6.0"
s.summary = "Capture & record ARKit videos 📹, photos 🌄, Live Photos 🎇, and GIFs 🎆."
s.description = "Enabling developers to capture videos 📹, photos 🌄, Live Photos 🎇, and GIFs 🎆 with augmented reality components."
s.homepage = "https://github.com/AFathi/ARVideoKit"
s.screenshots = "http://www.ahmedbekhit.com/SK_PREV.gif", "http://www.ahmedbekhit.com/SCN_PREVIEW.gif"
s.swift_version = '5.0'
s.license = { :type => "Apache 2.0", :file => "LICENSE" }
@@ -16,10 +16,7 @@ Pod::Spec.new do |s|
s.platform = :ios, "11.0"
# ARVideoKit for Swift 4.0
s.source = { :git => "https://github.com/AFathi/ARVideoKit.git", :tag => "1.5.12" }
# ARVideoKit for Swift 5.0
s.source = { :git => "https://github.com/AFathi/ARVideoKit.git", :tag => "1.6.0" }
s.source_files = "ARVideoKit", "ARVideoKit/**/*.{h,m,swift}"
s.resources = "ARVideoKit/Assets/*.scnassets"
s.swift_version = '4.0'
end
+16 -15
View File
@@ -7,10 +7,10 @@
objects = {
/* Begin PBXBuildFile section */
B466A8B82279E34C00BD7070 /* WeakProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B466A8B72279E34C00BD7070 /* WeakProxy.swift */; };
FB2E36891FAE29C00035B8D6 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = FB2E36881FAE29BF0035B8D6 /* LICENSE */; };
FB404FFE20D72A190056EA1D /* JPEG.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB404FFD20D72A190056EA1D /* JPEG.swift */; };
FBD604DF1FA969DD00EC9804 /* ARVideoKit.h in Headers */ = {isa = PBXBuildFile; fileRef = FBD604DD1FA969DD00EC9804 /* ARVideoKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
FBD604EB1FA96B1C00EC9804 /* video.scnassets in Resources */ = {isa = PBXBuildFile; fileRef = FBD604EA1FA96B1C00EC9804 /* video.scnassets */; };
FBD604EE1FA96B2700EC9804 /* ARVideoOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBD604EC1FA96B2700EC9804 /* ARVideoOptions.swift */; };
FBD604EF1FA96B2700EC9804 /* ARInputViewOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBD604ED1FA96B2700EC9804 /* ARInputViewOptions.swift */; };
FBD604F51FA96B3300EC9804 /* UIImage+VideoBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBD604F01FA96B3300EC9804 /* UIImage+VideoBuffer.swift */; };
@@ -33,12 +33,12 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
B466A8B72279E34C00BD7070 /* WeakProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakProxy.swift; sourceTree = "<group>"; };
FB2E36881FAE29BF0035B8D6 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
FB404FFD20D72A190056EA1D /* JPEG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JPEG.swift; sourceTree = "<group>"; };
FBD604DA1FA969DD00EC9804 /* ARVideoKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ARVideoKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FBD604DD1FA969DD00EC9804 /* ARVideoKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ARVideoKit.h; sourceTree = "<group>"; };
FBD604DE1FA969DD00EC9804 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FBD604EA1FA96B1C00EC9804 /* video.scnassets */ = {isa = PBXFileReference; lastKnownFileType = wrapper.scnassets; path = video.scnassets; sourceTree = "<group>"; };
FBD604EC1FA96B2700EC9804 /* ARVideoOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ARVideoOptions.swift; sourceTree = "<group>"; };
FBD604ED1FA96B2700EC9804 /* ARInputViewOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ARInputViewOptions.swift; sourceTree = "<group>"; };
FBD604F01FA96B3300EC9804 /* UIImage+VideoBuffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+VideoBuffer.swift"; sourceTree = "<group>"; };
@@ -71,6 +71,14 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B466A8B62279E33800BD7070 /* Utils */ = {
isa = PBXGroup;
children = (
B466A8B72279E34C00BD7070 /* WeakProxy.swift */,
);
path = Utils;
sourceTree = "<group>";
};
FBA0AA0A1FAD9D9D006C481B /* Writer */ = {
isa = PBXGroup;
children = (
@@ -99,7 +107,7 @@
FBD604DC1FA969DD00EC9804 /* ARVideoKit */ = {
isa = PBXGroup;
children = (
FBD604E51FA96ACD00EC9804 /* Assets */,
B466A8B62279E33800BD7070 /* Utils */,
FBD604E61FA96AD400EC9804 /* Enumerations */,
FBD604E71FA96AE500EC9804 /* Extensions */,
FBD604E81FA96AEC00EC9804 /* Protocols */,
@@ -111,14 +119,6 @@
path = ARVideoKit;
sourceTree = "<group>";
};
FBD604E51FA96ACD00EC9804 /* Assets */ = {
isa = PBXGroup;
children = (
FBD604EA1FA96B1C00EC9804 /* video.scnassets */,
);
path = Assets;
sourceTree = "<group>";
};
FBD604E61FA96AD400EC9804 /* Enumerations */ = {
isa = PBXGroup;
children = (
@@ -241,7 +241,7 @@
TargetAttributes = {
FBD604D91FA969DD00EC9804 = {
CreatedOnToolsVersion = 9.1;
LastSwiftMigration = 0910;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
@@ -252,6 +252,7 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = FBD604D01FA969DD00EC9804;
productRefGroup = FBD604DB1FA969DD00EC9804 /* Products */;
@@ -269,7 +270,6 @@
buildActionMask = 2147483647;
files = (
FB2E36891FAE29C00035B8D6 /* LICENSE in Resources */,
FBD604EB1FA96B1C00EC9804 /* video.scnassets in Resources */,
FBD605071FA96B6B00EC9804 /* LoveLiver_LICENSE in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -290,6 +290,7 @@
FBD604F51FA96B3300EC9804 /* UIImage+VideoBuffer.swift in Sources */,
FBD605111FA96BA100EC9804 /* ARView.swift in Sources */,
FBD604F61FA96B3300EC9804 /* CGImage+Resize.swift in Sources */,
B466A8B82279E34C00BD7070 /* WeakProxy.swift in Sources */,
FBD604F91FA96B3300EC9804 /* UIViewController+hasType.swift in Sources */,
FBD605141FA96BA100EC9804 /* ViewAR.swift in Sources */,
FBD604EE1FA96B2700EC9804 /* ARVideoOptions.swift in Sources */,
@@ -450,7 +451,7 @@
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -475,7 +476,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.ahmedbekhit.ARVideoKit;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
Binary file not shown.
@@ -5,6 +5,7 @@
// Created by Ahmed Bekhit on 10/18/17.
// Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
//
import Foundation
/// Allows specifying the final video orientation.
@objc public enum ARFrameMode: Int {
@@ -12,6 +13,7 @@
case aspectFit
/// Recommended for iPhone X
case aspectFill
case viewAspectRatio
}
/// Allows specifying the video rendering frame per second `FPS` rate.
@@ -8,6 +8,7 @@
import AVFoundation
import Photos
import UIKit
@available(iOS 11.0, *)
extension RecordAR {
+2 -2
View File
@@ -14,8 +14,8 @@ extension UIScreen {
/**
`isiPhone10` is a boolean that returns if the device is iPhone X or not.
*/
var isiPhone10: Bool {
return self.nativeBounds.size == CGSize(width: 1125, height: 2436) || self.nativeBounds.size == CGSize(width: 2436, height: 1125)
var isNotch: Bool {
return UIApplication.shared.keyWindow?.safeAreaInsets != UIEdgeInsets.zero
}
}
@available(iOS 11.0, *)
+1 -1
View File
@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.31</string>
<string>1.32</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
@@ -28,12 +28,25 @@ import ARKit
- parameter noError: A boolean that returns true when the recorder ends without errors. Otherwise, it returns false.
*/
func recorder(didEndRecording path: URL, with noError: Bool)
/**
A protocol method that is triggered when a recorder fails recording.
- parameter error: An `Error` object that returns the error value.
- parameter status: A string that returns the reason of the recorder failure in a string literal format.
*/
func recorder(didFailRecording error: Error?, and status: String)
/**
A protocol method that is triggered when a recorder is cancelled.
- parameter status: A string that returns the reason the of recorder cancelation in a string literal format.
*/
@objc optional func recorder(didCancelRecording status: String)
/**
A protocol method that is triggered when a recorder is modified.
- parameter duration: A double that returns the duration of current recording
*/
@objc optional func recorder(didUpdateRecording duration: TimeInterval)
/**
A protocol method that is triggered when the application will resign active.
@@ -8,6 +8,7 @@
import AVFoundation
import Photos
import UIKit
@available(iOS 11.0, *)
class LivePhotoGenerator {
@@ -26,11 +27,11 @@ class LivePhotoGenerator {
generator.appliesPreferredTrackTransform = true
//retrieves the key photo frame from the middle of the video asset
let time = NSValue(time: CMTimeMultiplyByFloat64(asset.duration, 0.5))
let time = NSValue(time: CMTimeMultiplyByFloat64(asset.duration, multiplier: 0.5))
//generates the key photo CGImage asynchronously
generator.generateCGImagesAsynchronously(forTimes: [time], completionHandler: { _, image, _, _, _ in
if let cgImg = image, let imgData = UIImagePNGRepresentation(UIImage(cgImage: cgImg)) {
if let cgImg = image, let imgData = UIImage(cgImage: cgImg).pngData() {
do {
self.keyPhotoPath = self.newPath(for: true, and: false)
try imgData.write(to: self.keyPhotoPath!, options: [.atomic])
@@ -16,7 +16,7 @@ class QuickTimeMov {
private let kKeyStillImageTime = "com.apple.quicktime.still-image-time"
private let kKeySpaceQuickTimeMetadata = "mdta"
private let path: String
private let dummyTimeRange = CMTimeRangeMake(CMTimeMake(0, 1000), CMTimeMake(200, 3000))
private let dummyTimeRange = CMTimeRange(start: CMTime(value: 0, timescale: 1000), duration: CMTime(value: 200, timescale: 3000))
private lazy var asset: AVURLAsset = {
let url = URL(fileURLWithPath: self.path)
@@ -128,7 +128,7 @@ class QuickTimeMov {
// --------------------------------------------------
writer.startWriting()
reader.startReading()
writer.startSession(atSourceTime: kCMTimeZero)
writer.startSession(atSourceTime: CMTime.zero)
// write metadata track
adapter.append(AVTimedMetadataGroup(items: [metadataForStillImageTime()],
@@ -148,7 +148,7 @@ class QuickTimeMov {
input.markAsFinished()
if reader.status == .completed && aAudioAsset.tracks.count > 1 {
audioReader?.startReading()
writer.startSession(atSourceTime: kCMTimeZero)
writer.startSession(atSourceTime: CMTime.zero)
let media_queue = DispatchQueue(label: "assetAudioWriterQueue", attributes: [])
audioWriterInput?.requestMediaDataWhenReady(on: media_queue) {
while (audioWriterInput?.isReadyForMoreMediaData)! {
@@ -218,7 +218,9 @@ class QuickTimeMov {
"com.apple.metadata.datatype.int8" ]
var desc: CMFormatDescription? = nil
CMMetadataFormatDescriptionCreateWithMetadataSpecifications(kCFAllocatorDefault, kCMMetadataFormatType_Boxed, [spec] as CFArray, &desc)
CMMetadataFormatDescriptionCreateWithMetadataSpecifications(allocator: kCFAllocatorDefault, metadataType: kCMMetadataFormatType_Boxed, metadataSpecifications: [spec] as CFArray, formatDescriptionOut: &desc)
// CMFormatDescription.createForMetadata(allocator: kCFAllocatorDefault, metadataType: kCMMetadataFormatType_Boxed, metadataSpecifications: [spec] as CFArray, formatDescriptionOut: &desc)
let input = AVAssetWriterInput(mediaType: AVMediaType.metadata,
outputSettings: nil, sourceFormatHint: desc)
return AVAssetWriterInputMetadataAdaptor(assetWriterInput: input)
+11 -7
View File
@@ -9,11 +9,10 @@
import Foundation
import ARKit
private var view: Any?
private var renderEngine: SCNRenderer!
@available(iOS 11.0, *)
struct RenderAR {
private var view: Any?
private var renderEngine: SCNRenderer!
var ARcontentMode: ARFrameMode!
init(_ ARview: Any?, renderer: SCNRenderer, contentMode: ARFrameMode) {
@@ -45,7 +44,7 @@ struct RenderAR {
if let contentMode = ARcontentMode {
switch contentMode {
case .auto:
if UIScreen.main.isiPhone10 {
if UIScreen.main.isNotch {
width = Int(UIScreen.main.nativeBounds.width)
height = Int(UIScreen.main.nativeBounds.height)
}
@@ -55,8 +54,15 @@ struct RenderAR {
case .aspectFill:
width = Int(UIScreen.main.nativeBounds.width)
height = Int(UIScreen.main.nativeBounds.height)
case .viewAspectRatio where view is UIView:
let bufferWidth = CVPixelBufferGetWidth(raw)
let bufferHeight = CVPixelBufferGetHeight(raw)
let viewSize = (view as! UIView).bounds.size
let targetSize = AVMakeRect(aspectRatio: viewSize, insideRect: CGRect(x: 0, y: 0, width: bufferWidth, height: bufferHeight)).size
width = Int(targetSize.width)
height = Int(targetSize.height)
default:
if UIScreen.main.isiPhone10 {
if UIScreen.main.isNotch {
width = Int(UIScreen.main.nativeBounds.width)
height = Int(UIScreen.main.nativeBounds.height)
}
@@ -93,9 +99,7 @@ struct RenderAR {
} else {
renderedFrame = renderEngine.snapshot(atTime: time, with: size, antialiasingMode: .none)
}
guard let buffer = renderedFrame!.buffer else { return nil }
return buffer
} else if view is ARSKView {
guard let size = bufferSize else { return nil }
+39 -41
View File
@@ -25,7 +25,7 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
private var isRecording: Bool = false
var delegate: RecordARDelegate?
weak var delegate: RecordARDelegate?
var videoInputOrientation: ARVideoOrientation = .auto
init(output: URL, width: Int, height: Int, adjustForSharing: Bool, audioEnabled: Bool, orientaions:[ARInputViewOrientation], queue: DispatchQueue, allowMix: Bool) {
@@ -33,13 +33,13 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
do {
assetWriter = try AVAssetWriter(outputURL: output, fileType: AVFileType.mp4)
} catch {
fatalError("An error occurred while intializing an AVAssetWriter")
// FIXME: handle when failed to allocate AVAssetWriter.
return
}
if audioEnabled {
if allowMix {
let audioOptions: AVAudioSessionCategoryOptions = [.mixWithOthers , .allowBluetooth, .defaultToSpeaker, .interruptSpokenAudioAndMixWithOthers]
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, with: audioOptions)
let audioOptions: AVAudioSession.CategoryOptions = [.mixWithOthers , .allowBluetooth, .defaultToSpeaker, .interruptSpokenAudioAndMixWithOthers]
try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, mode: AVAudioSession.Mode.spokenAudio, options: audioOptions)
try? AVAudioSession.sharedInstance().setActive(true)
}
AVAudioSession.sharedInstance().requestRecordPermission({ permitted in
@@ -57,15 +57,15 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
AVVideoHeightKey: height as AnyObject
]
// let attributes: [String: Bool] = [
// kCVPixelBufferCGImageCompatibilityKey as String: true,
// kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
// ]
let attributes: [String: Bool] = [
kCVPixelBufferCGImageCompatibilityKey as String: true,
kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
]
videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutputSettings)
videoInput.expectsMediaDataInRealTime = true
pixelBufferInput = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoInput, sourcePixelBufferAttributes: nil)
var angleEnabled: Bool {
for v in orientaions {
if UIDevice.current.orientation.rawValue == v.rawValue {
@@ -141,7 +141,6 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
if session.canAddInput(audioDeviceInput!) {
session.addInput(audioDeviceInput!)
}
if session.canAddOutput(audioDataOutput) {
session.addOutput(audioDataOutput)
}
@@ -153,7 +152,7 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
audioInput.expectsMediaDataInRealTime = true
audioBufferQueue.async {
self.session.startRunning()
self.session?.startRunning()
}
if assetWriter.canAdd(audioInput) {
@@ -163,34 +162,11 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
var startingVideoTime: CMTime?
var isWritingWithoutError: Bool?
var currentDuration: TimeInterval = 0 // Seconds
func insert(pixel buffer: CVPixelBuffer, with intervals: CFTimeInterval) {
let time: CMTime = CMTimeMakeWithSeconds(intervals, 1000000)
if assetWriter.status == .unknown {
guard startingVideoTime == nil else {
isWritingWithoutError = false
return
}
startingVideoTime = time
if assetWriter.startWriting() {
assetWriter.startSession(atSourceTime: startingVideoTime!)
session.startRunning()
isRecording = true
isWritingWithoutError = true
} else {
delegate?.recorder(didFailRecording: assetWriter.error, and: "An error occurred while starting the video session.")
isWritingWithoutError = false
}
} else if assetWriter.status == .failed {
delegate?.recorder(didFailRecording: assetWriter.error, and: "Video session failed while recording.")
logAR.message("An error occurred while recording the video, status: \(assetWriter.status.rawValue), error: \(assetWriter.error!.localizedDescription)")
isWritingWithoutError = false
return
}
if videoInput.isReadyForMoreMediaData {
append(pixel: buffer, with: time)
isWritingWithoutError = true
}
let time: CMTime = CMTime(seconds: intervals, preferredTimescale: 1000000)
insert(pixel: buffer, with: time)
}
func insert(pixel buffer: CVPixelBuffer, with time: CMTime) {
@@ -202,16 +178,19 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
startingVideoTime = time
if assetWriter.startWriting() {
assetWriter.startSession(atSourceTime: startingVideoTime!)
currentDuration = 0
isRecording = true
isWritingWithoutError = true
} else {
delegate?.recorder(didFailRecording: assetWriter.error, and: "An error occurred while starting the video session.")
currentDuration = 0
isRecording = false
isWritingWithoutError = false
}
} else if assetWriter.status == .failed {
delegate?.recorder(didFailRecording: assetWriter.error, and: "Video session failed while recording.")
logAR.message("An error occurred while recording the video, status: \(assetWriter.status.rawValue), error: \(assetWriter.error!.localizedDescription)")
currentDuration = 0
isRecording = false
isWritingWithoutError = false
return
@@ -219,15 +198,20 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
if videoInput.isReadyForMoreMediaData {
append(pixel: buffer, with: time)
currentDuration = time.seconds - startingVideoTime!.seconds
isRecording = true
isWritingWithoutError = true
delegate?.recorder?(didUpdateRecording: currentDuration)
}
}
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
if let input = audioInput {
audioBufferQueue.async { [weak self] in
if input.isReadyForMoreMediaData && (self?.isRecording)! {
if let isRecording = self?.isRecording,
let session = self?.session,
input.isReadyForMoreMediaData && isRecording
&& session.isRunning {
input.append(sampleBuffer)
}
}
@@ -238,13 +222,27 @@ class WritAR: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
isRecording = false
}
func end(writing finished: @escaping () -> Void){
func end(writing finished: @escaping () -> Void) {
if let session = session {
if session.isRunning {
session.stopRunning()
}
}
assetWriter.finishWriting(completionHandler: finished)
if assetWriter.status == .writing {
isRecording = false
assetWriter.finishWriting(completionHandler: finished)
}
}
func cancel() {
if let session = session {
if session.isRunning {
session.stopRunning()
}
}
isRecording = false
assetWriter.cancelWriting()
}
}
+4 -4
View File
@@ -20,7 +20,7 @@ import ARKit
*/
@available(iOS 11.0, *)
@objc public class ARView: NSObject {
private var parentVC: UIViewController?
private weak var parentVC: UIViewController?
private var recentAngle = 0
private var inputViewOrientation:[ARInputViewOrientation] = []
@@ -52,7 +52,7 @@ import ARKit
@objc init?(ARSceneKit: ARSCNView) {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: UIDevice.orientationDidChangeNotification, object: nil)
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
@@ -68,7 +68,7 @@ import ARKit
@objc init?(ARSpriteKit: ARSKView) {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: UIDevice.orientationDidChangeNotification, object: nil)
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
@@ -82,7 +82,7 @@ import ARKit
@objc init?(SceneKit: SCNView) {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: UIDevice.orientationDidChangeNotification, object: nil)
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
+88 -36
View File
@@ -12,13 +12,6 @@ import ARKit
import Photos
import PhotosUI
private var view: Any?
private var renderEngine: SCNRenderer!
private var gpuLoop: CADisplayLink!
private var isResting = false
private var ARcontentMode: ARFrameMode!
@available(iOS 11.0, *)
private var renderer: RenderAR!
/**
This class renders the `ARSCNView` or `ARSKView` content with the device's camera stream to generate a video 📹, photo 🌄, live photo 🎇 or GIF 🎆.
@@ -34,11 +27,11 @@ private var renderer: RenderAR!
/**
An object that passes the AR recorder errors and status in the protocol methods.
*/
@objc public weak var delegate: RecordARDelegate?
@objc weak public var delegate: RecordARDelegate?
/**
An object that passes the AR rendered content in the protocol method.
*/
@objc public weak var renderAR: RenderARDelegate?
@objc weak public var renderAR: RenderARDelegate?
/**
An object that returns the AR recorder current status.
*/
@@ -116,6 +109,21 @@ private var renderer: RenderAR!
}
}
}
/**
A boolean that indicates whether render engine should retain SCNTechnique used in the view. Default is `false`.
*/
@objc public var retainTechnique: Bool = false {
didSet {
if retainTechnique {
guard let techniqueSupportingView = view as? SCNTechniqueSupport else {
return
}
renderEngine?.technique = techniqueSupportingView.technique
} else {
renderEngine?.technique = nil
}
}
}
//MARK: - Public initialization methods
/**
@@ -135,16 +143,9 @@ private var renderer: RenderAR!
view = ARSpriteKit
scnView = SCNView(frame: UIScreen.main.bounds)
let bundle = Bundle(for: RecordAR.self)
let url = bundle.url(forResource: "video.scnassets/vid", withExtension: "scn")
do {
let scene = try SCNScene(url: url!, options: nil)
scnView.scene = scene
setup()
}catch let error {
logAR.message("Error occurred while loading SK Video Assets : \(error). Please download \"video.scnassets\" from\nwww.ahmedbekhit.com/ARVideoKitAssets")
}
let scene = SCNScene()
scnView.scene = scene
setup()
}
/**
@@ -155,6 +156,11 @@ private var renderer: RenderAR!
view = SceneKit
setup()
}
//MARK: - Deinit
deinit {
gpuLoop.invalidate()
}
//MARK: - threads
let writerQueue = DispatchQueue(label:"com.ahmedbekhit.WriterQueue")
@@ -162,6 +168,12 @@ private var renderer: RenderAR!
let audioSessionQueue = DispatchQueue(label: "com.ahmedbekhit.AudioSessionQueue", attributes: .concurrent)
//MARK: - Objects
private var view: Any?
private var renderEngine: SCNRenderer!
private var gpuLoop: CADisplayLink!
private var isResting = false
private var renderer: RenderAR!
private var scnView: SCNView!
private var fileCount = 0
@@ -220,10 +232,11 @@ private var renderer: RenderAR!
}
renderEngine = SCNRenderer(device: mtlDevice, options: nil)
renderEngine.scene = view.scene
gpuLoop = CADisplayLink(target: self, selector: #selector(renderFrame))
gpuLoop = CADisplayLink(target: WeakProxy(target: self),
selector: #selector(renderFrame))
gpuLoop.preferredFramesPerSecond = fps.rawValue
gpuLoop.add(to: .main, forMode: .commonModes)
gpuLoop.add(to: .main, forMode: .common)
status = .readyToRecord
} else if let view = view as? ARSKView {
@@ -243,10 +256,11 @@ private var renderer: RenderAR!
renderEngine = SCNRenderer(device: mtlDevice, options: nil)
renderEngine.scene = scnView.scene
gpuLoop = CADisplayLink(target: self, selector: #selector(renderFrame))
gpuLoop = CADisplayLink(target: WeakProxy(target: self),
selector: #selector(renderFrame))
gpuLoop.preferredFramesPerSecond = fps.rawValue
gpuLoop.add(to: .main, forMode: .commonModes)
gpuLoop.add(to: .main, forMode: .common)
status = .readyToRecord
} else if let view = view as? SCNView {
@@ -256,10 +270,11 @@ private var renderer: RenderAR!
}
renderEngine = SCNRenderer(device: mtlDevice, options: nil)
renderEngine.scene = view.scene
gpuLoop = CADisplayLink(target: self, selector: #selector(renderFrame))
gpuLoop = CADisplayLink(target: WeakProxy(target: self),
selector: #selector(renderFrame))
gpuLoop.preferredFramesPerSecond = fps.rawValue
gpuLoop.add(to: .main, forMode: .commonModes)
gpuLoop.add(to: .main, forMode: .common)
status = .readyToRecord
}
@@ -268,7 +283,7 @@ private var renderer: RenderAR!
renderer = RenderAR(view, renderer: renderEngine, contentMode: contentMode)
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterBackground), name: UIApplication.willResignActiveNotification, object: nil)
}
@@ -513,6 +528,39 @@ private var renderer: RenderAR!
}
}
}
/**
A method that cancels recording a video 📹.
- parameter finished: A block that will be called when the specified `duration` has ended.
*/
@objc public func cancel() {
writerQueue.sync {
isRecording = false
adjustPausedTime = false
backFromPause = false
recordingWithLimit = false
pausedFrameTime = nil
resumeFrameTime = nil
DispatchQueue.main.async {
self.writer?.cancel()
if let path = self.currentVideoPath {
logAR.remove(from: path)
self.delegate?.recorder?(didCancelRecording: "Recording was cancelled manually.")
self.status = .readyToRecord
} else {
self.status = .readyToRecord
self.delegate?.recorder(didFailRecording: errSecDecode as? Error, and: "An error occured while stopping your video.")
}
self.writer = nil
}
}
}
/**
A method that exports a video 📹 file path to the Photo Library 📲💾.
@@ -675,8 +723,8 @@ private var renderer: RenderAR!
Recommended to use in the `UIViewController`'s method `func viewWillAppear(_ animated: Bool)`
- parameter configuration: An object that defines motion and scene tracking behaviors for the session.
*/
@objc public func prepare(_ configuration: ARConfiguration? = nil) {
ARcontentMode = contentMode
@objc func prepare(_ configuration: ARConfiguration? = nil) {
renderer.ARcontentMode = contentMode
onlyRenderWhileRec = onlyRenderWhileRecording
if let view = view as? ARSCNView {
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
@@ -700,7 +748,7 @@ private var renderer: RenderAR!
Recommended to use in the `UIViewController`'s method `func viewWillDisappear(_ animated: Bool)`.
*/
@objc public func rest() {
@objc func rest() {
ViewAR.orientation = UIInterfaceOrientationMask(ViewAR.orientations)
}
}
@@ -712,6 +760,8 @@ extension RecordAR {
//frame rendering
if self.onlyRenderWhileRec && !isRecording && !isRecordingGIF { return }
renderer.ARcontentMode = contentMode
guard let buffer = renderer.buffer else { return }
guard let rawBuffer = renderer.rawBuffer else {
logAR.message("ERROR:- An error occurred while rendering the camera's main buffers.")
@@ -721,10 +771,10 @@ extension RecordAR {
logAR.message("ERROR:- An error occurred while rendering the camera buffer.")
return
}
renderer.ARcontentMode = contentMode
self.writerQueue.sync {
var time: CMTime { return CMTimeMakeWithSeconds(renderer.time, 1000000) }
var time: CMTime { return CMTime(seconds: renderer.time, preferredTimescale: 1000000) }
self.renderAR?.frame(didRender: buffer, with: time, using: rawBuffer)
@@ -773,8 +823,10 @@ extension RecordAR {
self.adjustPausedTime = false
if self.pausedFrameTime != nil {
self.pausedFrameTime = self.adjustTime(current: time, resume: self.resumeFrameTime!, pause: self.pausedFrameTime!)
if self.pausedFrameTime != nil && self.resumeFrameTime != nil {
self.pausedFrameTime = self.adjustTime(current: time,
resume: self.resumeFrameTime!,
pause: self.pausedFrameTime!)
} else {
self.pausedFrameTime = time
}
+26
View File
@@ -0,0 +1,26 @@
//
// SSSS.swift
// ARVideoKit
//
// Created by Saul Moreno Abril on 01/05/2019.
// Copyright © 2019 Ahmed Fathit Bekhit. All rights reserved.
//
import Foundation
class WeakProxy: NSObject {
weak var target: NSObjectProtocol?
init(target: NSObjectProtocol) {
self.target = target
super.init()
}
override func responds(to aSelector: Selector!) -> Bool {
return (target?.responds(to: aSelector) ?? false) || super.responds(to: aSelector)
}
override func forwardingTarget(for aSelector: Selector!) -> Any? {
return target
}
}
@@ -429,7 +429,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ahmedbekhit.ARVideoKit-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -451,7 +451,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.ahmedbekhit.ARVideoKit-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -19,8 +19,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return ViewAR.orientation
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
return true
}
@@ -115,7 +115,7 @@ class SCNViewController: UIViewController, ARSCNViewDelegate, RenderARDelegate,
}else if status == .denied || status == .restricted || status == .notDetermined {
let errorView = UIAlertController(title: "😅", message: "Please allow access to the photo library in order to save this media file.", preferredStyle: .alert)
let settingsBtn = UIAlertAction(title: "Open Settings", style: .cancel) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
@@ -123,11 +123,11 @@ class SCNViewController: UIViewController, ARSCNViewDelegate, RenderARDelegate,
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
})
} else {
UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)
UIApplication.shared.openURL(URL(string:UIApplication.openSettingsURLString)!)
}
}
}
errorView.addAction(UIAlertAction(title: "Later", style: UIAlertActionStyle.default, handler: {
errorView.addAction(UIAlertAction(title: "Later", style: UIAlertAction.Style.default, handler: {
(UIAlertAction)in
}))
errorView.addAction(settingsBtn)
@@ -106,7 +106,7 @@ class SKViewController: UIViewController, ARSKViewDelegate, RenderARDelegate, Re
}else if status == .denied || status == .restricted || status == .notDetermined {
let errorView = UIAlertController(title: "😅", message: "Please allow access to the photo library in order to save this media file.", preferredStyle: .alert)
let settingsBtn = UIAlertAction(title: "Open Settings", style: .cancel) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
@@ -114,11 +114,11 @@ class SKViewController: UIViewController, ARSKViewDelegate, RenderARDelegate, Re
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
})
} else {
UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)
UIApplication.shared.openURL(URL(string:UIApplication.openSettingsURLString)!)
}
}
}
errorView.addAction(UIAlertAction(title: "Later", style: UIAlertActionStyle.default, handler: {
errorView.addAction(UIAlertAction(title: "Later", style: UIAlertAction.Style.default, handler: {
(UIAlertAction)in
}))
errorView.addAction(settingsBtn)
+17 -2
View File
@@ -1,8 +1,23 @@
// swift-tools-version:4.0
// swift-tools-version:5.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "ARVideoKit"
name: "ARVideoKit",
platforms: [
.iOS(.v11)
],
products: [
.library(
name: "ARVideoKit",
targets: ["ARVideoKit"]),
],
dependencies: [ ],
targets: [
.target(
name: "ARVideoKit",
dependencies: [],
path: "ARVideoKit")
]
)
+20 -11
View File
@@ -1,7 +1,13 @@
# Swift 4.0 Branch
> Use [swift_4_2](https://github.com/AFathi/ARVideoKit/tree/swift_4_2) branch for projects written in Swift 4.2
> [swift_4_2](https://github.com/AFathi/ARVideoKit/tree/swift_4_2) branch has been set as the default branch for `ARVideoKit` as of March 6th, 2019.
> Use [master](https://github.com/AFathi/ARVideoKit/tree/master) branch for projects written in Swift 4.0
## Sponsors
[**Chemical Wedding**](https://www.chemicalwedding.tv)
![Chemical Wedding](https://www.chemicalwedding.tv/imgs/general/logo-main.png)
## ARVideoKit
![intro image](http://www.ahmedbekhit.com/projects/repo-header-arvideokit.png)
@@ -21,6 +27,7 @@ In other words, you **NO LONGER** have to ~screen record~/~screenshot~ to captur
| [Implementation](#implementation) | Lists the [steps needed](#implementation) for Objective-C & Swift, [notes](#note), and [reference](#youre-all-set-) for more options |
| [Publishing to the App Store](#publishing-to-the-app-store) | Describes the steps **required** before submitting an application using `ARVideoKit` to the App Store. |
|[![Donate](https://www.paypalobjects.com/webstatic/en_US/i/btn/png/btn_donate_92x26.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ahmedfbekhit@gmail.com&item_name=Support+ARVideoKit+Developer&item_number=ARVideoKit+Framework+Donations&amount=0%2e00&currency_code=USD) | [Donations](#donate) will support me to keep maintaining `ARVideoKit` ❤️|
|[Sponsors](#sponsors) | Featuring the sponsors of this project |
| [Contributions](#contributions) | Describes how you can contribute to this project |
| [Apps using ARVideoKit](#apps-using-arvideokit) | A list of published applications using ARVideoKit |
| [License](#license) | Describes `ARVideoKit` license |
@@ -55,9 +62,10 @@ To try the example project, simply clone this repository and open the `Examples`
## Installation
### Cocoapods
1. Add this line to your project's `Podfile`
1. Add this line to your project's `Podfile` (for Swift 5.0)
```
pod 'ARVideoKit'
pod 'ARVideoKit', '~> 1.5.51'
```
2. Install the pod
```
@@ -74,14 +82,12 @@ github "AFathi/ARVideoKit" ~> 1.31
$ carthage update
```
### ~Manual~ _Deprecated_
**If you're currently using the `.framework` file, I recommend to re-install the framework using one of the other installation options.**
### Swift Package Manager (available Xcode 11.2 and forward)
1. In Xcode, select File > Swift Packages > Add Package Dependency.
2. Follow the prompts using the URL for this repository.
~Drag the `ARVideoKit.framework` file as an embedded binary of your project targets. `ARVideoKit.framework` can be found in the `/Framework Build/` folder of this repository.~
![Tutorial](http://www.ahmedbekhit.com/arvideokit_install_new.gif)
### Manual (Supported)
### Manual
Drag `ARVideoKit.xcodeproj` into your project and click the **+** button in the embedded binaries section of your project's target.
![example embed framework](http://www.ahmedbekhit.com/embeddedBinary.png)
## Implementation
@@ -148,7 +154,7 @@ To do so, follow those steps:
Donations will support me to keep maintining **ARVideoKit Framework** ❤️
[![Donate](https://www.paypalobjects.com/webstatic/en_US/i/btn/png/btn_donate_92x26.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ahmedfbekhit@gmail.com&item_name=Support+ARVideoKit+Developer&item_number=ARVideoKit+Framework+Donations&amount=0%2e00&currency_code=USD)
## Contributions
If you have an idea for a new **ARVideoKit** feature/functionality and want to add it to this repository, feel free to fork the project and create a pull request!
@@ -157,7 +163,10 @@ Also, feel free to create an issue if you have any suggestions or need any help
## Apps using ARVideoKit
| App | Description |
| ------------------ |:------------------:|
| [Pathica](https://apps.apple.com/us/app/pathica/id1564780182) | The first proof of the theory of "six degrees of separation" which is the idea that any two people on the planet can be connected through five or fewer individuals. |
| [Our SolAR](https://itunes.apple.com/app/id1267675913) | An app that allows you to see our Solar System anywhere at all! |
| [In The Walls](https://apps.apple.com/us/app/id1522257130) | Uses real time face tracking and AR to put your face in any real world wall! |
| [ScribScrab](https://apps.apple.com/in/app/scribscrab/id1339432955) | ScribScrab is a tool for creativity. Youre only limited to your imagination and your battery life. |
_Feel free to add your application to this list!_
## License