I am working on adding video to a chat application. The users can either share a video chosen from their files or record a new one to upload.
The issue I am having is differentiating between a video which has just been recorded and a video which has been selected as I want to save a just recorded video to their album when they upload it.
Currently my code looks like this:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// This checks whether we are adding image or video (public.movie for video)
if ([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:#"public.image"]) {
UIImage * image = [info objectForKey:UIImagePickerControllerEditedImage];
[self sendImage:image];
}
else {
// SS-V
// If we are dealing with a video then we want to return to the chat view and post the video
NSURL * videoURL = (NSURL *)[info objectForKey:UIImagePickerControllerMediaURL];
// Send video to the chat view
[self sendVideo:[videoURL absoluteString]];
}
[tableView reloadData];
[picker dismissViewControllerAnimated:YES completion:Nil];
}
So I am getting the local url of the video and then uploading it to an external database.
I have also got this code:
// Save the recorded video to the iPhone
NSString * videoCompatibleString = [videoURL.absoluteString stringByReplacingOccurrencesOfString:#"file://" withString:#""];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(videoCompatibleString)) {
UISaveVideoAtPathToSavedPhotosAlbum (videoCompatibleString, self, nil, nil);
}
Which will save it to my phone library.
So now my only issue is how to differentiate between a video just taken and a video selected from my library already.
I was hoping there would be an elegant way of achieving this. Seemingly there isn't and so I set up an enum to record what I loaded the image picker with, if I loaded it with the camera then I knew that I would be taking the video or picture so should add it to the album:
In the header file:
typedef enum {
bPictureTypeCamera,
bPictureTypeAlbumImage,
bPictureTypeAlbumVideo,
} bPictureType;
// This allows us to see what kind of media is being sent to know if we need to save it to album
bPictureType _pictureType;
In the main file:
// If we have just taken the media then save it to the users camera
if (_pictureType == bPictureTypeCamera) {
[self saveMediaWithInfo:info];
}
With my save function checking if it is video or image and saving it:
- (void)saveMediaWithInfo: (NSDictionary *)info {
// Save image
if ([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:#"public.image"]) {
UIImageWriteToSavedPhotosAlbum([info objectForKey:UIImagePickerControllerEditedImage], self, nil, nil);
}
// Save Video
else {
// Make sure the video is in a compatible format to save
NSURL * videoURL = (NSURL *)[info objectForKey:UIImagePickerControllerMediaURL];
NSString * videoCompatibleString = [[videoURL absoluteString] stringByReplacingOccurrencesOfString:#"file://" withString:#""];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (videoCompatibleString)) {
UISaveVideoAtPathToSavedPhotosAlbum (videoCompatibleString, self, nil, nil);
}
}
}
Now the neatest answer but it does what it needs to
Related
I am using ELCImagePickerController for multiple video selection. But I want to get size of selected video. When user click on any video, then their video size is check.
Right now, all selected video information is getting in:
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
for (NSDictionary *dict in info) {
NSUrl *video url = [dict objectForKey:UIImagePickerControllerReferenceURL];
NSLog(#"Video information is ::",url);
}
}
I can find the video size in didFinishPickingMediaWithInfo: method . But this method is called when user select all video. But I want to restrict user from selection of large size file.
I want to get video information when a user click on video ,If user click on one video then that video size is get and show a alert related to large size .
Following is called when user tap on a video for selecting. But I am unable to get video information at this time .
ELCImagePickerController.m
- (BOOL)shouldSelectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previousCount
{
BOOL shouldSelect = previousCount < self.maximumImagesCount;
if (!shouldSelect) {
NSString *title = [NSString stringWithFormat:NSLocalizedString(#"Only %d Video please!", nil), self.maximumImagesCount];
NSString *message = [NSString stringWithFormat:NSLocalizedString(#"You can only upload %d Videos at a time.", nil), self.maximumImagesCount];
[[[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(#"Okay", nil), nil] show];
}
return shouldSelect;
}
Check the below code Length:`
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:yourVideoUrl];
CMTime duration = playerItem.duration;
float seconds = CMTimeGetSeconds(duration);
NSLog(#"duration: %.2f", seconds);`
Check the below code Size:
There are 1024 bytes in a kilobyte and 1024 kilobytes in a megabyte
NSData * movieData = [NSData dataWithContentsOfURL:yourVideoUrl];
NSLog(#"%.2f",(float)movieData.length/1024.0f/1024.0f);
I am trying to develop an app that can record video then attach it to email.
Here's what I did, but it isn't working.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
[self dismissModalViewControllerAnimated:NO];
// Handle a movie capture
if (CFStringCompare ((__bridge_retained CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) {
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath)) {
UISaveVideoAtPathToSavedPhotosAlbum(moviePath, self,
#selector(video:didFinishSavingWithError:contextInfo:), nil);
videoURL = [[NSURL URLWithString:moviePath] init];
}
}
}
For Attachment:
[tempMailCompose addAttachmentData:[NSData dataWithContentsOfURL:videoURL] mimeType:#"video/MOV" fileName:#"defectVideo.MOV"];
The video recording and saving it to Photo Library is working good, my problem is the attachment.
What could be wrong?
For attachment you must use NSData. in case video attachment you have to use MimeType #"video/quicktime".
For more clarification please refer apple documentation.
MFMailComposeViewController
For attachment in mail use the following code :
[tempMailCompose addAttachmentData:[NSData dataWithContentsOfURL:videoURL] mimeType:#"video/quicktime" fileName:#"defectVideo.MOV"];
and rest of part is ok, i think.
I figured it out, here:
I replaced this...
videoURL = [[NSURL URLWithString:moviePath] init];
With this...
videoURL = [[NSURL alloc] initFileURLWithPath:moviePath];
It's working now.
I am working on an iOS app and I recently implemented a imagePicker in a popover that allows a user to record photos and videos. I would like to store these in the iPad's photo roll so that the user can sync them in iTunes later. I've been able to do this successfully, but I would like to give each photo and video a unique name that contains useful information about the photo and video so I can load them later. Specifically, I would like to store the photo using a property of the class, live_trial_id, as the filename. Below is the code that I am currently using to store my photos and videos to the photo roll. I understand that I could do this with metadata for pictures, but for the videos I am lost. Thanks in advance for any help with this issue!
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
UIImage *originalImage, *editedImage, *imageToSave;
// Handle a still image capture
if( [mediaType isEqualToString:#"public.image"]){
editedImage = (UIImage *) [info objectForKey:
UIImagePickerControllerEditedImage];
originalImage = (UIImage *) [info objectForKey:
UIImagePickerControllerOriginalImage];
if (editedImage) {
imageToSave = editedImage;
} else {
imageToSave = originalImage;
}
// Get the image metadata
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypeCamera)
{
NSDictionary *imageMetadata = [info objectForKey:
UIImagePickerControllerMediaMetadata];
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteImageCompletionBlock imageWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library");
}
};
// Save the new image (original or edited) to the Camera Roll
[library writeImageToSavedPhotosAlbum:[imageToSave CGImage]
metadata:imageMetadata
completionBlock:imageWriteCompletionBlock];
}
}
if ([mediaType isEqualToString:#"public.movie"]) {
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypeCamera)
{
NSURL *mediaURL = [info objectForKey:UIImagePickerControllerMediaURL];
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteVideoCompletionBlock videoWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library");
}
};
// Save the new image (original or edited) to the Camera Roll
[library writeVideoAtPathToSavedPhotosAlbum:mediaURL
completionBlock:videoWriteCompletionBlock];
}
}
I would also like to avoid creating a custom library or custom metadata if at all possible. I really just wanted to change the filename on the way to the photo roll
I ended up answering my own question. What I wanted to do was to save to the application's documents directory instead of the photo roll. This allowed me to access the files that I had saved and also to sync them to the computer when attached later.
I have a simple App than you have the possibility to choose an existent video from photo library or you can take a video with UIImagePickerController.
I added the following code for when I make a new video with camera I can save it in photo Gallery if I need in the future.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Get the selected Video.
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
// Convert to Video data.
NSData *imageData = [NSData dataWithContentsOfURL:videoURL];
// Save Video to Photo Album
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSURL *recordedVideoURL= [info objectForKey:UIImagePickerControllerMediaURL];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:recordedVideoURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:recordedVideoURL
completionBlock:^(NSURL *assetURL, NSError *error){}
];
}
[library release];
[picker dismissModalViewControllerAnimated:NO];
}
Now my issue is when I select a video from Photo Library this same video is duplicated as this code save always a new video.
Is it a way to detect if you selected the video from Photo Library ?
Before saving the video, check the imagePickerController's sourceType. Only save the video if sourceType is UIImagePickerControllerSourceTypeCamera.
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
// Save the video
}
I'm building an iOS app that allows the user to upload videos from UIImagePickerController, either by recording or choosing them from the Camera Roll, as well as also play the chosen video. My question is, how would I go about keeping a reference to the videos that have been chosen this way? I want to do this so that if the video is still present on the device, I can use the local file rather than streaming the uploaded file.
When
imagePickerController:didFinishPickingMediaWithInfo:
returns, the URL in:
[info objectForKey:UIImagePickerControllerMediaURL];
Is in the format of: "file://localhost/private/var/mobile/Applications/ /tmp//trim.z2vLjx.MOV"
I'm lead to believe that the "/tmp/" directory is temporary, and therefore not suitable to save the URL for that location.
I can get all of the videos on the device through ALAssetsLibrary, but because I don't have a way of distinguishing them, this doesn't help me. I've been attempting to use:
[result valueForProperty:ALAssetPropertyDate];
To distinguish the videos, but I need a way of getting the creation date from UIImagePickerController for this to be useful.
I've finally managed to find a solution:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if(CFStringCompare((CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo)
{
//Dismiss the media picker view
[picker dismissModalViewControllerAnimated:YES];
//Get the URL of the chosen content, then get the data from that URL
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSData *webData = [NSData dataWithContentsOfURL:videoURL];
//Gets the path for the URL, to allow it to be saved to the camera roll
NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (moviePath))
{
ALAssetsLibrary *lib = [[ALAssetsLibrary alloc] init];
//The key UIImagePickerControllerReferenceURL allows you to get an ALAsset, which then allows you to get metadata (such as the date the media was created)
[lib assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) {
NSLog(#"created: %#", [asset valueForProperty:ALAssetPropertyDate]);
} failureBlock:^(NSError *error) {
NSLog(#"error: %#", error);
}];
}
}
As per usual, the solution was found by reading the documentation a little more thoroughly. Hopefully this'll help someone else out at some point.
You can easily keep a record of the videos you have on the device. Either by keeping a data base (which I think would be too much) or just a file with a list of your videos. In that list, you could have the URL of the assets.