2011-08-02 23 views
24

jestem przechwytywania wideo za pomocą następującego kodu:jak zapisać plik wideo do katalogu dokumentów

UIImagePickerController *ipc = [[UIImagePickerController alloc] init]; 
ipc.sourceType = UIImagePickerControllerSourceTypeCamera; 
ipc.delegate = self; 
//need to handle delegates methods 
// 
ipc.allowsEditing = YES; 
ipc.videoQuality = UIImagePickerControllerQualityTypeMedium; 
ipc.videoMaximumDuration = 30.0f; // 30 seconds 
//temporary duation of 30 seconds for testing 

ipc.mediaTypes = [NSArray arrayWithObject:@"public.movie"]; 
// ipc.mediaTypes = [NSArray arrayWithObjects:@"public.movie", @"public.image", nil]; 
[self presentModalViewController:ipc animated:YES]; 
//this controller allows to record the videos 

i mogę zapisać nagrany na płycie za pomocą następującego kodu

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    // recover video URL 
    NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL]; 

    // check if video is compatible with album 
    BOOL compatible = UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([url path]); 

    // save 
    if (compatible){ 
     UISaveVideoAtPathToSavedPhotosAlbum([url path], self, @selector(video:didFinishSavingWithError:contextInfo:), NULL); 
     NSLog(@"saved!!!! %@",[url path]); 
    } 
    [self dismissModalViewControllerAnimated:YES]; 
    [picker release]; 
} 

ale muszę odzyskać że plik z albumu i trzeba przechowywać w katalogu dokumentów?

+1

Czy znaleziono jeszcze rozwiązania? –

Odpowiedz

29

Zapisywanie wideo do katalogu dokumentów jest następująca:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 

    NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; 
    NSData *videoData = [NSData dataWithContentsOfURL:videoURL]; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *tempPath = [documentsDirectory stringByAppendingFormat:@"/vid1.mp4"]; 
    BOOL success = [videoData writeToFile:tempPath atomically:NO]; 
    [picker dismissModalViewControllerAnimated:YES]; 
} 
+2

Dlaczego atomowy jest ustawiony na NIE dla [videoData writeToFile: tempPath atomically: NO]? – zakdances

+0

Mam również pytanie uzupełniające. Czy istnieje sposób na zapisanie wideo, ale bez kompresji? Skopiować pliki wideo w taki sposób, w jaki jest. – Jonny

+0

To działa dla mnie. –

4
#pragma mark - 
#pragma mark File Names and Paths 
// Creates the path if it does not exist. 
- (void)ensurePathAt:(NSString *)path { 
    NSFileManager *fm = [NSFileManager defaultManager]; 
    if ([fm fileExistsAtPath:path] == false) { 
     [fm createDirectoryAtPath:path 
     withIntermediateDirectories:YES 
         attributes:nil 
          error:NULL]; 
    } 
} 
- (NSString *)documentPath { 
    if (! documentPath_) { 
     NSArray *searchPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     documentPath_ = [searchPaths objectAtIndex: 0]; 
     documentPath_=[documentPath_ stringByAppendingPathComponent:@"VideoAlbum"]; 
     [documentPath_ retain]; 
    } 
    return documentPath_; 
} 

- (NSString *)audioPath { 
    if (! AudioPath_) { 
     AudioPath_ = [[self documentPath] stringByAppendingPathComponent:@"Demo"]; 
     NSLog(@"%@",AudioPath_); 
     [AudioPath_ retain]; 
     [self ensurePathAt:AudioPath_]; 
    } 
    return AudioPath_; 
} 
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; 

    if ([type isEqualToString:(NSString *)kUTTypeVideo] || [type isEqualToString:(NSString *)kUTTypeMovie]) 
    { 
     NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; 

     NSData *videoData = [NSData dataWithContentsOfURL:videoURL]; 
     tempPath = [[self audioPath] stringByAppendingFormat:@"/%@.mp4",[NSDate date]]; 
     BOOL success = [videoData writeToFile:tempPath atomically:NO]; 

     NSLog(@"%hhd",success); 
    } 
    [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil]; 
} 
0
videoUrl = [info objectForKey:UIImagePickerControllerMediaURL]; 
urlString=[urlvideo path]; 
NSLog(@"path url %@",videoUrl); 
NSData *videoData = [NSData dataWithContentsOfURL:videoUrl]; 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *sourcePath = [documentsDirectory stringByAppendingPathComponent:@"yourfilename.mp4"]; 

[videoData writeToFile:sourcePath atomically:YES]; 
//Below code will save video to iOS Device 
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init]; 
[library writeVideoAtPathToSavedPhotosAlbum:videoUrl 
          completionBlock:^(NSURL *assetURL, NSError *error){/*notify of completion*/}]; 

[picker dismissViewControllerAnimated:YES completion:nil]; 

Nadzieja ta pomoc

2

Możemy użyć moveItemAtPath:toPath:error: metodę NSFileManager by przenieść plik wideo do dokumentu naszej aplikacji informator. Jest bardziej wydajny.

Powinniśmy również uzyskać rozszerzenie pliku wideo i użyć go jako rozszerzenia naszej lokalnej nazwy pliku wideo.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    [self dismissViewControllerAnimated:YES completion:nil] ; 

    if ([info[UIImagePickerControllerMediaType] isEqualToString:(NSString *)kUTTypeMovie]) { 
     // video 
     NSURL *url = [info[UIImagePickerControllerMediaType] ; 
     NSString *filePath = [url path] ; 
     NSString *pathExtension = [filePath pathExtension] ; 
     if ([pathExtension length] > 0) { 
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ; 
      NSString *documentsDirectory = [paths objectAtIndex:0] ; 
      NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"temp.%@", pathExtension]] ; 
      NSError *error = nil ; 
      BOOL res = [[NSFileManager defaultManager] moveItemAtPath:filePath toPath:localFilePath error:&error] ; 
      if (!res) { 
       NSLog(@"%@", [error localizedDescription]) ; 
      } 
     } 
    } 
} 

To działa dla mnie.

+0

Dobrze, dobrze mi też działa. Aktualizacja dla Swift 4.0: niech pathExtension = videoPath.pathExtension jeśli pathExtension.isEmpty, niech documentsDirectory = FileManager.default.urls (dla: .documentDirectory, w: .userDomainMask)! .first { niech plik_lokalny = documentsDirectory.appendingPathComponent ("temp. \ (pathExtension)") ścieżka do { wypróbuj FileManager.default.moveItem (atPath: videoPath.path, toPath: localFile) } catch { print ("Nie można przenieść wideo \ (błąd)") } } – Tony

3

Bit R & D, to pracował dla mnie

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 

{

NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL]; 
    // Save video to app document directory 

NSString *filePath = [url path]; 
NSString *pathExtension = [filePath pathExtension] ; 
if ([pathExtension length] > 0) 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ; 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 

    NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", [filePath lastPathComponent]]]; 

    // Method last path component is used here, so that each video saved will get different name. 

    NSError *error = nil ; 
    BOOL res = [[NSFileManager defaultManager] moveItemAtPath:filePath toPath:localFilePath error:&error] ; 

    if (!res) 
    { 
     NSLog(@"%@", [error localizedDescription]) ; 
    } 
    else 
    { 
     NSLog(@"File saved at : %@",localFilePath); 
    } 
} 

}

// Również, gdy trzeba sprawdzić na samym filmie już istnieją w dokumencie aplikacji i nie chcesz tworzyć wielu kopii, a następnie wprowadzić pewne zmiany poniżej:

NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL]; 
NSURL *videoAsset = [info objectForKey:UIImagePickerControllerReferenceURL]; 

__weak typeof(self) weakSelf = self; 

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
[library assetForURL:videoAsset resultBlock:^(ALAsset *asset) 
{ 
    weakSelf.selectedFileName = [[asset defaultRepresentation] filename]; 
    NSLog(@"Video Filename %@",weakSelf.selectedFileName); 

    // Save video to doc directory 
    NSString *filePath = [url path]; 
    NSString *pathExtension = [filePath pathExtension] ; 
    if ([pathExtension length] > 0) 
    { 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ; 
     NSString *documentsDirectory = [paths objectAtIndex:0]; 

     NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", weakSelf.selectedFileName]]; 

     //check if same video is having its copy in app directory. 
     //so that multiple entries of same file should not happen. 

     BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:localFilePath]; 

     if (!fileExists) 
     { 
      NSError *error = nil ; 

      BOOL res = [[NSFileManager defaultManager] moveItemAtPath:filePath toPath:localFilePath error:&error] ; 

      if (!res) 
      { 
       NSLog(@"%@", [error localizedDescription]) ; 
      } 
      else 
      { 
       NSLog(@"File saved at : %@",localFilePath); 
       weakSelf.filePathURL = [NSURL URLWithString:localFilePath]; 
      } 
     } 
     else 
     { 
      NSLog(@"File exist at : %@",localFilePath); 
      weakSelf.filePathURL = [NSURL URLWithString:localFilePath]; 
     } 

    } 
} 

}

// Gdzie weakSelf.selectedFileName & weakSelf.filePathURL są właściwościami typu NSString i bibliotece NSURL mojej klasie odpowiednio.

+0

Niestety, uważam, że ALAssets Library jest przestarzałe. Potrzebne jest PHPhoto, metinks. –

8

Oto swift code jeśli ktoś to potrzebne w przyszłości:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { 

    let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL 
    let videoData = NSData(contentsOfURL: videoURL) 
    let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) 
    let documentsDirectory: AnyObject = paths[0] 
    let dataPath = documentsDirectory.stringByAppendingPathComponent("/vid1.mp4") 

    videoData?.writeToFile(dataPath, atomically: false) 
    self.dismissViewControllerAnimated(true, completion: nil) 

} 
+0

Możliwe jest również określenie pierwszych ścieżek, z tą korzyścią, że nie zawiedzie, jeśli lista ma zerową długość. –

0
videoURL = info[UIImagePickerControllerMediaURL]as? NSURL 
    print(videoURL!) 

    let urlData=NSData(contentsOf: videoURL as! URL) 

    if((urlData) != nil) 
    { 
     let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 
     let documentDirectory = path.first! as NSString 
     let fileName = "Video.MOV" 
     let PDFPathFileName = documentDirectory.appendingPathComponent(fileName as String) 

     print(PDFPathFileName) 

     DispatchQueue.main.async(execute: { 
      urlData?.write(toFile: PDFPathFileName, atomically: true) 
     }) 

     do { 
      let asset = AVURLAsset(url: videoURL as! URL , options: nil) 
      let imgGenerator = AVAssetImageGenerator(asset: asset) 
      imgGenerator.appliesPreferredTrackTransform = true 
      let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(0, 1), actualTime: nil) 
      let thumbnail = UIImage(cgImage: cgImage) 
      imgView.image = thumbnail 
      // thumbnail here 

     } catch let error { 
      print("*** Error generating thumbnail: \(error.localizedDescription)") 
     } 

    } 
    self.dismiss(animated: true, completion: nil) 
0

Swift 3/4

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { 
     // recover video URL 
     let url = info[UIImagePickerControllerMediaURL] as? URL 
     // check if video is compatible with album 
     let compatible: Bool = UIVideoAtPathIsCompatibleWithSavedPhotosAlbum((url?.path)!) 
     // save 
     if compatible { 
      UISaveVideoAtPathToSavedPhotosAlbum((url?.path)!, self, nil, nil) 
      print("saved!!!! \(String(describing: url?.path))") 
     } 
     dismiss(animated: true, completion: nil) 
    } 
// error 
    func video(_ videoPath: String, didFinishSavingWithError error: Error?, contextInfo: UnsafeMutableRawPointer) { 
    } 

oszczędność przykład Ścieżka: -

"/private/var/mobile/Containers/Data/Application/EA53C844-7931-446C-800D-DA90717426BB/tmp/xxxxxx.MOV" 
0

Wystarczy zadzwonić tej funkcji, i to zrobi wszystko, co dla ciebie :)

private func saveVideo(url:URL) { 
    DispatchQueue.global(qos: .userInitiated).async { 
     guard let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } 
     if !FileManager.default.fileExists(atPath: documentsDirectoryURL.appendingPathComponent(url.lastPathComponent).path) { 
      URLSession.shared.downloadTask(with: url) { (location, response, error) -> Void in 
       guard let location = location else { return } 
       let destinationURL = documentsDirectoryURL.appendingPathComponent(response?.suggestedFilename ?? url.lastPathComponent) 

       do { 
        try FileManager.default.moveItem(at: location, to: destinationURL) 
        PHPhotoLibrary.requestAuthorization({ (authorizationStatus: PHAuthorizationStatus) -> Void in 
         if authorizationStatus == .authorized { 
          PHPhotoLibrary.shared().performChanges({ 
           PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: destinationURL)}) { completed, error in 
            DispatchQueue.main.async { 
             if completed { 
              self.view.makeToast(NSLocalizedString("Video Saved!", comment: "Video Saved!"), duration: 3.0, position: .center) 
             } else { 
              print(error!) 
             } 
            } 
          } 
         } 
        }) 
       } catch { print(error) } 

       }.resume() 
     } else { 
      print("File already exists at destination url") 
     } 
    } 
} 
Powiązane problemy