iOS Swift - Not able to use video from Library - ios

I'm trying to obtain a video from the library in my swift app.
I'm using the following code snippet :
print("ChatDetailsController - imgaction - Vid from Lib pressed")
self.selection = "videoLib";
self.imgSelection = "vidFromLib"
self.imagePicker.sourceType = .PhotoLibrary
self.imagePicker.delegate = self
self.imagePicker.mediaTypes = ["public.movie"]
self.presentViewController(self.imagePicker!, animated: true, completion: nil)
Then in delegate method:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
if(selection == "videoLib")
{
if let videoURL = info[UIImagePickerControllerReferenceURL] as? NSURL
{
print("imagePickerController - reached for video - from Lib - \(videoURL)")
let videoData = NSData(contentsOfURL: videoURL)
}
}
}
When running the app, it shows the library and I can select a video, then it says compressing video.. but then the app crashes.
The Crash happens when I try to access the videoData Variable becuase it wasn't able to get the actual data since the path is an asset path and not a video path.
The Log shows something similar to this:
fatal error: unexpectedly found nil while unwrapping an Optional value
The print function shows:
imagePickerController - reached for video - from Lib - assets-library://asset/asset.MOV?id=7D3BFA00-A7CB-470C-8899-F82FCC2CBC54&ext=MOV
Also, right after choosing/selecting the video, a message similar to this is displayed in the console/log:
[Generic] video path /var/mobile/Media/PhotoData/CPLAssets/group419/A2901DD1-FDEF-423B-B4A3-E808B9AC45E1.MOV for PLPreviewImageAndDurationForVideoAtPath does not exist
Of course the file name changes on every run.
I'm able to get a video and images from the camera, and getting images from the library, I'm only having trouble with using the the video from the library. I would expect to see the video URL similar to :
/var/mobile/Containers/Data/Application/BEDDC883-B20E-496D-8C9A-A40EC0A29214/Documents/63ea24932c101b76c72fcbae3993fc9b.mov for example; where the video file is in the application and not showing as an unusable asset URL.
Any help would be appreciated.

The problem is that you're trying to fetch the wrong video. You're trying to use info[UIImagePickerControllerReferenceURL]. What you want is info[UIImagePickerControllerMediaURL].

Related

Image from iPhone photo library is scaled down when picked

I'm trying to implement a little tool to manipulate photos on the iPhone. I'm currently using both the simulator and an iPhone 7 with iOS 13.5.1.
I've noticed that when I copy a photo from the Mac to the simulator or via iCloud to the device, the dimensions after picking it in my app differ a lot from what the macOS Photos app tells me they should be.
Example:
Panorama in macOS Photos with dimensions of 14204 × 3628 pixels is exported as original version. Finder shows the same dimensions.
Image file copied to simulator via drag & drop and opened by my app with UIImagePickerController: 2048 x 523 pixels.
Panorama copied to device via iCloud and opened by my app with UIImagePickerController: 4096 x 1046
I'd actually like to open the image with its real dimensions as shown in Finder and Photos. I'm currently using the following code:
#IBAction func btnAddProjectPressed(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
self.dismiss(animated: true, completion: { () -> Void in
})
pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
imageView.image = image
}
UPDATE:
I've managed to get the unscaled image using the .phAsset value from the info dictionary, loading the "real" image using the PHImageManager. However, this outputs the message
Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)"
This problem is described in many questions here (for example this one) and I could not really find a solution. Even Apple's sample project outputs this error and doesn't show any photos or albums.
However, combining the UIImagePickerController and the PHImageManager seems to reduce this to a warning so that I do get the full-sized image.

Getting metadata of image from photoLibrary

I need to get the metaData from an Image I'm picking via UIImagePickerController.
This is my code:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let metaData = info[UIImagePickerController.InfoKey.mediaMetadata] as? [AnyHashable: Any]
print(metaData)
picker.dismiss(animated: true, completion: nil)
}
It works fine, when im picking the Image having .camera as source. But when I use .photoLibrary as source, then metaData is nil. I already read through other questions and tried stuff like
let asset = info[.phAsset] as? PHAsset
print(asset?.creationDate ?? "None")
print(asset?.location ?? "None")
But this also returns nil. I guess the source of the problem is, that the info-Dictionary only returns 4 Keys when picking from .photoLibrary:
UIImagePickerControllerOriginalImage
UIImagePickerControllerMediaType
UIImagePickerControllerImageURL
UIImagePickerControllerReferenceURL
It would be awesome if someone could tell me where my mistake is.
Thanks in advance !
I had the same problem. If the user does not grant access to the photo library first, info[.phAsset] will return nil.
Quote from Apple: "Accessing the photo library always requires explicit permission from the user. The first time your app uses PHAsset, PHCollection, PHAssetCollection, or PHCollectionList methods to fetch content from the library ..."
Thus, you have to call PHPhotoLibrary.requestAuthorization{ ... } before presenting the image picker.
If the user denies the request, info[.phAsset] will also be nil!
This key is valid only when using an image picker whose source type is set to UIImagePickerController.SourceType.camera, and applies only to still images.
The value for this key is an NSDictionary object that contains the metadata of the photo that was just captured. To store the metadata along with the image in the Camera Roll, use the PHAssetChangeRequest class from the Photos framework.
https://developer.apple.com/documentation/uikit/uiimagepickercontroller/infokey/1619147-mediametadata

How to post a video selected from the library on an apple device to a view controller in xcode using swift

I would like to choose a video from the library(which I have completed) NOW, I want to take that video and display it in a view controller. What do I do? I have looked everywhere and have found nothing.
Here is my code for trying to get the file name of a selected video from the library, which I am trying to display in a webview. It does not work.
videoURL = info[UIImagePickerControllerReferenceURL] as! NSURL?
let fileURL = NSURL(fileURLWithPath: " (videoURL)")
videoView.loadHTMLString( " ", baseURL : nil)
Any help is much appreciated. Thanks!
You'll need to implement the delegate methods.. Check this out:
How to select any Video or Movie file from UIImagePickerController

iOS Swift 2 - Get path to video in camera roll

I'm working on an app that uploads a video on a server and I got to a point where I need to re-run the upload process if a user shuts down the app and openes it again later.
After a user taps on a video, this function gets triggered
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let mediaType = info[UIImagePickerControllerMediaType] as! NSString
if mediaType == kUTTypeMovie {
let fileUrl = info[UIImagePickerControllerMediaURL] as! NSURL
// ...
}
self.performSegueWithIdentifier("someSegue", sender: self)
}
But I found out that fileUrl points to some temporary reference to the original video and is always different even if the video is the same.
So how can I get real path to the video, which I can save to NSUserDefaults so when a user opens the app again I can access the video again.
The UIImagePicker will always compress a video and hands you the NSURL of the temp file given in info[UIImagePickerControllerMediaURL]--and it is your responsibility to delete that temp file whether you use it or not.
If you want to use the compressed version, move it to your documents folder and save the path to that in your NSUserDefaults.
If you want the original raw video, get the NSURL in info[UIImagePickerControllerReferenceURL]. This is the URL to the original ALAsset. Then you'll need to use PHImageManager().requestImageDataForAsset or PHImageManager().requestExportSessionForVideo to get the data for upload.

Extract video portion from Live Photo

Has anyone figured out how to extract the video portion from a Live Photo? I'm working on an app to convert Live Photos into a GIF, and the first step is to get the video file from the Live Photo. It seems like it should be possible, because if you plug in your phone to a Mac you can see the separate image and video files. I've kinda run into a brick wall in the extraction process, and I've tried many ways to do it and they all fail.
The first thing I did was obtain a PHAsset for what I think is the video part of the Live Photo, by doing the following:
if let livePhoto = info["UIImagePickerControllerLivePhoto"] as? PHLivePhoto {
let assetResources = PHAssetResource.assetResourcesForLivePhoto(livePhoto)
for assetRes in assetResources {
if (assetRes.type == .PairedVideo) {
let assets = PHAsset.fetchAssetsWithLocalIdentifiers([assetRes.assetLocalIdentifier], options: nil)
if let asset = assets.firstObject as? PHAsset {
To convert the PHAsset to an AVAsset I've tried:
asset.requestContentEditingInputWithOptions(nil, completionHandler: { (contentEditingInput, info) -> Void in
if let url = contentEditingInput?.fullSizeImageURL {
let movieUrl = url.absoluteString + ".mov"
let avAsset = AVURLAsset(URL: NSURL(fileURLWithPath: movieUrl), options: nil)
debugPrint(avAsset)
debugPrint(avAsset.duration.value)
}
})
I don't think this one works because the debug print with the duration.value gives 0.
I've also tried without the ".mov" addition and it still doesn't work.
I also tried:
PHImageManager.defaultManager().requestAVAssetForVideo(asset, options: nil, resultHandler: { (avAsset, audioMix, info) -> Void in
debugPrint(avAsset)
})
And the debugPrint(avAsset) prints nil so it doesn't work.
I'm kind of afraid they might have made it impossible to do, it seems like I'm going in circles since it seems like the PHAsset I got is still a Live Photo and not actually a video.
Use the PHAssetResourceManager to get the video file from the PHAssetResource.
PHAssetResourceManager.defaultManager().writeDataForAssetResource(assetRes,
toFile: fileURL, options: nil, completionHandler:
{
// Video file has been written to path specified via fileURL
}
NOTE: The Live Photo specific APIs were introduced in iOS 9.1
// suppose you have PHAsset instance (you can get it via [PHAsset fetchAssetsWithOptions:...])
PHAssetResource *videoResource = nil;
NSArray *resourcesArray = [PHAssetResource assetResourcesForAsset:asset];
const NSInteger livePhotoAssetResourcesCount = 2;
const NSInteger videoPartIndex = 1;
if (resourcesArray.count == livePhotoAssetResourcesCount) {
videoResource = resourcesArray[videoPartIndex];
}
if (videoResource) {
NSString * const fileURLKey = #"_fileURL";
NSURL *videoURL = [videoResource valueForKey:fileURLKey];
// load video url using AVKit or AVFoundation
}
I accidentally did. I have an ios app called Goodreader (available in the appstore) which features a windows-like file manager. When importing a live photo, it will save it as a folder ending in .pvt containing the jpg and mov files in it. There is only one caveat: you need to open the live photo from within the messages app after you've sent it to yourself or somebody else to see the "import to goodreader" option, not from the photos app.

Resources