Get Image from Selected Video UIImagePickerController - ios

How can i retrieve or make a thumbnail image of the selected video to be used in a another view controller after the video has been selected by user?
func imagePickerController1(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
// 1
let mediaType = info[UIImagePickerControllerMediaType] as! NSString
// 2
dismissViewControllerAnimated(true) {
// 3
if mediaType == kUTTypeMovie {
let moviePlayer = MPMoviePlayerViewController(contentURL: info[UIImagePickerControllerMediaURL] as! NSURL)
self.presentMoviePlayerViewControllerAnimated(moviePlayer)
}
}
let destination = self.storyboard!.instantiateViewControllerWithIdentifier("FinializePost")
self.navigationController!.pushViewController(destination, animated: true);
}

You can use this code:
let URL_originalvideo = info[UIImagePickerControllerMediaURL]
let asset: AVAsset = AVAsset.assetWithURL(URL_originalvideo) as AVAsset
let imageGenerator = AVAssetImageGenerator(asset: asset);
let time = CMTimeMakeWithSeconds(1.0, 1)
var actualTime : CMTime = CMTimeMake(0, 0)
var error : NSError?
let myImage = imageGenerator.copyCGImageAtTime(time, actualTime: &actualTime, error: &error)
myImage is what you need.

Related

Unable to generate thumbnail from video in gallery

I'm displaying to the user an image picker to select a video from the gallery. That works, i pass the mediatype ["public.movie"] and all the videos of the gallery are displayed to pick up. When the user picks it i receive in my dellegate:
extension VNInventoryCollectionVC: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)
if let pickedImage = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as? UIImage
{
pickImageCallback?(pickedImage)
}
if let videoURL = info["UIImagePickerControllerReferenceURL"] as? URL
{
print(videoURL)
pickImageCallback?(videoURL)
}
dismiss(animated: true)
}
}
After the callback i'm trying to create a image thumbnail from that video, and that is where i'm not able to do it:
let thumbnail = getThumbnailFrom(path: multimedia.video!)
cell.image.image = thumbnail
The function that generates the thumbnail is:
func getThumbnailFrom(path: URL) -> UIImage? {
do {
print("Video URL: \(path)")
print("Video absolute URL: \(path.absoluteURL)")
//let asset = AVURLAsset(url: path.absoluteURL! , options: nil)
var asset : AVAsset = AVAsset(url: path.absoluteURL) as! AVAsset
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
return thumbnail
} catch let error {
print("*** Error generating thumbnail: \(error.localizedDescription)")
return nil
}
}
In the console the video url displayed is:
Video URL: assets-library://asset/asset.MP4?id=84D1CEDD-7AE4-4FE5-897E-47608DC2CFF0&ext=MP4
Video absolute URL: assets-library://asset/asset.MP4?id=84D1CEDD-7AE4-4FE5-897E-47608DC2CFF0&ext=MP4
The displayed error is that is unable to open the file. The line that breaks is:
let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
I suppose the problem is with the url, that i have an assets url and i would require an absolute file path or something like that.
Use UIImagePickerController.InfoKey.mediaURL to key into the info dictionary. UIImagePickerController.InfoKey.referenceURL is deprecated.
func didSelectVideo(at url: URL) {
let asset = AVAsset(url: url)
let generator = AVAssetImageGenerator(asset: asset)
generator.appliesPreferredTrackTransform = true
let cgImage = try! generator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
cell.image.image = thumbnail
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
dismiss(animated: true) {
guard let url = info[.mediaURL] as? URL else { return }
self.didSelectVideo(at: url)
}
}

Thumb image from server url

How to create thumb image from video URL and load in table view cell
I am using this code but it freezes table view
func generateThumbImage(url : NSURL) -> UIImage{
var asset : AVAsset = AVAsset.assetWithURL(url) as! AVAsset
var assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
var error : NSError? = nil
var time : CMTime = CMTimeMake(1, 30)
var img : CGImageRef = assetImgGenerate.copyCGImageAtTime(time, actualTime: nil, error: &error)
var frameImg : UIImage = UIImage(CGImage: img)!
return frameImg
}
you can try that code may help to you
import Foundation
import UIKit
import AVKit
class CommonFunctions {
static let shared = CommonFunctions()
typealias ResponseBlock = (_ result: UIImage?) -> Void
func getVideoThumnail(URLString: String, responseBlock:#escaping ResponseBlock) {
DispatchQueue.global().async {
let url = URL(string: URLString)
let asset = AVAsset(url: url!)
let assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMake(value: 1, timescale: 2)
let img = try? assetImgGenerate.copyCGImage(at: time, actualTime: nil)
if img != nil {
let frameImg = UIImage(cgImage: img!)
DispatchQueue.main.async(execute: {
responseBlock(frameImg)
})
}else {
responseBlock(nil)
}
}
}
}
use :-
CommonFunctions.shared.getVideoThumnail(URLString: downloadURL) { (image) in
if image != nil {
let thumbimage = image
}
}
Use your method in UIThread
DispatchQueue.main.async() {
// your UI update code
}
It prevents from freezing.

Generating thumbnail from Video ends up always rotated in an UIImageView

I'm using UIImagePickerController to select a video or an image from the user's gallery. With the photos, there's no problem, everything is displayed the way it should be. The problem comes when I'm trying to generate a thumbnail for a video.
Basically, the thumbnail image could end up being displayed upside down or 90 degrees to the left or right. I'm not sure why it happens. Am I missing something or doing something wrong?
extension PostVC : UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let videoUrl = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
if let thumbnail = self.generateThumbnailForImage(videoUrl) {
self.videoUrl = videoUrl
self.photoImageView.image = thumbnail
self.selectedImage = thumbnail
}
}
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
selectedImage = image
photoImageView.image = image
shareButton.isEnabled = true
}
dismiss(animated: true, completion: nil)
}
func generateThumbnailForImage(_ fileUrl: URL) -> UIImage? {
let asset = AVAsset(url: fileUrl)
let imageGenerator = AVAssetImageGenerator(asset: asset)
do {
let thumbnailCGImage = try imageGenerator.copyCGImage(at: CMTimeMake(value: 1, timescale: 10), actualTime: nil) // 1 sec
return UIImage(cgImage: thumbnailCGImage)
} catch let err {
SVProgressHUD.showError(withStatus: err.localizedDescription)
}
return nil
}
}
It seems like setting the imageGenerator.appliesPreferredTrackTransform = true solves this issue.

How to convert NSURL to String

I have a CameraVC class start with :
class CameraVC: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var imagePicker = UIImagePickerController()
var image = UIImage()
var videoFilePath = NSURL()
...
I have this function :
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let mediaType:String = info[UIImagePickerControllerMediaType] as! String
print(mediaType)
if mediaType == "public.image" {
self.image = info[UIImagePickerControllerOriginalImage] as! UIImage
if self.imagePicker.sourceType == UIImagePickerControllerSourceType.Camera {
UIImageWriteToSavedPhotosAlbum(self.image, nil, nil, nil)
}
self.dismissViewControllerAnimated(true, completion: nil)
} else if mediaType == "public.movie" {
self.videoFilePath = info[UIImagePickerControllerMediaURL] as! NSURL
print(self.videoFilePath)
// THIS LINE IS NOT WORK ->
let url = NSURL(string: self.videoFilePath)
/*if self.imagePicker.sourceType == UIImagePickerControllerSourceType.Camera {
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(self.videoFilePath) {
UISaveVideoAtPathToSavedPhotosAlbum(self.videoFilePath, nil, nil, nil)
}
}*/
}
}
The line :
let url = NSURL(string: self.videoFilePath)
is not working and i have a red alert with "Cannot convert value of type NSURL to expected argument type String.
The line :
print(self.videoFilePath)
write in console log :
file:///private/var/mobile/Containers/Data/Application/071BCA9C-D246-4D14-9D56-34057A17079B/tmp/capture-T0x156501280.tmp.y4Ve7u/capturedvideo.MOV
Try looking at the documentation here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/#//apple_ref/occ/instp/NSURL/absoluteString
Try let url = NSURL(string: self.videoFilePath.absoluteString)
Also you do realise that self.videoFilePath is already an NSURL...
You have a poorly named variable. self.videoFilePath isn't a path, it's a url. You're making it a URL here:
self.videoFilePath = info[UIImagePickerControllerMediaURL] as! NSURL
If you already have self.videoFilePath as NSURL, you don't have to convert it to String and then NSURL
To keep the code safer:
if let path = info[UIImagePickerControllerMediaURL] as? NSURL {
self.videoFilePath = path
let url = path
//Continue whatever you want
}

Getting URL of UIImage selected from UIImagePickerController

I'm trying to provide a user selection of an image from Photo Library. Thus I'm using UIImagePickerController for selecting. But here comes an issue with getting its initial URL in the file system (I need this for CKAsset).
My code.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
let imageURL = info[UIImagePickerControllerReferenceURL] as NSURL
let path = imageURL.path!
let imageName = path.lastPathComponent
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentDirectory = paths.first as String!
let localPath = documentDirectory + "/" + imageName
let imageData = NSData(contentsOfFile: localPath)!
let image = UIImage(data: imageData)!
picker.dismissViewControllerAnimated(true, completion: nil)
}
imageURL is kinda cryptic. It describes Asset URL, but not one in File System. And it looks like: assets-library://asset/asset.JPG?id=B6C0A21C-07C3-493D-8B44-3BA4C9981C25&ext=JPG.
According to this logic the path is /asset.JPG where asset.JPG is a name of the image.
Then I'm accessing my Documents folder and trying to find there a file with path:
/Users/Eugene/Library/Developer/CoreSimulator/Devices/3C5E9A23-8220-4B37-BD14-F1E42EEC2C7C/data/Containers/Data/Application/20EBAAE2-6C6F-4651-A48F-16A222CCB3A2/Documents/asset.JPG
Cryptic as well but seems to be a real path for a not existing image... No image with that path can be found. And this makes me sick.
Do I have to save an image from the beginning? Or is there any other way to go?
I've looked through several tutorials using AssetsLibrary API but I didn't find anything useful to solve my problem. Thank you in advance!
Okay, I've solved the issue.
All you have to do is simply grab the image (info[UIImagePickerControllerOriginalImage] as UIImage) and save to the given directory. If you need to save only 1 picture it works great. The code id below.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
let imageURL = info[UIImagePickerControllerReferenceURL] as NSURL
let imageName = imageURL.path!.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let localPath = documentDirectory.stringByAppendingPathComponent(imageName)
let image = info[UIImagePickerControllerOriginalImage] as UIImage
let data = UIImagePNGRepresentation(image)
data.writeToFile(localPath, atomically: true)
let imageData = NSData(contentsOfFile: localPath)!
let photoURL = NSURL(fileURLWithPath: localPath)
let imageWithData = UIImage(data: imageData)!
picker.dismissViewControllerAnimated(true, completion: nil)
}
In SWIFT 4 u Can Try This, It's working properly.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imgUrl = info[UIImagePickerControllerImageURL] as? URL{
let imgName = imgUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let localPath = documentDirectory?.appending(imgName)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImagePNGRepresentation(image)! as NSData
data.write(toFile: localPath!, atomically: true)
//let imageData = NSData(contentsOfFile: localPath!)!
let photoURL = URL.init(fileURLWithPath: localPath!)//NSURL(fileURLWithPath: localPath!)
print(photoURL)
}
APPDEL.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
For Swift 5+ ;according to #Jaydip answer
if let imgUrl = info[UIImagePickerController.InfoKey.imageURL] as? URL{
let imgName = imgUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let localPath = documentDirectory?.appending(imgName)
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let data = image.pngData()! as NSData
data.write(toFile: localPath!, atomically: true)
//let imageData = NSData(contentsOfFile: localPath!)!
let photoURL = URL.init(fileURLWithPath: localPath!)//NSURL(fileURLWithPath: localPath!)
print(photoURL)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
//this block of code grabs the path of the file
let imageURL = info[UIImagePickerControllerReferenceURL] as NSURL
let imagePath = imageURL.path!
let localPath = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(imagePath)
//this block of code adds data to the above path
let path = localPath.relativePath!
let imageName = info[UIImagePickerControllerOriginalImage] as UIImage
let data = UIImagePNGRepresentation(imageName)
data?.writeToFile(imagePath, atomically: true)
//this block grabs the NSURL so you can use it in CKASSET
let photoURL = NSURL(fileURLWithPath: path)
}
check this solution.
import AssetsLibrary
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
self.imagePicker = picker
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
let controller = CropViewController(image: selectedImage )
controller.delegate = self
picker.presentViewController(controller, animated: true, completion: nil)
}
else if let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL{
let assetLibrary = ALAssetsLibrary()
assetLibrary.assetForURL(imageUrl , resultBlock: { (asset: ALAsset!) -> Void in
if let actualAsset = asset as ALAsset? {
let assetRep: ALAssetRepresentation = actualAsset.defaultRepresentation()
let iref = assetRep.fullResolutionImage().takeUnretainedValue()
let image = UIImage(CGImage: iref)
let controller = CropViewController(image: image)
controller.delegate = self
picker.presentViewController(controller, animated: true, completion: nil)
}
}, failureBlock: { (error) -> Void in
})
}
}
In swift 4
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imgUrl = info[UIImagePickerControllerReferenceURL] as? URL{
let imgName = imgUrl.lastPathComponent
let documentDirectory = NSTemporaryDirectory()
let localPath = documentDirectory.appending(imgName)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImageJPEGRepresentation(image, 0.3)! as NSData
data.write(toFile: localPath, atomically: true)
let photoURL = URL.init(fileURLWithPath: localPath)
}
}
swift 4.2
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//obtaining saving path
let fileManager = FileManager.default
let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
let imagePath = documentsPath?.appendingPathComponent("image.jpg")
// extract image from the picker and save it
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
let imageData = pickedImage.jpegData(compressionQuality: 0.75)
try! imageData?.write(to: imagePath!)
}
}
Thanks
let imgUrl = info[UIImagePickerController.InfoKey.imageURL] as? URL

Resources