How do I get a thumbnail of a video imported from the camera roll, or the camera itself?
This has been asked before, and has been answered. However, the answers kind of suck for me.
This thread iphone sdk > 3.0 . Video Thumbnail? has some options that boil down to:
Crawl some filesystem directory for a JPG with the latest modification date that should correspond to the video you just picked. This is extremely messy, and involves rooting around in directories Apple would probably not really want me doing.
Use ffmpeg. But this is so general that I cannot seem to figure out the steps that it would take to import ffmpeg into my project and to actually call it to extract images.
Is there really no other way? This seems like a HUGE oversight in the SDK to me. I mean the video picker has thumbnails in it, so Apple must be doing something to generate those, yet does not allow us to?
-(void)testGenerateThumbNailDataWithVideo {
NSString *path = [[NSBundle mainBundle] pathForResource:#"IMG_0106" ofType:#"MOV"];
NSURL *url = [NSURL fileURLWithPath:path];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
NSError *err = NULL;
CMTime time = CMTimeMake(1, 60);
CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
[generate release];
NSLog(#"err==%#, imageRef==%#", err, imgRef);
UIImage *currentImg = [[UIImage alloc] initWithCGImage:imgRef];
static BOOL flag = YES;
if (flag) {
NSData *tmpData = UIImageJPEGRepresentation(currentImg, 0.8);
NSString *path = [NSString stringWithFormat:#"%#thumbNail.png", NSTemporaryDirectory()];
BOOL ret = [tmpData writeToFile:path atomically:YES];
NSLog(#"write to path=%#, flag=%d", path, ret);
flag = NO;
}
[currentImg release];
}
Best method I've found... MPMoviePlayerController thumbnailImageAtTime:timeOption
Nevermind this... see first comment below. That's the answer.
We use ffmpeg, you can explore our site for hints on how to do it, eventually I want to put up a tutorial.
But right now I'm more concentrated on getting ffmpeg to play movies.
Understand once you have that code the code to generate a thumbnail is just a subset of that.
http://sol3.typepad.com/tagalong_developer_journa/
This tutorial here, has helped us and maybe the majority of developers using ffmpeg to get started.
dranger.com/ffmpeg/ "
Finally,
Apple probably would maybe not have any problems with using the thumbnail generated from the video camera, I don't think its in a private folder however that is only created by the camera and not for videos picked from the image picker.
Related
I am looking for a way to get the app icon from the app id. Do you know how to do it? Please share the way. Thanks.
e.g
Instagram, where the id I'm looking for is: id389801252
https://itunes.apple.com/jp/app/instagram/id389801252?mt=8
I want to get this image:
(I composed this answer after 2 minutes of googling... It's just the matter of the correct keyword!)
This is possible using an undocumented documented API of the iTunes Store. It might change in the future, but it doesn't seem to have changed in the near past, so here you are...
NSString *idString = #"id389801252";
NSString *numericIDStr = [idString substringFromIndex:2]; // #"389801252"
NSString *urlStr = [NSString stringWithFormat:#"http://itunes.apple.com/lookup?id=%#", numericIDStr];
NSURL *url = [NSURL URLWithString:urlStr];
NSData *json = [NSData dataWithContentsOfURL:url];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:json options:0 error:NULL];
NSArray *results = [dict objectForKey:#"results"];
NSDictionary *result = [results objectAtIndex:0];
NSString *imageUrlStr = [result objectForKey:#"artworkUrl100"]; // or 512, or 60
NSURL *artworkURL = [NSURL URLWithString:imageUrlStr];
NSData *imageData = [NSData dataWithContentsOfURL:artworkURL];
UIImage *artworkImage = [UIImage imageWithData:imageData];
Note that this performs two synchronous round-trips using the NSURL API, so you better wrap this in a backgorund thread for maximal user experience. Feed this program an ID string (idString in the code above) and in the end, artworkImage will contain a UIImage with the desired image.
Just for reference, you can use the app's bundle id too:
http://itunes.apple.com/lookup?bundleId=com.burbn.instagram
Not sure if this is at all relevant anymore, but Apple provides an iTunes Link Maker tool. If you use this tool to find your app, you'll also see where it shows an App Icon section. Click embed and grab the img link from there. One thing to note, I did end up playing with the url a bit to find the right size and format I needed (for instance you can get a jpg render instead of png or select an arbitrary size like 128x128)
I have searched and read the docs, but I cannot seem to find a solution to this (seemingly-simple) issue I've run into. I have songs exporting working fine from the user's iTunes library, and it downloads into the user's documents folder with no issues every time, but videos just don't seem to work.
I have it showing an MPMediaPickerController (allowsPickingMultipleItems = YES) to allow the user to select either videos or songs from their downloaded library. When done, here is the relavent code I'm using:
- (void)mediaPicker:(MPMediaPickerController*)mediaPicker didPickMediaItems:(MPMediaItemCollection*)mediaItemCollection {
AVAssetExportSession *exportSession;
for (MPMediaItem *item in mediaItemCollection.items) {
NSURL *assetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
MPMediaType type = [[item valueForProperty:MPMediaItemPropertyMediaType] intValue];
if (type >= MPMediaTypeMovie) {
exportSession = [[AVAssetExportSession alloc] initWithAsset:[AVAsset assetWithURL:assetUrl] presetName:AVAssetExportPreset640x480];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
filePath = [title stringByAppendingString:#".mov"];
exportSession.outputURL = [NSURL fileURLWithPath:[[NSFileManager documentDirectory] stringByAppendingPathComponent:filePath]];
} // .. check for song-types here and set session up appropriately
[exportSession exportAsynchronouslyWithCompletionHandler:^{
// never gets into AVAssetExportSessionStatusCompleted here for videos
}
}
}
The error I get every time is the following:
Error Domain=AVFoundationErrorDomain Code=-11820 "Cannot Complete Export" UserInfo=0x1e1a2180 {NSLocalizedRecoverySuggestion=Try exporting again., NSLocalizedDescription=Cannot Complete Export}
Not very helpful. :( I feel like I may be potentially missing something obvious here. Am I going about this the correct way? Is it potentially a problem with me trying to "force" it to MOV-format? Or perhaps needing a different way of setting up the export session?
For reference, I'm using iOS 6.0.1 on my iPhone 5 for testing, with a baseSDK of 6.0. Thanks in advance for any guidance that can be offered on this!
Additional Info #1: something that's odd. It seems to crash immediately with a "SIGTRAP" if I set the outputFileType to "AVFileTypeAppleM4V".. I wanted to try M4V, because when I do a log output of the assetURL, I see something like: ipod-library://item/item.m4v?id=12345. Don't know if that makes a difference or not, but odd that it just crashes like that if I try m4v format. Probably because it's not in the supported filetypes list (see next info point).
Additional Info #2: The supported file types I get (from calling the "supportedFileTypes" method are: "com.apple.quicktime-movie" and "public.mpeg-4". The "exportPresetsCompatibleWithAsset" include all of the video ones, including m4a, low/med/high quality, and the specific dimensions ones. I have tried EVERY combination of all these, such as AVFileTypeQuickTimeMovie and AVFileTypeMPEG4 for fileTypes, and all of the presets, including the low/med/high, and all of the dimension ones. It never fails that I get the "Cannot Complete Export" error.
Additional Info #3: I am also using a Deployment Target of 5.1. But yes, I have tried 6.0, and it gives the same error. :(
Additional Info #4: If needed to know, the movie I'm testing with is a "Pilot" TV show, one video, the first one I saw in iTunes that was free. So I downloaded it for use in this app.
Additional Info #5: Not sure if this is important, but the "hasProtectedContent" method returns YES for the AVAsset (and AVURLAsset if I convert). May not make a difference, but thought I'd throw it out there.
After trying to replicate the issue and doing some testing, I strongly suspect the protected content is an issue. Here's why:
I copied your code, and tested it on my iPod Touch (5th gen, iOS 6.0.1), though instead of coming from a media picker, I just let it loop through all the videos I have on the device (7 of them.) It worked great, and called the completion handler and made proper .mov files in the documents directory of the app sandbox. I moved the .mov files to my Mac and they all played.
These video files had the hasProtectedContent as NO.
So I placed a video file I got from the iTunes store, and confirmed it had the hasProtectedContent as YES. Interestingly, when I try to get the URL from MPMediaItemPropertyAssetURL, I get nil for the protected/iTunes obtained video.
I strongly suspect the media protection is the problem.
Here's the variation of code that I used. I didn't change your conversion code at all, just how the URLs are supplied:
// select all the video files
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInteger:MPMediaTypeMovie] forProperty:MPMediaItemPropertyMediaType];
MPMediaQuery *query = [[MPMediaQuery alloc] init];
[query addFilterPredicate:predicate];
NSArray *items = [query items];
// now go through them all to export them
NSString* title;
NSURL * url;
AVAssetExportSession *exportSession;
NSString *storePath;
AVAsset *theAsset;
// we fill put the output at this path
NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
// loop through the items and export
for (MPMediaItem* item in items)
{
title = [item valueForProperty:MPMediaItemPropertyTitle];
url = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSLog(#"Title: %#, URL: %#",title,url);
theAsset = [AVAsset assetWithURL:url];
if ([theAsset hasProtectedContent]) {
NSLog(#"%# is protected.",title);
} else {
NSLog(#"%# is NOT protected.",title);
}
exportSession = [[AVAssetExportSession alloc] initWithAsset:theAsset presetName:AVAssetExportPreset640x480];
storePath = [applicationDocumentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mov",title]];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.outputURL = [NSURL fileURLWithPath:storePath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSLog(#"done!");
}];
}
Out of curiosity, are you checking the AVAsset exportable flag?
I stored videos in my document directory from photo library. Now i want to show all videos which are stored in my document directory.. but i don't know how its possible???
Actually i want to display all videos as like its open in photo library(four videos in a single row).. and when i click on any video... the video is start playing...
can anybody help me which is the best way to show all videos from document directory to ViewController....
Thanx......
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSURL * movieURL = [info valueForKey:UIImagePickerControllerMediaURL] ;
NSData * movieData = [NSData dataWithContentsOfURL:movieURL];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[[self imageNameTextField]text]];
fullPath = [fullPath stringByAppendingFormat:#".MOV"];
[ movieData writeToFile:fullPath atomically:YES];
}
I recommend you to use an open-source grid-view control. You can find them in GitHub. For instance, BDDynamicGridViewController is interesting. But it is not the only option. There is also AQGridView.
Also, there is a popular open-source library, called Three20 and it has it's upgrade, called Nimbus. This library has a custom control for displaying photos grid. You can use the same for displaying video thumbnails grid. For instance, try this.
After you will manage to use or create Grid view control, you will need thumbnail generator for the videos. Use this topic for that purpose.
To get access to the videos stored in the photo library on the device you need to use the Asset library. The following code shows you how to get access to the first video in the photo library :
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
// Within the group enumeration block, filter to enumerate just videos.
[group setAssetsFilter:[ALAssetsFilter allVideos]];
// For this example, we're only interested in the first item.
[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0] options:0
usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
// The end of the enumeration is signaled by asset == nil.
if (alAsset) {
ALAssetRepresentation *representation = [alAsset defaultRepresentation];
NSURL *url = [representation url];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
// Now you have the AV asset for the video.
}
}];
}
failureBlock: ^(NSError *error) {
// Typically you should handle an error more gracefully than this.
NSLog(#"No groups");
}];
[library release];
This example is in the AVFoundation Programming guide, more details on the Apple developer website
I have made the same project for one of my client. I can tell you the idea but cann't tell you the code. The idea is while taking or saving video take the starting frame of every video and save it as PNG image as icon of the video. By this way you will get the icon of every video. Save all the Images in different folder in such a manner that each image can be link with its video. Now retrieve all videos from the document folder by below code
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:path error:nil];
*filelist is the NSArray
In the same manner retrieve the icons of the videos.
Make a grid view of buttons. Set images of the buttons as icons of the videos. Show the video names. When click on the video open a new view controller and make a video player ther play the video there.
I am trying to get a thumbnail from a .mov file that I captured from the iphone camera. I currently have the movie saved in the documents portion of the app. When I call [Asset duration] it returns a null object. Also when I try to call the copyCGImageAtTime:actualtime:error method it also returns a null object. I've spent count less hours trying to figure this out. I've tried moving my code to another main section portion of my app to just see if I could get it to work. I've also tried to run it on the simulator with no luck. Here is the code:
NSString* destinationPath = [NSString stringWithFormat:#"%#/aaa/aaa.mov", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL URLWithString:destinationPath] options:nil];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0.0, 600);
NSError *error2 = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error2];
UIImage *thumb = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);
I have also confirmed that the movie does exist under that folder. Any help would be greatly appreciated. Thanks :)
--Edit--
Forgot to mention that the Error from copyCGImageAtTime is the AVUnknown error.
--Edit2--
Found out the problem. I didn't include file:// at the beginning of the url. It works now.
Found out the problem. I didn't include file:// at the beginning of the url. It works now.
I'm try to create thumbnail image from video url.
I use AV Foundation Programming Guide.
My project have a button and an imageview. When button pressed so thumbnail image will load on uiimageview.
my code can't work,it's:
- (IBAction) btnClick : (id)sender
{
NSURL *url = [NSURL URLWithString:#"http://www.youtube.com/watch?v=bgN62D70VLk"];
AVURLAsset *myAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:myAsset];
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds/2.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef halfWayImage = [imageGenerator copyCGImageAtTime:midpoint actualTime:&actualTime error:&error];
if (halfWayImage != NULL) {
NSString *actualTimeString = (NSString *)CMTimeCopyDescription(NULL, actualTime);
NSString *requestedTimeString = (NSString *)CMTimeCopyDescription(NULL, midpoint);
NSLog(#"got halfWayImage: Asked for %#, got %#", requestedTimeString, actualTimeString);
[actualTimeString release];
[requestedTimeString release];
// Do something interesting with the image.
CGImageRelease(halfWayImage);
}
UIImage *image = [UIImage imageWithCGImage:halfWayImage];
[imageView setImage:image];
[imageGenerator release];
}
Help me for this problem,please!
Thanks!
MPMoviePlayerController has some method to handle this -
thumbnailImageAtTime:timeOption:
requestThumbnailImagesAtTimes: timeOption:
cancelAllThumbnailImageRequests:
I see a few problems in your code:
http://www.youtube.com/watch?v=bgN62D70VLk is the URL of a web page, but AVAssets must be video or audio files. Note: YouTube does not advertise the URLs of its video files.
Your call to [myAsset duration] will block. You should instead use the AVAsynchronousKeyValueLoading protocol (see loadValuesAsynchronouslyForKeys).
You are using halfwayImage after releasing it.
I would recommend watching the AVFoundation sessions from WWDC 2010, and looking at the session sample code.
This is very late but it will help some other who comes to this question.
Look into this answer for the same problem, Hope will help to other guys.