【问题标题】:how to save video file into document directory如何将视频文件保存到文档目录
【发布时间】:2011-08-02 17:49:40
【问题描述】:

我正在使用以下代码捕获视频:

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

我可以使用以下代码将录制的视频保存到相册

- (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];
}

但我需要从相册中检索该文件并需要存储到文档目录中?

【问题讨论】:

  • 您找到解决方案了吗?

标签: ios objective-c iphone video


【解决方案1】:

将视频保存到documents目录如下:

- (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];
}

【讨论】:

  • 为什么 [videoData writeToFile:tempPath atomically:NO] 自动设置为 NO?
  • 我也有一个后续问题。有没有办法保存视频但没有任何压缩?即按原样复制视频文件。
  • 为什么保存为mp4?文件类型也可以是MOV吧?
【解决方案2】:

如果将来有人需要,这里是 swift 代码:

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)

}

【讨论】:

  • 您也可以指定paths.first,其优点是如果列表长度为零,则不会失败。
  • 如果有人遇到这个问题,你可以试试 videoData?.write(to: dataPath, options: .withoutOverwriting) .. 这对我有用。
【解决方案3】:
#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];
}

【讨论】:

    【解决方案4】:

    一点研发,这对我有用

    - (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);
        }
    }
    

    }

    //此外,当您必须检查应用文档目录中是否已经存在相同的视频并且您不想创建多个副本时,请进行如下更改

    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];
            }
    
        }
    }
    

    }

    //其中weakSelf.selectedFileName和weakSelf.filePathURL分别是我类的NSString和NSURL类型属性。

    【讨论】:

    • 唉,我相信 ALAssetsLibrary 已被弃用。我认为需要 PHPhoto。
    【解决方案5】:

    我们可以使用 NSFileManager 的moveItemAtPath:toPath:error: 方法将视频文件移动到我们应用的文档目录中。效率更高。

    我们还应该获取视频文件的扩展名并将其用作本地视频文件名的扩展名。

    - (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]) ;
                }
            }
        }
    }
    

    它对我有用。

    【讨论】:

    • 很好,对我也很好。 Swift 4.0 更新: let pathExtension = videoPath.pathExtension if !pathExtension.isEmpty, let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { let localFile = documentsDirectory.appendingPathComponent("temp.( pathExtension)").path do { try FileManager.default.moveItem(atPath: videoPath.path, toPath: localFile) } catch { print("Cannot move the video (error)") } }
    【解决方案6】:
     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];
    

    希望有帮助

    【讨论】:

      【解决方案7】:
          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)
      

      【讨论】:

        【解决方案8】:

        斯威夫特 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) {
            }
        

        保存示例路径:-

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

        【讨论】:

          【解决方案9】:

          只要调用这个函数,它就会为你做每一件事:)

              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")
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2019-07-05
            • 2015-02-04
            • 1970-01-01
            • 1970-01-01
            • 2016-06-24
            • 1970-01-01
            • 1970-01-01
            • 2015-10-05
            • 1970-01-01
            相关资源
            最近更新 更多