{"id":15132888,"url":"https://github.com/piemonte/pbjvision","last_synced_at":"2025-09-29T02:31:53.116Z","repository":{"id":9673087,"uuid":"11615523","full_name":"piemonte/PBJVision","owner":"piemonte","description":"📸 iOS Media Capture – features touch-to-record video, slow motion, and photography","archived":true,"fork":false,"pushed_at":"2021-03-03T06:14:45.000Z","size":2216,"stargazers_count":1925,"open_issues_count":0,"forks_count":321,"subscribers_count":76,"default_branch":"main","last_synced_at":"2025-09-18T03:06:40.128Z","etag":null,"topics":["avfoundation","camera","capture","ios","media","objective-c","photography","recording","snapchat","video","vine"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piemonte.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-23T18:12:56.000Z","updated_at":"2025-09-11T14:19:18.000Z","dependencies_parsed_at":"2022-08-07T05:01:13.052Z","dependency_job_id":null,"html_url":"https://github.com/piemonte/PBJVision","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/piemonte/PBJVision","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piemonte%2FPBJVision","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piemonte%2FPBJVision/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piemonte%2FPBJVision/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piemonte%2FPBJVision/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piemonte","download_url":"https://codeload.github.com/piemonte/PBJVision/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piemonte%2FPBJVision/sbom","scorecard":{"id":733256,"data":{"date":"2025-08-11","repo":{"name":"github.com/piemonte/PBJVision","commit":"5218c66b11bb1758beeb4aca00b2d3dcde083702"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":1,"reason":"Found 3/25 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T15:01:50.329Z","repository_id":9673087,"created_at":"2025-08-22T15:01:50.329Z","updated_at":"2025-08-22T15:01:50.329Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276058109,"owners_count":25577866,"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","status":"online","status_checked_at":"2025-09-20T02:00:10.207Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["avfoundation","camera","capture","ios","media","objective-c","photography","recording","snapchat","video","vine"],"created_at":"2024-09-26T04:41:20.622Z","updated_at":"2025-09-29T02:31:52.752Z","avatar_url":"https://github.com/piemonte.png","language":"Objective-C","readme":"![PBJVision](https://raw.githubusercontent.com/piemonte/PBJVision/master/pbj.gif)\n\n## PBJVision\n\n`PBJVision` is a camera library for iOS that enables easy integration of special capture features and camera interface customizations in your iOS app. [Next Level](https://github.com/NextLevel/NextLevel) is the Swift counterpart.\n\n[![Build Status](https://api.travis-ci.org/piemonte/PBJVision.svg?branch=master)](https://travis-ci.org/piemonte/PBJVision)\n[![Pod Version](https://img.shields.io/cocoapods/v/PBJVision.svg?style=flat)](http://cocoadocs.org/docsets/PBJVision/)\n[![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://github.com/NextLevel/NextLevel/blob/master/LICENSE)\n\n- Looking for a Swift version? Check out [Next Level](https://github.com/NextLevel/NextLevel).\n- Looking for a video player? Check out [Player (Swift)](https://github.com/piemonte/player) and [PBJVideoPlayer (obj-c)](https://github.com/piemonte/PBJVideoPlayer).\n\n### Features\n- [x] touch-to-record video capture\n- [x] slow motion capture (120 fps on [supported hardware](https://www.apple.com/iphone/compare/))\n- [x] photo capture\n- [x] customizable user interface and gestural interactions\n- [x] ghosting (onion skinning) of last recorded segment\n- [x] flash/torch support\n- [x] white balance, focus, and exposure adjustment support\n- [x] mirroring support\n\nCapture is also possible without having to use the touch-to-record gesture interaction as the sample project provides.\n\n### About\n\nThis library was originally created at [DIY](https://diy.org/) as a fun means for kids to author video and share their [skills](https://diy.org//skills). The touch-to-record interaction was pioneered by [Vine](https://vine.co/) and [Instagram](https://instagram.com/).\n\nThanks to everyone who has contributed and helped make this a fun project and community.\n\n## Quick Start\n\n`PBJVision` is available and recommended for installation using the dependency manager [CocoaPods](https://cocoapods.org/). \n\nTo integrate, just add the following line to your `Podfile`:\n\n```ruby\npod 'PBJVision'\n```\n\n## Usage\n\nImport the header.\n\n```objective-c\n#import \"PBJVision.h\"\n```\n\nSetup the camera preview using `[[PBJVision sharedInstance] previewLayer]`.\n\n```objective-c\n    // preview and AV layer\n    _previewView = [[UIView alloc] initWithFrame:CGRectZero];\n    _previewView.backgroundColor = [UIColor blackColor];\n    CGRect previewFrame = CGRectMake(0, 60.0f, CGRectGetWidth(self.view.frame), CGRectGetWidth(self.view.frame));\n    _previewView.frame = previewFrame;\n    _previewLayer = [[PBJVision sharedInstance] previewLayer];\n    _previewLayer.frame = _previewView.bounds;\n    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;\n    [_previewView.layer addSublayer:_previewLayer];\n```\n\nIf your view controller is managed by a Storyboard, keep the previewLayer updated for device sizes\n\n```objective-c\n- (void)viewDidLayoutSubviews\n{\n    _previewLayer.frame = _previewView.bounds;\n}\n```\n\nSetup and configure the `PBJVision` controller, then start the camera preview.\n\n```objective-c\n- (void)_setup\n{\n    _longPressGestureRecognizer.enabled = YES;\n\n    PBJVision *vision = [PBJVision sharedInstance];\n    vision.delegate = self;\n    vision.cameraMode = PBJCameraModeVideo;\n    vision.cameraOrientation = PBJCameraOrientationPortrait;\n    vision.focusMode = PBJFocusModeContinuousAutoFocus;\n    vision.outputFormat = PBJOutputFormatSquare;\n\n    [vision startPreview];\n}\n```\n\nStart/pause/resume recording.\n\n```objective-c\n- (void)_handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer\n{\n    switch (gestureRecognizer.state) {\n      case UIGestureRecognizerStateBegan:\n        {\n            if (!_recording)\n                [[PBJVision sharedInstance] startVideoCapture];\n            else\n                [[PBJVision sharedInstance] resumeVideoCapture];\n            break;\n        }\n      case UIGestureRecognizerStateEnded:\n      case UIGestureRecognizerStateCancelled:\n      case UIGestureRecognizerStateFailed:\n        {\n            [[PBJVision sharedInstance] pauseVideoCapture];\n            break;\n        }\n      default:\n        break;\n    }\n}\n```\n\nEnd recording.\n\n```objective-c\n    [[PBJVision sharedInstance] endVideoCapture];\n```\n\nHandle the final video output or error accordingly.\n\n```objective-c\n- (void)vision:(PBJVision *)vision capturedVideo:(NSDictionary *)videoDict error:(NSError *)error\n{   \n    if (error \u0026\u0026 [error.domain isEqual:PBJVisionErrorDomain] \u0026\u0026 error.code == PBJVisionErrorCancelled) {\n        NSLog(@\"recording session cancelled\");\n        return;\n    } else if (error) {\n        NSLog(@\"encounted an error in video capture (%@)\", error);\n        return;\n    }\n\n    _currentVideo = videoDict;\n    \n    NSString *videoPath = [_currentVideo  objectForKey:PBJVisionVideoPathKey];\n    [_assetLibrary writeVideoAtPathToSavedPhotosAlbum:[NSURL URLWithString:videoPath] completionBlock:^(NSURL *assetURL, NSError *error1) {\n        UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @\"Video Saved!\" message: @\"Saved to the camera roll.\"\n                                                       delegate:self\n                                              cancelButtonTitle:nil\n                                              otherButtonTitles:@\"OK\", nil];\n        [alert show];\n    }];\n}\n```\n\nTo specify an automatic end capture maximum duration, set the following property on the 'PBJVision' controller.\n\n```objective-c\n    [[PBJVision sharedInstance] setMaximumCaptureDuration:CMTimeMakeWithSeconds(5, 600)]; // ~ 5 seconds\n```\n\nTo adjust the video quality and compression bit rate, modify the following properties on the `PBJVision` controller.\n\n```objective-c\n    @property (nonatomic, copy) NSString *captureSessionPreset;\n\n    @property (nonatomic) CGFloat videoBitRate;\n    @property (nonatomic) NSInteger audioBitRate;\n    @property (nonatomic) NSDictionary *additionalCompressionProperties;\n```\n\n## Community\n\nContributions and discussions are welcome!\n\n### Project\n\n- Need help? Use [Stack Overflow](http://stackoverflow.com/questions/tagged/pbjvision) with the tag 'pbjvision'.\n- Questions? Use [Stack Overflow](http://stackoverflow.com/questions/tagged/pbjvision) with the tag 'pbjvision'.\n- Found a bug? Open an [issue](https://github.com/piemonte/PBJVision/issues).\n- Feature idea? Open an [issue](https://github.com/piemonte/PBJVision/issues).\n- Want to contribute? Submit a [pull request](https://github.com/piemonte/PBJVision/blob/master/CONTRIBUTING.md).\n\n### Related Projects\n\n* [Next Level](https://github.com/NextLevel/NextLevel/), rad media capture in Swift\n* [Player](https://github.com/piemonte/player), a simple iOS video player in Swift\n* [PBJVideoPlayer](https://github.com/piemonte/PBJVideoPlayer), a simple iOS video player in Objective-C\n\n## Resources\n\n* [iOS Device Camera Summary](https://developer.apple.com/library/prerelease/content/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Cameras/Cameras.html)\n* [AV Foundation Programming Guide](https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html)\n* [AV Foundation Framework Reference](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVFoundationFramework/)\n* [objc.io Camera and Photos](https://www.objc.io/issues/21-camera-and-photos/)\n* [objc.io Video](https://www.objc.io/issues/23-video/)\n* [Cameras, ecommerce and machine learning](http://ben-evans.com/benedictevans/2016/11/20/ku6omictaredoge4cao9cytspbz4jt)\n\n## License\n\nPBJVision is available under the MIT license, see the [LICENSE](https://github.com/piemonte/PBJVision/blob/master/LICENSE) file for more information.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiemonte%2Fpbjvision","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiemonte%2Fpbjvision","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiemonte%2Fpbjvision/lists"}