iPhone- Avoid video compression in UIImagePickerController - iphone

In my app , im uploading videos to server. Im using the native UIImagePickercontroller to pick the videos from the gallery.
The delegate i have is ;
imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
My application has to work in the background and while picking large videos from gallery the compressing time is so annoyingly high that , the user some how gets irritated and exits the app.While this occur, the beginbackgroundTaskWithExpirationhandler gives me 10 mins for bgTask.But if the compression process is in excess of 10 mins while app is in background the OS suspends /kills my app.
Do you have any idea how I can avoid this.??

Sadly, there is no way to avoid compression completely. Setting the video quality to high should help though.
myController.videoQuality = UIImagePickerControllerQualityTypeHigh;
EDIT: I have not tested this, but it sounds like it would work. It's a remake of the UIImagePickerController that claims to give raw access to images and videos.
GitHub: https://github.com/elc/ELCImagePickerController
More info about it: http://www.icodeblog.com/2010/10/07/cloning-uiimagepickercontroller-using-the-assets-library-framework/

If you know how to acquire a PHAsset object, use this instead of a third-party solution (finer control, never have to upgrade):
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset *avAsset, AVAudioMix *audioMix, NSDictionary *info) {
NSURL *url = (NSURL *)[[(AVURLAsset *)avAsset URL] fileReferenceURL];
NSLog(#"url = %#", [url absoluteString]);
NSLog(#"url = %#", [url relativePath]);
}];
Whereas phAsset is the PHAsset object, and avAsset is the resulting AVAsset object generated by PHImageManager, the output to the console from the above code will produce, for example:
2016-04-16 01:15:40.155 ChromaEpsilon[3423:933358] url = file:///.file/id=16777218.8262005
2016-04-16 01:15:40.155 ChromaEpsilon[3423:933358] url = /private/var/mobile/Media/DCIM/108APPLE/IMG_8421.MOV
There's more than just these two, I believe, but start here.

Related

creating NSURL crashes on IOS5 only

Upgraded device to iOS 5, now the app crashes. Nuts...
It's a camera application. Records video. I have a playMovie procedure to play the captured video. That function needs to create a NSURL using the path (NSString) that points to the video file. But the NSURL creation crashes with exc_bad_access. 2 nights trying to solve this, no luck. Beginning to suspect the problem is older version of xcode 3.2.5.
Here's the snippet...
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
/// after I verify that file type is movie ....
videoFilePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
NSURL *url = [NSURL fileURLWithPath:videoFilePath];
... at this point the app crashes.
ALREADY TRIED:
- Moving NSURL creation from playMovie proc to within didFinishPickingMediaWithInfo (as shown above). Still crashes.
- Adding isDirectory:NO]. still crashes.
- printing the path string in log... path looks just fine (it's not empty or overwritten)
- comment out the NSURL and just save the MOV file without playing it. works fine. But I need the URL in order to play the movie.
device log:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x10000010
console msg:
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Can't find dlopen function, so it is not possible to load shared libraries.)
--- adding more details (8/30/12) ---
videoFilePath is an NSString declared in my viewController.h. It has #property (retain,nonatomic), and it's synthesized. It is NOT alloc'ed anywhere, so it is used as a constant. The snipped of code above shows how the media url is assigned to videoFilePath (as a constant, not alloc'ed).
After this I open a UIActionSheet for user to "Play Movie", or "Save Movie", or "Cancel" (someday will add Youtube option). In the actionsheet, if user picks PlayMovie I call (void)playMovie procedure. In that procedure, I declare the *url object initiating it with the path stored in videoFilePath. Worked like a charm until upgraded to IOS 5.
I just tried to preallocate the NSString videoFilePath inside (void)viewDidLoad, so that it's used allocated instead of constant. But that didn't solve it.
I just tried upgrading XCODE to 4.2. I don't get the msg "Data Formatters temporarily unavailable" anymore. But still crash with EXC_BAD_ACCESS.
Thanks! Thanks! Thanks!
Apparently you are extracting a path from an NSURL object, then creating an new NSURL object from that path. fileURLWithPath: is not happy with that path for some reason. It could be that the path does not conform to RFC 1808, and therefore the previous path call results in videoFilePath == nil.
But why do this conversion? Just use:
NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL];

AssetsLibrary: Location Services prompt. How did Instagram avoid it?

I am working an app that uses the photos and videos in the AssetsLibrary, and I am just trying to determine once and for all if there is any way around asking the user for permission to access Location data in order to get these assets. I understand that the EXIF data includes GPS information, and that makes enough sense to me.
Note: I have searched through StackOverflow and I have found similar questions, and I am not making this post simply to add one more to the list. I am asking specifically about one (apparent) counterexample.
When using Instagram for the first time, I am able to browse through my photo album, select photos, edit them and share them all without ever being prompted about location services. I am only prompted when I choose to click on the button labeled "Enable Geotagging." Checking the settings tab, it looks like if I don't ever click that button, Instagram doesn't even come up in the Location Services section of my Settings.
My question is, how did Instagram get away with this? Anyone have any ideas? I'd like to figure out if I can mimic their implementation somehow so my users aren't shut out from getting their camera assets if they say no to this prompt.
the explanation is quite simple. Instagram uses the UIImagePickerController. UIImagePickerController works without Location Services enabled, but you don't get EXIF data using this method.
UIImagePickerController can retrieve metadata (incl. GPS) only through the UIImagePickerControllerReferenceURL. UIImagePickerControllerReferenceURL you have to pass then AssetsLibrary methods, which needs again location services enabled.
Cheers,
Hendrik
As holtmann mentioned, reading the UIImagePickerControllerReferenceURL triggers the location services prompt. If you only need the image data, not the metadata, you can get that from the UIImagePickerControllerOriginalImage and UIImagePickerControllerEditedImage keys instead (I'm checking EditedImage first and then checking OriginalImage if EditedImage is null). This doesn't require the use of the assets library and doesn't require location access.
Here's how I'm using this in my app, including saving a local copy of the image for further editing:
- (void)imagePickerController:(UIImagePickerController *)controller didFinishPickingMediaWithInfo:(NSDictionary *)info {
// get the selected photo as a UIImage
UIImage *photo = [info objectForKey:#"UIImagePickerControllerEditedImage"];
if (!photo) {
photo = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
// save the photo to the app's Documents folder
if (photo) {
NSString *extension = #"jpg";
NSString *filename = [NSString stringWithFormat:#"%#.%#", self.defaultTitle, extension]; // self.defaultTitle is defined elsewhere in my app
NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:filename];
[UIImageJPEGRepresentation(photo, 0.8) writeToFile:path atomically:YES];
}
}

Save MP4 into iPhone photo album

I have an app that plays video clips through the MPMovieplayer. These clips are in mp4 format and everything works dandy. I want to take that same clip and save it into the photo album. This works if I manually sync the video from a computer through iTunes to the phone. It appears to transcode the video file and store it as a .MOV format.
However, when I try and save the video while in the app via code, I get a video format error. So my question is how do I get my video to save in the photo album? If this is not possible with mp4 how do I transcode (in app) to .MOV?
Here is the code:
ALAssetsLibrary* library = [[ALAssetsLibrary alloc]init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:moviePlayerController.contentURL])
{
NSURL *clipURl = moviePlayerController.contentURL;
[library writeVideoAtPathToSavedPhotosAlbum:clipURl completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
[ErrorAlertView showError:error];
else [ErrorAlertView showErrorTitle:#"Success" message:#"Your video clip is saved"];
}];
}
[library release];
Is your contentURL a file path URL or a web URL? For the writeVideoAtPathToSavedPhotosAlbum method, in my testing you actually need a file path URL created (for example) in this way:
NSString *pathString = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"mp4"];
NSString *pathURL = [NSURL fileURLWithPath:pathString isDirectory:NO];
This means you need to first download the movie from the web, if you're using a web URL. I recommend ASIHTTPRequest, using the setDownloadDestinationPath: method to set the download directory.
In general, mp4 files should work if they're the right resolution for the right (retina, non-retina, iPad) device (see my tests of supported video files here).
If the video still gives a NO response on videoAtPathIsCompatibleWithSavedPhotosAlbum: after making absolutely sure the file path URL is correct, then you'll need to use AVAssetExportSession (with AVAssetExportPresetLowQuality, AVAssetExportPresetMediumQuality, or AVAssetExportPresetHighestQuality) to get a device-appropriate file that you can then save to the Photo Album.

Save Youtube video to iPhone in the app

Playing Youtube video in the app is easy and well documented around.
There are two problems with that:
after closing Youtube player, if user wants to play it again it has to wait for online streaming again
can't play offline (load video at home to watch on the road)
Does anyone have code to:
download Youtube video to documents folder and show progress of download
play downloaded video by loading file from documents folder (meaning even when not connected to the internet)
To download the video from YouTube:
Get the URL to download from, via the YouTube API or whatever other method.
Create an NSOutputStream or NSFileHandle opened on a temporary file (in NSTemporaryDirectory() or a temp-named file in your Documents directory).
Set up your progress bar and whatever else you need to do.
Allocate and start an NSURLConnection to fetch the file from the URL. Do not use sendSynchronousRequest:returningResponse:error:, of course.
In the connection:didReceiveResponse: delegate method, read out the length of data to be downloaded for proper updating of the progress bar.
In the connection:didReceiveData: delegate method, write the data to the output stream/file handle and update the progress bar as necessary.
In connectionDidFinishLoading: or connection:didFailWithError:, close the output stream/file handle and rename or delete the temporary file as appropriate.
To play it back, just use NSURL's fileURLWithPath: to create a URL pointing to the local file in the Documents directory and play it as you would any remote video.
Ive used classes from this project: https://github.com/larcus94/LBYouTubeView
It works fine for me.
I can download youtube videos.
I used this code:
LBYouTubeExtractor *extractor = [[[LBYouTubeExtractor alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:(#"http://www.youtube.com/watch?v=%#"), self.videoID ]] quality:LBYouTubeVideoQualityLarge] autorelease];
[extractor extractVideoURLWithCompletionBlock:^(NSURL *videoURL, NSError *error) {
if(!error) {
NSLog(#"Did extract video URL using completion block: %#", videoURL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL: videoURL];
NSString *pathToDocs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filename = [NSString stringWithFormat:(#"video_%#.mp4"), self.videoID ];
[data writeToFile:[pathTODocs stringByAppendingPathComponent:filename] atomically:YES];
NSLog(#"File %# successfully saved", filename);
});
} else {
NSLog(#"Failed extracting video URL using block due to error:%#", error);
}
}];
You can show progress of downloading using technique described in the posts above.
Here is my example: https://github.com/comonitos/youtube_video
I used PSYouTubeExtractor.h class by Peter Steinberger It can get youtube mp4 video url and than downloading and viewing is not a problem
NSURLConnection
+
NSNotificationCenter
+
PSYouTubeExtractor
+
NSMutableData
check these projects -
https://github.com/iosdeveloper/MyTube
https://github.com/pvinis/mytube
these will definitely help you!!
I don't personally know how to download youtube videos (and the code is too big to put in an answer here).
However, here's a complete youtube downloading example here.
It's an open source youtube downloader called LoadTube: here's the a link to the source code.
I would play the video and figure out where the temp file is being stored. If you can get access to it, copy it into some document folder for offline viewing.

In the UIImagePickerController, is it possible to get the NSURL value for UIImagePickerControllerMediaURL?

When the user selects an image from the picker controller, I'm calling the delegate:
(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
in the dictionary info, the value for key UIImagePickerControllerMediaURL is NULL. Am I missing something here?
I know this question is horribly old, but I did manage to wander across it from a recent google search, so thought I'd throw in what I think is actually the answer to your question which the other answers seem to miss.
You're getting NULL for UIImagePickerControllerMediaURL as it is only returned for the Movie (kUTTypeMovie) media type in a picker. If you're presenting a default picker without specifying additional media types after it's creation, then the docs seem to imply that you won't get it:
"UIImagePickerControllerMediaURL - Specifies the filesystem URL for the movie."
And I can confirm that it isn't returned at least in the quick test that I did in iOS 6 for images (not Movies).
To access the image returned, you actually have direct access to a UIImage object under the keys of UIImagePickerControllerOriginalImage (if editing is not allowed, the default setting) or UIImagePickerControllerEditedImage if editing is allowed in the picker. The original image is always available, even if editing was done in the picker. You can treat these UIImage's just like you would any other UIImage in your program.
You can get an NSURL path to the object, but it isn't quite what you would expect. And I can't seem to access the data in the file either.
- (void)imagePickerController:(UIImagePickerController *)imagepicker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// dismiss the image picker modal
[[imagepicker parentViewController] dismissModalViewControllerAnimated:YES];
// grab the image url
NSURL *imageURL = [info valueForKey: UIImagePickerControllerReferenceURL];
// get the data from the url
NSData *data = [NSData dataWithContentsOfURL:imageURL];
// data is null at this point
}
The NSURL looks something like the following for a jpeg file.
assets-library://asset/asset.JPG?id=1000000246&ext=JPG
Yes the Meta data is not populated in the callback (some were also expecting the geotag / position of the place where the picture was taken , but this is not the case).
The fact that you don't get the NSURL sounds logical from Apple perspective : they will not give you the path to the real file (like file:// ....) because this is something that is considered as part of the implementation, not part of the public API : from the client perspective it looks like if apple doesn't want you to known where the picture is store physically on the File system.
Running iOS 3.2.1 on an iPad, it seems that my app is able to get the file URL via UIImagePickerControllerMediaURL for image files, even though the documentation seems to say that it only works for movie files.
The following link helped me. display image from URL retrieved from ALAsset in iPhone
The UIImagePickerControllerReferenceURL returns an asset-library url. You need to use an ALAssetLibrary object to access the image. The link describes how to do this.