I have several videos uploaded on Amazon S3 bucket. I want to display the videos in a list format in an iOS application along with the thumbnail.
Suppose the url is https://testurlatamzons3/mybucket/somefile.mp4 and I want to get the thumbnail from the URL without actually downloading or streaming the file.
I have seen certain examples and I am able to download the UIImage and display it on the UIImageView. The example I found was here
But for a 350MB file on amazon s3, it takes around 1.9mb of data transfer just to get the thumbnail. Is there a more optimized or a different approach to getting the thumbnails for the mp4/mov files hosted on Amazon S3
Regards,
Nirav
you could get thumbnails using AVFoundation with any time, any size you want:
AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:yourVideoUrl options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform = YES;
CMTime thumbTime = CMTimeMakeWithSeconds(5,30);
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime,
CGImageRef im,
CMTime actualTime,
AVAssetImageGeneratorResult result,
NSError *error){
NSLog(#"make sure generator is used in this block and it'll work %#", generator);
};
generator.maximumSize = CGSizeMake(320, 180);
[generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler];
I guess you have two options:
To have some API which does what you want and returns the URL of the thumbnail image to your application
To download just a small part of the video and grab a frame from it but this depends on the format of your video, maybe this could help for MP4 videos
https://github.com/ohminteractive/OHMTagLib
Related
Am using JSQMessageViewController for chatting,while capturing the video it is saved in the photo album,i can't add it in to the chatview,if am trying to add the video means that video displayed in the png format.So could you please any one help me to solve this issue,How to add the capture the video from the chatview using JSQMessageViewController.After that i would like to upload the video in the chatview is using the API.Every captured video will be saved and added to the API and display the ChatView.
This code is only for create a thumbnail that you want to display in chat
YOURIMAGEVIEW.image = [SELF imageFromVideoUrl:#"GIVE HERE URL OF VIDEO"];
+(UIImage *)imageFromVideoUrl : (NSURL *)videoUrl
{
AVAsset *asset = [AVAsset assetWithURL:videoUrl];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
imageGenerator.appliesPreferredTrackTransform = YES;
CMTime time = [asset duration];
time.value = 0;
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef); // CGImageRef won't be released by ARC
return thumbnail;
}
When you display this thumbnail in chat and in background call your api that upload a video into your server database . hope that you are clear with my this answer and got a idea what task actually you do.
Happy Coding.
I am a newbie in iOS.I want to show a video thumbnail in image view such that by clicking a Button it should open a gallery and by selecting a video it should display the video thumbnail...... please help me...
There are videos and images that stored on photo library, firstly you want to get all videos from the library, prior to iOS 8, this post shows you how to fetch pictures using AssetsLibrary library. You can filter videos out when doing it, then you get an ALAsset, which can represent a image or video, suppose when you select a video, you get a ALAsset named asset, using the below function will get you a thumbnail image for that video.
If you use ALAsset.
UIImage *thumbnail = [UIImage imageWithCGImage:[asset thumbnail]];
For iOS 8, apple introduces a new Photos library,you can fetch all videos from the library as above, a video or images is represented by PHAsset, suppose you have a PHAsset ivar named asset, you can use the following method to get a UIImage from this asset. Take a look at requestImageForAsset:targetSize:contentMode:options:resultHandler:, you can set the target size to the size of the thumb image you want,in the resultHandler,you get the UIImage.
I am using below code to get thumbnail of video which is downloaded in document directory,
- (UIImage *)thumbnailFromVideoAtURL:(NSURL *)url
{
AVURLAsset *aImgAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *aImgGenerator = [[AVAssetImageGenerator alloc] aImgAsset];
aImgGenerator.appliesPreferredTrackTransform = YES;
NSError *err = NULL;
CMTime time = CMTimeMake(1, 2);
CGImageRef aImgRef = [aImgGenerator copyCGImageAtTime:time actualTime:NULL error:&err];
UIImage *aImgThumb = [[UIImage alloc] initWithCGImage:aImgRef];
return aImgThumb;
}
I know this question has been asked many times on stackoverflow. But my problem is different.
I am iterating on the albumns of photos library to get all videos and their thumbnails.
Now, the problem is, my code is very slow to get the thumbnail of each video. For example, there is 14 videos in my camera roll and the total time taken to generate the thumbnail is around 3-4 seconds. I am using this code.
+(UIImage*)imageFromVideoAtURL:(NSURL*)contentURL {
UIImage* theImage = nil;
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:contentURL options:nil];
AVAssetImageGenerator* generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform = YES;
NSError* err = NULL;
CMTime time = CMTimeMake(1, 60);
CGImageRef imgRef = [generator copyCGImageAtTime:time actualTime:NULL error:&err];
theImage = [[[UIImage alloc] initWithCGImage:imgRef] autorelease];
CGImageRelease(imgRef);
[asset release];
[generator release];
return theImage;
}
I am finding a way to get the thumbnail of all videos very fast so that user has not to wait. I have seen apps on Apple store that are doing the same thing in just micro seconds. Please help.
I have also tried this code to generate the thumbnail, it is also very slow.
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:mediaUrl];
moviePlayer.shouldAutoplay = NO;
UIImage *thumbnail = [[moviePlayer thumbnailImageAtTime:0.0 timeOption:MPMovieTimeOptionNearestKeyFrame] retain];
[imageView setImage:thumbnail]; //imageView is a UIImageView
If you are loading videos from image library, it should already have the embedded thumbnail of the video. This can be accessed using thumbnail or aspectRatioThumnail methods of ALAsset class.
So in your case the thumbnails could be loaded like:
ALAssetLibrary* lib = [ALAssetLibrary new];
[lib assetForURL:contentURL resultBlock:^(ALAsset* asset) {
CGImageRef thumb = [asset thumbnail];
dispatch_async(dispatch_get_main_queue(), ^{
//do any UI operation here with thumb
});
}];
Please make sure to make any UIKit call in the main queue as assetForURL:: method may invoke the resultBlock in some background thread.
I have an application that uploads videos into a server and now what I am trying to create is a news feed to display those video post but by a thumbnail or frame of the video. So that once the user clicks the thumbnail the video will play.
I have the following code used to grab the video from the server and play it:
- (void)openVideo {
NSString *videoURLString = #"http://myite.com/dev/iphone/uploads/t69566.mov";
NSURL *videoURL = [NSURL URLWithString:videoURLString];
MPMoviePlayerViewController *moviePlayerView = [[[MPMoviePlayerViewController alloc] initWithContentURL:videoURL] autorelease];
[self presentMoviePlayerViewControllerAnimated:moviePlayerView];
}
Now of coarse I am gong to make openVideo dynamic with the population of video post but I am stuck on taking this video and grabbing a frame or thumbnail and displaying it.
Suggestions? thoughts?
UPDATE:
I want to take a thumbnail from a video taken from server. which actually brings me to a question.
When the user first uploads the video, would it be better to just create a thumbnail there and upload it to my server and just associate that with the video on grabbing them to populate a news feed type?
You can do it using the AVAssetImageGenerator. Rough code, copied and pasted from a working project (but might not be properly isolated):
_thumbnailView is an UIImageView to display the thumbnail.
_activityView is a UIActivityIndicatorView that gets hidden when the thumbnail finishes loading.
AVPlayerItem *playerItem = [[AVPlayerItem playerItemWithURL:movieURL] retain];
AVAssetImageGenerator *_generator;
_generator = [[AVAssetImageGenerator assetImageGeneratorWithAsset:playerItem.asset] retain];
[playerItem release];
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
if (result == AVAssetImageGeneratorSucceeded) {
UIImage *thumb = [UIImage imageWithCGImage:image];
[_thumbnailView setImage:thumb forState:UIControlStateNormal];
} else {
DLog(#"%s - error: %#", __PRETTY_FUNCTION__, error);
}
dispatch_async(dispatch_get_main_queue(), ^{
_thumbnailView.hidden = NO;
_playButton.hidden = NO;
[_activityView stopAnimating];
});
};
[_generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:CMTimeMakeWithSeconds(30,30)]] completionHandler:handler];
Back to your question, in my opinion, a server side generated thumbnail is usually better, as servers have way more processing power. Also, in order to get this thumbnail you need to start downloading the actual video from the server.
Finally, not that you pass a CMTime parameter including a call to CMTimeMakeWithSeconds(). This might prove problematic, as you can easily hit a blank frame. This is why we are using 30 as the parameter, so we avoid that situation in our videos.
I am recording a video from the iPhone camera by using the AVCam code provided from apple.
After the video is recorded it is saved to the photos library.
A new view is then loaded, here I need to have an image thumbnail of the video.
I have a path to the video:
file://localhost/private/var/mobile/Applications/ED45DEFC-ABF9-4A5E-9102-21680CC1448E/tmp/output.mov
I can't seem to figure how to get the first frame of the video to use as a thumbnail.
Any help would be very appreciated and thank you for your time.
EDIT
I ended up using this, I'm not sure why it returns the image sideways?
- (UIImage*)loadImage {
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vidURL 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];
NSLog(#"err==%#, imageRef==%#", err, imgRef);
return [[UIImage alloc] initWithCGImage:imgRef];
}
To fix the thumbnail orientation set appliesPreferredTrackTransform to YES in the AVAssetImageGenerator instance. If you add your own video composition, you'll need to include the right transform to rotate the video as wanted.
generate.appliesPreferredTrackTransform = YES;
Remember to release the obtained image reference with CGImageRelease.
To request multiple thumbnails it's better to do asynchronously with generateCGImagesAsynchronouslyForTimes:completionHandler:.