{"id":13907901,"url":"https://github.com/GottaYotta/PixelSDK","last_synced_at":"2025-07-18T06:32:08.676Z","repository":{"id":37572419,"uuid":"237120209","full_name":"GottaYotta/PixelSDK","owner":"GottaYotta","description":"The modern photo and video editor for your iPhone / iPad app. A fully customizable image \u0026 video editing iOS Swift framework.","archived":false,"fork":false,"pushed_at":"2024-07-23T09:13:36.000Z","size":837774,"stargazers_count":519,"open_issues_count":5,"forks_count":49,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-11-09T19:43:18.317Z","etag":null,"topics":["adjustments","camera","composing","correction","crop","cropping","drafts","encoder","filter","filters","ios","rotate","stitching","swift","transcode","transcoder","transform","trim","trimming","xcode"],"latest_commit_sha":null,"homepage":"https://www.pixelsdk.com","language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GottaYotta.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-30T01:54:13.000Z","updated_at":"2024-11-06T13:56:54.000Z","dependencies_parsed_at":"2024-06-19T05:30:38.852Z","dependency_job_id":null,"html_url":"https://github.com/GottaYotta/PixelSDK","commit_stats":{"total_commits":98,"total_committers":3,"mean_commits":"32.666666666666664","dds":0.05102040816326525,"last_synced_commit":"004d707dec432d5108c9e06d15c869e45d67497b"},"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GottaYotta%2FPixelSDK","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GottaYotta%2FPixelSDK/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GottaYotta%2FPixelSDK/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GottaYotta%2FPixelSDK/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GottaYotta","download_url":"https://codeload.github.com/GottaYotta/PixelSDK/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226361610,"owners_count":17612928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adjustments","camera","composing","correction","crop","cropping","drafts","encoder","filter","filters","ios","rotate","stitching","swift","transcode","transcoder","transform","trim","trimming","xcode"],"created_at":"2024-08-06T23:02:17.198Z","updated_at":"2025-07-18T06:32:08.664Z","avatar_url":"https://github.com/GottaYotta.png","language":"Swift","funding_links":[],"categories":["HarmonyOS"],"sub_categories":["Windows Manager"],"readme":"\u003e [!CAUTION]\n\u003e Pixel SDK will sunset on February 3, 2025. We are not accepting new customers at this time. Thank you for being part of our journey.\n\n# Pixel SDK\nPixel SDK is a photo and video editing framework written in Swift.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/library_1_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_1_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_7_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_3_border.gifx\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\n\u003c/p\u003e\n\n- [Features](#features)\n- [Getting Started](#getting-started)\n    * [Swift Package Manager](#swift-package-manager-recommended)\n    * [CocoaPods](#cocoapods)\n- [Restrict the SDK](#restrict-the-sdk)\n    * [Images Only](#images-only)\n    * [Videos Only](#videos-only)\n    * [Square Content Only](#square-content-only)\n    * [Portrait Content Only](#portrait-content-only)\n    * [Library Only](#library-only)\n    * [Camera Only](#camera-only)\n- [Present the Editor](#present-the-editor)\n- [Programmatic Editing](#programmatic-editing)\n- [Export Media](#export-media)\n    * [Image Exports](#image-exports)\n    * [Video Exports](#video-exports)\n    * [Encoding Settings](#encoding-settings)\n- [Transcode Media](#transcode-media)\n- [Write Custom Filters](#write-custom-filters)\n- [Customize Colors](#customize-colors)\n- [License](#license)\n\n## Features\n✅ Fully Customizable Filters with 40+ Included Filters and Visual Effects\n\n✅ Vine Style Video Camera\n\n✅ Auto-Saving Drafts\n\n✅ Video Segment Composing, Trimming, Scaling, and Re-ordering\n\n✅ Photo and Video Adjustments (Brightness, Vibrance, Saturation, Contrast, Exposure, Hue, Warmth, Sharpness, Gamma, Highlights, Shadows, Vignette)\n\n✅ Cropping, Rotation, and Horizontal/Vertical Perspective Correction\n\n✅ Adjust Individual Video Segments and Whole Video Composition\n\n✅ Programmatic and Visual Editing\n\n✅ Press and Hold Photo/Video to See Original While Editing\n\n✅ Landscape, Portrait and or Square Content Support\n\n✅ Swipe for Realtime Camera Filters\n\n✅ Top Down Photo Mode\n\n✅ Camera Brightness and Tap to Focus\n\n✅ Share Directly to Facebook, Instagram or Twitter.\n\n✅ Custom Colors and Dark Mode Support.\n\n✅ Localized in 40+ [Languages](https://github.com/GottaYotta/PixelSDK/blob/master/LANGUAGES.md) and Dynamic Type Accessibility Support.\n\n✅ Import Photos and Videos from DSLR Camera. Lightning to USB Cable Required.\n\n✅ Direct GPU Access with Metal and [GPUImage3](https://github.com/BradLarson/GPUImage3).\n\n✅ Transcode Video Files with Codecs, Filters, Trimming and more.\n\n✅ RAW Images and 60fps 4K UHD Video Support. HEVC Support.\n\n✅ Full [Documentation](https://www.pixelsdk.com/docs/latest/).\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/camera_1_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_4_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_5_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_6_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\n\u003c/p\u003e\n\n## Requirements\n- iPhone or iPad\n- iOS 11+\n- Xcode 11.4+\n\n## Getting Started\n\n\u003e [!CAUTION]\n\u003e Pixel SDK will sunset on February 3, 2025. We are not accepting new customers at this time. Thank you for being part of our journey.\n\n**Note:** Extensive sample code can be found in the [Xcode sample project](https://github.com/GottaYotta/PixelSDK/archive/master.zip).\n\u003cgetting-started-supplement\u003e\n\n### Swift Package Manager (Recommended)\n\n[Swift Package Manager](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app) is a dependency manager built into Xcode. To integrate PixelSDK into your Xcode project\u0026nbsp;using\u0026nbsp;Swift Package Manager, first verify you have the latest version of Xcode installed.\n\nIn the Xcode menu bar select File \u003e Add Packages and enter the following repository URL into the search bar:\n\n```\nhttps://github.com/GottaYotta/PixelSDK.git\n```\n\nFor Dependency Rule select `Branch` and `master`. Then press Add Package.\n\nNote: We do not recommend setting the Dependency Rule to a major version because it will prevent you from receiving critical bug fixes in the future.\n\n### CocoaPods\n\n[CocoaPods](https://cocoapods.org/) is a dependency manager for iOS projects. To integrate PixelSDK into your Xcode project\u0026nbsp;using\u0026nbsp;CocoaPods, first verify you have at least Xcode 11.4 or greater installed.\n\nThen, ensure you have the latest version of CocoaPods installed by running the following command:\n\n```\n$ sudo gem install cocoapods\n```\n\nSpecify PixelSDK in your `Podfile`:\n\n```\npod 'PixelSDK'\n```\n\nRun the following command from within your project directory:\n\n```\n$ pod install\n```\n\n### Setup\n\nInclude the following lines in your application `Info.plist`:\n\n```xml\n\u003ckey\u003eNSPhotoLibraryUsageDescription\u003c/key\u003e\n\u003cstring\u003ePhoto access is needed so you can select photos from your library.\u003c/string\u003e\n\u003ckey\u003eNSMicrophoneUsageDescription\u003c/key\u003e\n\u003cstring\u003eMicrophone access is needed so you can record video with sound.\u003c/string\u003e\n\u003ckey\u003eNSCameraUsageDescription\u003c/key\u003e\n\u003cstring\u003eCamera access is needed so you can take photos.\u003c/string\u003e\n```\nPresent the SDK in response to a user action, for example, clicking a button. The default primary filters and adjustment filters will be used. The SDK will support both photo and video of any dimension with access to both the camera and library.\n\n```swift\nimport PixelSDK\n```\n```swift\nlet container = ContainerController()\ncontainer.editControllerDelegate = self\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\n\nself.present(nav, animated: true, completion: nil)\n```\n\nAlso implement its delegate method. This delegate method will be called when the Next button in the EditController is pressed. In response you should either dismiss the UINavigationController or push a new controller on. The below example pushes a blank controller on. Then use the provided  `session` parameter to [export your photo or video](#export-media) at your own convenience.\n```swift\nextension ViewController: EditControllerDelegate {\n\n    func editController(_ editController: EditController, didFinishEditing session: Session) {\n        let controller = UIViewController()\n\n        editController.navigationController?.pushViewController(controller, animated: true)\n    }\n}\n```\n\n[Generate an API key](https://www.pixelsdk.com/dashboard/api-keys/) and specify it in your  `application(_, didFinishLaunchingWithOptions:)` of your App Delegate. \u003cspan style=\"display: none;\"\u003eThe following [pricing options](https://www.pixelsdk.com/#pricing) are available for your API key.\u003c/span\u003e Without an API key, image and video exports will include a watermark. Keep your API key private.\n\n```swift\nimport PixelSDK\n\nfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -\u003e Bool {\n\n    PixelSDK.setup(\"YOUR API KEY\")\n\n    return true\n}\n```\n\nOptionally, specify a maximum video duration. The default maximum video duration is 80 seconds.\n\n ```swift\n // Set the maximum video duration to 3 minutes.\n PixelSDK.shared.maxVideoDuration = 60*3\n ```\n \n That's it! You now have full access to the SDK.\n\n## Restrict the SDK\n### Images Only\n\nThe below example presents the SDK with only support for images. The user will have access to both the library and camera.\n```swift\n// Show only the library and photo camera modes in the tab bar\nlet container = ContainerController(modes: [.library, .photo])\ncontainer.editControllerDelegate = self\n\n// Include only images from the users photo library\ncontainer.libraryController.fetchPredicate = NSPredicate(format: \"mediaType == %d\", PHAssetMediaType.image.rawValue)\n// Include only images from the users drafts\ncontainer.libraryController.draftMediaTypes = [.image]\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\n\nself.present(nav, animated: true, completion: nil)\n```\n\n### Videos Only\n\nThe below example presents the SDK with only support for videos. The user will have access to both the library and camera.\n```swift\n// Show only the library and video camera modes in the tab bar\nlet container = ContainerController(modes: [.library, .video])\ncontainer.editControllerDelegate = self\n\n// Include only videos from the users photo library\ncontainer.libraryController.fetchPredicate = NSPredicate(format: \"mediaType == %d\", PHAssetMediaType.video.rawValue)\n// Include only videos from the users drafts\ncontainer.libraryController.draftMediaTypes = [.video]\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\n\nself.present(nav, animated: true, completion: nil)\n```\n\n### Square Content Only\n\nThe below example presents the SDK with only support for creating square photos and videos. The user will have access to both the library and camera.\n```swift\nlet container = ContainerController()\ncontainer.editControllerDelegate = self\n\n// Only allow square content from the library cropper\ncontainer.libraryController.previewCropController.aspectRatio = CGSize(width: 1, height: 1)\n// Only allow square content from the camera controller\ncontainer.cameraController.aspectRatio = CGSize(width: 1, height: 1)\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\nself.present(nav, animated: true, completion: nil)\n```\n\n### Portrait Content Only\n\nThe below example presents the SDK with only support for creating portrait photos and videos. The user will have access to both the library and camera.\n```swift\nlet container = ContainerController()\ncontainer.editControllerDelegate = self\n\n// Only allow portrait content from the library cropper\ncontainer.libraryController.previewCropController.aspectRatio = CGSize(width: 3, height: 4)\n// Only allow portrait content from the camera controller\ncontainer.cameraController.aspectRatio = CGSize(width: 3, height: 4)\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\nself.present(nav, animated: true, completion: nil)\n```\n\n### Library Only\n\nThe below example presents the SDK with only support for the library.\n```swift\nlet container = ContainerController(mode: .library)\ncontainer.editControllerDelegate = self\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\nself.present(nav, animated: true, completion: nil)\n```\n\n### Camera Only\n\nThe below example presents the SDK with only support for the video camera.\n```swift\nlet container = ContainerController(mode: .video)\ncontainer.editControllerDelegate = self\n\nlet nav = UINavigationController(rootViewController: container)\nnav.modalPresentationStyle = .fullScreen\nself.present(nav, animated: true, completion: nil)\n```\n\n## Present the Editor\n\nThe camera and library can be bypassed by presenting the [EditController](https://www.pixelsdk.com/docs/latest/Classes/EditController.html) with your own media.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_1_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_2_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_4_border.jpg\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\u0026nbsp;\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/screenshots/sdk/edit_3_border.gifx\" alt=\"Screenshot\" width=\"23.6%\" height=\"auto\" class=\"docs-screenshot\"/\u003e\n\u003c/p\u003e\n\n### Images\nThe below example presents the EditController with an image named \"test_image\" and sets the initial primary filter to [Wilshire](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterWilshire.html).\n\n```swift\nlet image = UIImage(named: \"test_image\")!\n\nlet session = Session(image: image)\nsession.image!.primaryFilter = SessionFilterWilshire()\n\nlet editController = EditController(session: session)\neditController.delegate = self\n\nlet nav = UINavigationController(rootViewController: editController)\nnav.modalPresentationStyle = .fullScreen\nself.present(nav, animated: true, completion: nil)\n```\n### Videos\nThe below example presents the EditController with two AVAssets named \"test.mov\" and \"test2.mp4\" and sets the initial primary filter to [Sepulveda](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterSepulveda.html). These two assets will become segments of the video in their respective order.\n\nYou can also manually pass a renderSize into the Session initializer. For more information see [Session](https://www.pixelsdk.com/docs/latest/Classes/Session.html) documentation.\n\n```swift\nlet asset1 = AVAsset(url: Bundle.main.url(forResource: \"test\", withExtension: \"mov\")!)\nlet asset2 = AVAsset(url: Bundle.main.url(forResource: \"test2\", withExtension: \"mp4\")!)\n\nlet _ = Session(assets: [asset1, asset2], sessionReady: { (session, error) in\n    guard let session = session,\n        let video = session.video else {\n        print(\"Unable to create session: \\(error!)\")\n        return\n    }\n    \n    // Set the initial primary filter to Sepulveda\n    video.primaryFilter = SessionFilterSepulveda()\n\n    let editController = EditController(session: session)\n    editController.delegate = self\n\n    let nav = UINavigationController(rootViewController: editController)\n    nav.modalPresentationStyle = .fullScreen\n    self.present(nav, animated: true, completion: nil)\n})\n```\n\n## Programmatic Editing\nImages and videos can also be edited programmatically instead of visually. For more information see [Session](https://www.pixelsdk.com/docs/latest/Classes/Session.html) documentation.\n\nFor example, setting the primaryFilter of an image to [Wilshire](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterWilshire.html):\n```swift\nsession.image!.primaryFilter = SessionFilterWilshire()\n```\nApplying a [Brightness](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterBrightness.html) filter to an image:\n```swift\nlet brightnessFilter = SessionFilterBrightness()\nbrightnessFilter.normalizedIntensity = 0.2\nsession.image!.filters = [brightnessFilter]\n```\nApplying a [Saturation](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterSaturation.html) filter to a whole video:\n```swift\nlet saturationFilter = SessionFilterSaturation()\nsaturationFilter.normalizedIntensity = 0.3\nsession.video!.filters = [saturationFilter]\n```\nApplying a [Contrast](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterContrast.html) filter to the first segment of a video:\n```swift\nlet segment = session.video!.videoSegments.first!\nlet contrastFilter = SessionFilterContrast()\ncontrastFilter.normalizedIntensity = 0.2\nsegment.filters = [contrastFilter]\n```\nTrimming a segment so it [starts](https://www.pixelsdk.com/docs/latest/Classes/SessionVideoSegment.html#/c:@M@PixelSDK@objc(cs)SessionVideoSegment(py)trimStartTime) at one second in, with a [duration](https://www.pixelsdk.com/docs/latest/Classes/SessionVideoSegment.html#/c:@M@PixelSDK@objc(cs)SessionVideoSegment(py)trimDuration) of two seconds:\n```swift\nlet segment = session.video!.videoSegments.first!\nsegment.trimStartTime = CMTime(seconds: 1, preferredTimescale: segment.duration.timescale)\nsegment.trimDuration = CMTime(seconds: 2, preferredTimescale: segment.duration.timescale)\n```\nRotating the first segment of a video with [preferredTransform](https://www.pixelsdk.com/docs/latest/Classes/SessionVideoSegment.html#/c:@M@PixelSDK@objc(cs)SessionVideoSegment(py)preferredTransform):\n```swift\nlet segment = session.video!.videoSegments.first!\nsegment.preferredTransform = .rotated180Degrees(segment.naturalSize)\nsegment.cropRect = segment.suggestedCropRect()\n```\nIncreasing the [speed](https://www.pixelsdk.com/docs/latest/Classes/SessionVideoSegment.html#/c:@M@PixelSDK@objc(cs)SessionVideoSegment(py)speedMultiplier) of the first segment of a video:\n```swift\nlet segment = session.video!.videoSegments.first!\nsegment.speedMultiplier = 2 // 2x faster\n```\n\nYou can present the [EditController](https://www.pixelsdk.com/docs/latest/Classes/EditController.html) after making programmatic edits and it will reflect your changes. Additionally, the [PreviewController](https://www.pixelsdk.com/docs/latest/Classes/PreviewController.html) will reflect all programmatic edits in real-time.\n\nAfter making programmatic edits to a session, you should manually call [`session.save()`](https://www.pixelsdk.com/docs/latest/Classes/Session.html#/c:@M@PixelSDK@objc(cs)Session(im)save).\n\n## Export Media\n\n### Image Exports\n\nThe below example demonstrates exporting to a UIImage:\n```swift\nif let image = session.image {\n    ImageExporter.shared.export(image: image, completion: { (error, uiImage) in\n        if let error = error {\n            print(\"Unable to export image: \\(error)\")\n            return\n        }\n\n        print(\"Finished image export with UIImage: \\(uiImage!)\")\n    })\n}\n```\nIn addition to exporting as a UIImage, the exported image is saved to file as a JPEG at the [`image.exportedImageURL`](https://www.pixelsdk.com/docs/latest/Classes/SessionImage.html#/c:@M@PixelSDK@objc(cs)SessionImage(py)exportedImageURL) variable. After the export has completed, you may use, move or copy this file. Once you are finished with the file, you should call [`session.destroy()`](https://www.pixelsdk.com/docs/latest/Classes/Session.html#/c:@M@PixelSDK@objc(cs)Session(im)destroy) in order to remove the image from the users drafts and delete its associated files.\n\n### Video Exports\n\nThe below example demonstrates exporting a video to an mp4 file:\n```swift\nif let video = session.video {\n    VideoExporter.shared.export(video: video, progress: { progress in\n        print(\"Export progress: \\(progress)\")\n    }, completion: { error in\n        if let error = error {\n            print(\"Unable to export video: \\(error)\")\n            return\n        }\n\n        print(\"Finished video export at URL: \\(video.exportedVideoURL)\")\n    })\n}\n```\nAfter the export has completed, you should use, move or copy the file found at the [`video.exportedVideoURL`](https://www.pixelsdk.com/docs/latest/Classes/SessionVideo.html#/c:@M@PixelSDK@objc(cs)SessionVideo(py)exportedVideoURL). Once you are finished with the file, you should call [`session.destroy()`](https://www.pixelsdk.com/docs/latest/Classes/Session.html#/c:@M@PixelSDK@objc(cs)Session(im)destroy) in order to remove the video from the users drafts and delete its associated files.\n\nFrame rate can be customized by setting the [`video.frameDuration`](https://www.pixelsdk.com/docs/latest/Classes/SessionVideo.html#/c:@M@PixelSDK@objc(cs)SessionVideo(py)frameDuration) variable before exporting the video.\n\nYou can also change  [`video.renderSize`](https://www.pixelsdk.com/docs/latest/Classes/SessionVideo.html#/c:@M@PixelSDK@objc(cs)SessionVideo(py)renderSize) but we recommend you instead set the PreviewCropController aspectRatio and CameraController aspectRatio. See the [square content example](#square-content-only). These properties allow you to preserve video quality by delaying any upscaling or downscaling until a later point in your video processing logic. If you plan on converting your video to HLS on a server that encoder should handle any upscaling or downscaling.\n\n### Encoding Settings\n\nIf you do not customize the video and audio encoding settings, the default settings will be an mp4 file with H.264 video encoding and stereo AAC audio encoding:\n```swift\nimport PixelSDK\nimport AVFoundation\n```\n```swift\nvar acl = AudioChannelLayout()\nmemset(\u0026acl, 0, MemoryLayout\u003cAudioChannelLayout\u003e.size)\nacl.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo\n\nlet audioEncodingSettings: [String: Any] = [\n    AVFormatIDKey: kAudioFormatMPEG4AAC,\n    AVNumberOfChannelsKey: 2,\n    AVSampleRateKey: AVAudioSession.sharedInstance().sampleRate,\n    AVChannelLayoutKey: NSData(bytes:\u0026acl, length:MemoryLayout\u003cAudioChannelLayout\u003e.size),\n    AVEncoderBitRateKey: 96000\n]\n\nlet videoEncodingSettings: [String: Any] = [\n    AVVideoCompressionPropertiesKey: [\n        AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel,\n        AVVideoH264EntropyModeKey: AVVideoH264EntropyModeCABAC],\n    AVVideoCodecKey: AVVideoCodecType.h264\n]\n\nVideoExporter.shared.export(video: session.video!,\n                            fileType: .mp4,\n                            videoEncodingSettings: videoEncodingSettings,\n                            audioEncodingSettings: audioEncodingSettings,\n                            progress: nil,\n                            completion: { error in\n})\n```\nThere are many combinations of encoding settings you can provide. They must conform to the specifications set forth in AVFoundations [AVVideoSettings.h](https://github.com/GottaYotta/PixelSDK/blob/master/.github/headers/AVVideoSettings.h) and [AVAudioSettings.h](https://github.com/GottaYotta/PixelSDK/blob/master/.github/headers/AVAudioSettings.h) headers. There is also a list of available [codecs](https://developer.apple.com/documentation/avfoundation/avvideocodectype). Keep in mind each codec may have different requirements for the settings you provide.\n\nBelow is an example of HEVC video encoding settings:\n```swift\nimport PixelSDK\nimport AVFoundation\nimport VideoToolbox\n```\n```swift\nlet videoEncodingSettings: [String: Any] = [\n    AVVideoCompressionPropertiesKey: [\n        AVVideoProfileLevelKey: kVTProfileLevel_HEVC_Main_AutoLevel],\n    AVVideoCodecKey: AVVideoCodecType.hevc\n]\n```\n\n## Transcode Media\n\nMedia files can also be transcoded without using UI.\n\nThis example stitches two AVAssets named \"test.mov\" and \"test2.mp4\" into a single 60 fps mp4 file with H.264 video encoding and stereo AAC audio encoding. \n\nAdditionally, a [Saturation](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterSaturation.html) filter is applied to the first segment (asset), and a [Pixellate](https://www.pixelsdk.com/docs/latest/Classes/SessionFilterPixellate.html) filter is applied to the second segment.\n\n```swift\nimport PixelSDK\nimport AVFoundation\n```\n```swift\nlet asset1 = AVAsset(url: Bundle.main.url(forResource: \"test\", withExtension: \"mov\")!)\nlet asset2 = AVAsset(url: Bundle.main.url(forResource: \"test2\", withExtension: \"mp4\")!)\n\nlet _ = Session(assets: [asset1, asset2], sessionReady: { (session, error) in\n    guard let session = session,\n        let video = session.video else {\n        print(\"Unable to create session: \\(error!)\")\n        return\n    }\n    \n    // Mark the session as transient so it does not persist on disk/appear in the users drafts\n    session.isTransient = true\n    \n    // Set the video frame rate to 60 fps\n    video.frameDuration = CMTime(value: 1, timescale: 60)\n    \n    // Apply a Saturation filter to the first segment\n    let saturationFilter = SessionFilterSaturation()\n    saturationFilter.normalizedIntensity = 0.2\n    video.videoSegments[0].filters = [saturationFilter]\n    \n    // Apply a Pixellate filter to the second segment\n    let pixellateFilter = SessionFilterPixellate()\n    video.videoSegments[1].filters = [pixellateFilter]\n    \n    // Write to an MP4 file with H.264 video encoding and stereo AAC audio encoding\n    \n    var acl = AudioChannelLayout()\n    memset(\u0026acl, 0, MemoryLayout\u003cAudioChannelLayout\u003e.size)\n    acl.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo\n    \n    let audioEncodingSettings: [String: Any] = [\n        AVFormatIDKey: kAudioFormatMPEG4AAC,\n        AVNumberOfChannelsKey: 2,\n        AVSampleRateKey: AVAudioSession.sharedInstance().sampleRate,\n        AVChannelLayoutKey: NSData(bytes:\u0026acl, length:MemoryLayout\u003cAudioChannelLayout\u003e.size),\n        AVEncoderBitRateKey: 96000\n    ]\n    \n    let videoEncodingSettings: [String: Any] = [\n        AVVideoCompressionPropertiesKey: [\n            AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel,\n            AVVideoH264EntropyModeKey: AVVideoH264EntropyModeCABAC],\n        AVVideoCodecKey: AVVideoCodecType.h264\n    ]\n    \n    VideoExporter.shared.export(video: video,\n                                fileType: .mp4,\n                                videoEncodingSettings: videoEncodingSettings,\n                                audioEncodingSettings: audioEncodingSettings,\n                                progress: { (progress) in\n        print(\"Transcode progress: \\(progress)\")\n    }, completion: { (error) in\n        if let error = error {\n            print(\"Unable to transcode video: \\(error)\")\n            return\n        }\n        \n        print(\"Finished video transcode at URL: \\(video.exportedVideoURL)\")\n    })\n})\n```\n\nAfter your transcode has completed, you may move, copy or delete the file found at the [`video.exportedVideoURL`](https://www.pixelsdk.com/docs/latest/Classes/SessionVideo.html#/c:@M@PixelSDK@objc(cs)SessionVideo(py)exportedVideoURL).\n\nThere are many combinations of encoding settings you can provide. They must conform to the specifications set forth in AVFoundations [AVVideoSettings.h](https://github.com/GottaYotta/PixelSDK/blob/master/.github/headers/AVVideoSettings.h) and [AVAudioSettings.h](https://github.com/GottaYotta/PixelSDK/blob/master/.github/headers/AVAudioSettings.h) headers. There is also a list of available [codecs](https://developer.apple.com/documentation/avfoundation/avvideocodectype). Keep in mind each codec may have different requirements for the settings you provide.\n\n## Write Custom Filters\n\nEasily create your own filters with Photoshop, Lightroom presets, [3D LUT](https://en.wikipedia.org/wiki/3D_lookup_table) files, or your favorite photo editing application. An RGB lookup image is used to remap the colors in photos and videos. This is the same method used by common social media apps. For more complex filters you can chain [GPUImage3](https://github.com/BradLarson/GPUImage3) operations e.g. LookupFilter --\u003e Saturation --\u003e Sharpen.\n\n**Step 1:** Open any test image of your choosing in your photo editor.\n\n**Step 2:** Apply filters and changes to the test image until you are satisfied with the end result.\n\n**Step 3:** Download the original [lookup.png](https://github.com/GottaYotta/PixelSDK/blob/master/lookup.png) image from the repository and open it in your photo editor.\n\n**Step 4:** Apply the same changes you made on your test image to the lookup.png image and save the result to a new image lookup_example.png. Do not downsize the lookup image, reduce its quality or change its format. In some photo editors you can simply copy your adjustment layers from your test image to the lookup image.\n\n**Note:** Each pixel color must be independent of other pixels (e.g. sharpen will not work). If you need a more complex filter you can chain [GPUImage3](https://github.com/BradLarson/GPUImage3) operations e.g. LookupFilter --\u003e Sharpen --\u003e Saturation. An example of chaining operations is also included in the [Xcode sample project](https://github.com/GottaYotta/PixelSDK/archive/master.zip).\n\n**Step 5:** Use the below code to create your own SessionFilter subclass that utilizes a LookupFilter operation and your newly created lookup_example.png image. Be sure to add your lookup_example.png image to your Xcode project.\n\n```swift\nimport Foundation\nimport PixelSDK\nimport GPUImage\n\nclass SessionFilterExample: SessionFilter {\n    public required init() {\n        super.init()\n\n        self.commonInit()\n    }\n\n    public required init(from decoder: Decoder) throws {\n        try super.init(from: decoder)\n\n        self.commonInit()\n    }\n\n    public override func encode(to encoder: Encoder) throws {\n        try super.encode(to: encoder)\n    }\n\n    func commonInit() {\n        self.displayName = \"Example Filter\"\n        self.version = \"1.0\"\n        self.cameraThumbnailImage = UIImage(named: \"thumbnail_example.png\")\n\n        // self.normalizedIntensityDefault = 100 // This value gets computed\n        self.normalizedIntensityRange = (0, 100)\n        self.actualIntensityDefault = 1\n        self.actualIntensityRange = (0, 1)\n    }\n\n    override public func operation() -\u003e ImageProcessingOperation {\n        let lookupFilter = LookupFilter()\n\n        do {\n            lookupFilter.lookupImage = try PictureInput(image: UIImage(named: \"lookup_example.png\")!)\n        }\n        catch {\n            print(\"ERROR: Unable to create PictureInput \\(error)\")\n        }\n\n        return lookupFilter\n    }\n\n    override public func operationUpdateNeeded(_ op: ImageProcessingOperation) {\n        let op = op as! LookupFilter\n\n        op.intensity = Float(self.actualIntensity)\n    }\n}\n\n```\n\n**Step 6:** Include your custom filter in the list of available filters. Do this before you present the ContainerController or EditController.\n\n```swift\nPixelSDK.shared.primaryFilters = [\n    SessionFilterExample(), // Your custom filter\n    SessionFilterWilshire(),\n    SessionFilterMontana(),\n    SessionFilterSanVicente(),\n    SessionFilterMelrose(),\n    SessionFilterSepulveda(),\n    SessionFilterLaCienega(),\n    SessionFilterAbbotKinney(),\n    SessionFilterMulholland(),\n    SessionFilterSunset()\n]\n```\n\nThat's it! Enjoy your new custom filter.\n\n## Customize Colors\n\nCustomize UI colors in the framework by adding color assets to your asset catalog:\n\n\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/add_color_asset.jpg\" alt=\"Add Color Asset\" width=\"341\" height=\"auto\" class=\"docs-screenshot\"/\u003e\n\nThe color assets you add can have any of the following names:\n\n\u003ctable class=\"table table-bordered table-striped\" style=\"width:initial;\"\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/theme_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Theme Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/label_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Label Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/label_inactive_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Label Inactive Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/shadow_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Shadow Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/background_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Background Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/placeholder_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Placeholder Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/destructive_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Destructive Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/face_up_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Face Up Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/camera_overlay_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Camera Overlay Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/gray_1_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Gray 1 Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/gray_2_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Gray 2 Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/gray_3_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Gray 3 Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/gray_4_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Gray 4 Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/gray_5_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK Gray 5 Color\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\"https://www.cdn.pixelsdk.com/assets/img/docs/colors/white_color.svg\" /\u003e\u003c/td\u003e\u003ctd\u003ePixel SDK White Color\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\nThe [Xcode sample project](https://github.com/GottaYotta/PixelSDK/archive/master.zip) includes all available color assets with their default colors. If you do not provide color assets, the default colors will be used.\n\n## License\n\nMake sure you [generate an API key](https://www.pixelsdk.com/dashboard/api-keys/) before releasing your app. The following [pricing options](https://www.pixelsdk.com/#pricing) are available for your API key. Without an API key, image and video exports will include a watermark.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGottaYotta%2FPixelSDK","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGottaYotta%2FPixelSDK","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGottaYotta%2FPixelSDK/lists"}