2011-04-16 89 views
41

在录制视频之前调用摄像头视图时,我已经实现了一个叠加视图。iPhone:以编程方式压缩录制的视频以分享?

pickerController.cameraOverlayView =myOverlay; 

视频录制和录制视频,并通过电子邮件等分享一切工作正常后,保存视频到相册。

如果我使用视频质量作为“高质量”,那么录制的视频已经变得非常庞大。例如,如果我以高质量录制视频30秒,录制的视频已经变成大约30 - 40 MB。

pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; 

如何在共享之前压缩高质量录制的视频,例如苹果如何使用内置录像机?

请指导我解决这个问题。

谢谢!

更新:

这就是我想要最近,但仍然没有成功:我要压缩拍摄录制的视频里面说到didFinishPickingMediaWithInfo并存储在同一相册实际的视频路径本身,而不是其他地方。我测试了同样的视频压缩到非常小的尺寸时,我从照片库中选择,但从摄像头拍摄并通过didFinishPickingMediaWithInfo传来的相同视频不压缩,虽然我使用下面的AVAssetExportSession代码。

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

    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; 


if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) 
{ 

    NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; 
    NSString *urlPath = [videoURL path]; 

    if ([[urlPath lastPathComponent] isEqualToString:@"capturedvideo.MOV"]) 
    { 
     if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (urlPath)) 
     { 
      [self copyTempVideoToMediaLibrary :urlPath]; 


     } 
     else 
     { 
      NSLog(@"Video Capture Error: Captured video cannot be saved...didFinishPickingMediaWithInfo()");     
     } 
    }  
    else 
    { 
     NSLog(@"Processing soon to saved photos album...else loop of lastPathComponent..didFinishPickingMediaWithInfo()"); 
    } 
}  
[self dismissModalViewControllerAnimated:YES]; 
} 

- (void)copyTempVideoToMediaLibrary :(NSString *)videoURL { 

     dispatch_queue_t mainQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

dispatch_async(mainQueue, ^{ 

    ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease]; 

    ALAssetsLibraryWriteVideoCompletionBlock completionBlock = ^(NSURL *assetURL, NSError *error) { 
     NSLog(@"Saved URL: %@", assetURL); 
     NSLog(@"Error: %@", error); 

     if (assetURL != nil) { 

      AVURLAsset *theAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:videoURL] options:nil]; 

      NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:theAsset]; 

      AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:theAsset presetName:AVAssetExportPresetLowQuality]; 

      [exportSession setOutputURL:[NSURL URLWithString:videoURL]]; 
      [exportSession setOutputFileType:AVFileTypeQuickTimeMovie]; 

      [exportSession exportAsynchronouslyWithCompletionHandler:^ { 
       switch ([exportSession status]) { 
        case AVAssetExportSessionStatusFailed: 
         NSLog(@"Export session faied with error: %@", [exportSession error]); 
         break; 
        default: 
         //[self mediaIsReady]; 
         break; 
       } 
      }]; 
     } 
    }; 

    [library writeVideoAtPathToSavedPhotosAlbum:[NSURL URLWithString:videoURL] completionBlock:completionBlock]; 
}); 
} 
+1

会是怎样降低视频质量和压缩其之间的差异压缩视频?或者你的意思是压缩像压缩? – 2011-04-19 12:36:31

回答

65

如果要压缩为远程共享视频,并保持在iPhone上本地存储的原有品质,你应该看看AVAssetExportSessionAVAssetWriter

另请参阅iOS管理Assets

- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL 
            outputURL:(NSURL*)outputURL 
            handler:(void (^)(AVAssetExportSession*))handler 
{ 
    [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil]; 
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil]; 
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality]; 
    exportSession.outputURL = outputURL; 
    exportSession.outputFileType = AVFileTypeQuickTimeMovie; 
    [exportSession exportAsynchronouslyWithCompletionHandler:^(void) 
    { 
     handler(exportSession); 
     [exportSession release]; 
    }]; 
} 

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

{ 
    NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; 
    NSURL *outputURL = [NSURL fileURLWithPath:@"/Users/josh/Desktop/output.mov"]; 
    [self convertVideoToLowQuailtyWithInputURL:videoURL outputURL:outputURL handler:^(AVAssetExportSession *exportSession) 
    { 
     if (exportSession.status == AVAssetExportSessionStatusCompleted) 
     { 
      printf("completed\n"); 
     } 
     else 
     { 
      printf("error\n"); 

     } 
    }]; 

} 
+0

非常感谢Jojaba! – Getsy 2011-05-19 06:03:33

+0

嗨Jojaba,我仍然在努力。我使用UIImagePickerController从照片库中获取视频/选择,从照片库获取视频正在压缩视频(显示消息也是压缩..),点击“选择”后很好,但如果我允许从相机拍摄视频,然后单击上“使用”不会压缩拍摄的视频。点击“使用”时是否可以压缩视频?当我使用UIImagePickerController API时,它如何在默认情况下工作? – Getsy 2011-05-24 21:32:04

+0

我附加了示例代码给答案。 – tidwall 2011-05-25 06:29:05

12

我猜这个视频已经被h264编解码器压缩了。但是您可以尝试使用AVFoundation从相机捕捉视频文件。但我怀疑你最终会得到相同的文件大小。

下面是iPhone 4上录制的10秒视频文件的一些统计信息,其中包含不同的质量预设。

high (1280х720) = ~14MB = ~11Mbit/s 
640 (640х480) = ~4MB = ~3.2Mbit/s 
medium (360х480) = ~1MB = ~820Kbit/s 
low (144х192) = ~208KB = ~170Kbit/s 
+0

感谢您提供此信息。就在这里,你可以看到这个问题... 14MB是一个10秒钟的视频大。并导致下降到480p降低质量显着 – zakdances 2012-08-04 22:27:41

+1

注意:这并不适用于较新的iPhone模型 - 即iPhone 5,5s等 – 2014-06-26 03:28:06

11
pickerController.videoQuality = UIImagePickerControllerQualityTypeMedium; 

这些都是你可以挑选所有值。

UIImagePickerControllerQualityTypeHigh = 0, 
UIImagePickerControllerQualityType640x480 = 3, 
UIImagePickerControllerQualityTypeMedium = 1, // default value 
UIImagePickerControllerQualityTypeLow  = 2 
+2

不知道是否有其他人有这个问题,但当我改变选择器质量(如上所示)它不会改变我的文件大小= \ – Ibdakine 2015-09-06 21:22:28

4

试试这几行字:

[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil]; 
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil]; 
    AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset: urlAsset presetName:AVAssetExportPresetLowQuality]; 
    session.outputURL = outputURL; 
    session.outputFileType = AVFileTypeQuickTimeMovie; 
    [session exportAsynchronouslyWithCompletionHandler:^(void) 
    { 
     handler(session); 

    }]; 
3

编程压缩视频使用SWIFT

而且不要忘了补充 - 进口AssetsLibrary

func convertVideoWithMediumQuality(inputURL : NSURL){ 

      let VideoFilePath = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("mergeVideo\(arc4random()%1000)d").URLByAppendingPathExtension("mp4").absoluteString 
      if NSFileManager.defaultManager().fileExistsAtPath(VideoFilePath) { 
       do { 
        try NSFileManager.defaultManager().removeItemAtPath(VideoFilePath) 
       } catch { } 
      } 

      let savePathUrl = NSURL(string: VideoFilePath)! 

      let sourceAsset = AVURLAsset(URL: inputURL, options: nil) 

      let assetExport: AVAssetExportSession = AVAssetExportSession(asset: sourceAsset, presetName: AVAssetExportPresetMediumQuality)! 
      assetExport.outputFileType = AVFileTypeQuickTimeMovie 
      assetExport.outputURL = savePathUrl 
      assetExport.exportAsynchronouslyWithCompletionHandler {() -> Void in 

       switch assetExport.status { 
       case AVAssetExportSessionStatus.Completed: 
        dispatch_async(dispatch_get_main_queue(), { 
         do { 
          let videoData = try NSData(contentsOfURL: savePathUrl, options: NSDataReadingOptions()) 
          print("MB - \(videoData.length/(1024 * 1024))") 
         } catch { 
          print(error) 
         } 

        }) 
       case AVAssetExportSessionStatus.Failed: 
        self.hideActivityIndicator(self.view) 
        print("failed \(assetExport.error)") 
       case AVAssetExportSessionStatus.Cancelled: 
        self.hideActivityIndicator(self.view) 
        print("cancelled \(assetExport.error)") 
       default: 
        self.hideActivityIndicator(self.view) 
        print("complete") 
       } 
      } 

     } 
+0

谢谢!这对我来说至少工作得很好 – b3rge 2016-05-06 21:02:04

+2

很酷。为什么使用随机文件名?这看起来很可疑。如果您多次调用此方法并且希望避免名称冲突,那么使用随机文件名不会总是有效并导致问题。如果您一次只调用一个,则不需要随机文件名。我建议使用更确定性的命名方案(计数器等) – n13 2016-07-30 12:01:04

2

我找到了一个极好的自定义类(SDAVAssetExportSession)进行视频压缩。你可以从这个link下载它。

下载后,将SDAVAssetExportSession.h和SDAVAssetExportSession.m文件添加到您的项目中,然后下面的代码将帮助执行压缩。 在下面的代码,你可以通过指定比特率的分辨率和

#import "SDAVAssetExportSession.h" 


- (void)compressVideoWithInputVideoUrl:(NSURL *) inputVideoUrl 
{ 
    /* Create Output File Url */ 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSString *finalVideoURLString = [documentsDirectory stringByAppendingPathComponent:@"compressedVideo.mp4"]; 
    NSURL *outputVideoUrl = ([[NSURL URLWithString:finalVideoURLString] isFileURL] == 1)?([NSURL URLWithString:finalVideoURLString]):([NSURL fileURLWithPath:finalVideoURLString]); // Url Should be a file Url, so here we check and convert it into a file Url 


    SDAVAssetExportSession *compressionEncoder = [SDAVAssetExportSession.alloc initWithAsset:[AVAsset assetWithURL:inputVideoUrl]]; // provide inputVideo Url Here 
    compressionEncoder.outputFileType = AVFileTypeMPEG4; 
    compressionEncoder.outputURL = outputVideoUrl; //Provide output video Url here 
    compressionEncoder.videoSettings = @ 
    { 
    AVVideoCodecKey: AVVideoCodecH264, 
    AVVideoWidthKey: @800, //Set your resolution width here 
    AVVideoHeightKey: @600, //set your resolution height here 
    AVVideoCompressionPropertiesKey: @ 
     { 
     AVVideoAverageBitRateKey: @45000, // Give your bitrate here for lower size give low values 
     AVVideoProfileLevelKey: AVVideoProfileLevelH264High40, 
     }, 
    }; 
    compressionEncoder.audioSettings = @ 
    { 
    AVFormatIDKey: @(kAudioFormatMPEG4AAC), 
    AVNumberOfChannelsKey: @2, 
    AVSampleRateKey: @44100, 
    AVEncoderBitRateKey: @128000, 
    }; 

    [compressionEncoder exportAsynchronouslyWithCompletionHandler:^ 
    { 
     if (compressionEncoder.status == AVAssetExportSessionStatusCompleted) 
     { 
      NSLog(@"Compression Export Completed Successfully"); 
     } 
     else if (compressionEncoder.status == AVAssetExportSessionStatusCancelled) 
     { 
      NSLog(@"Compression Export Canceled"); 
     } 
     else 
     { 
       NSLog(@"Compression Failed"); 

     } 
    }]; 

} 

要取消压缩使用以下线路码

[compressionEncoder cancelExport]; //Video compression cancel 
+0

我得到错误 - [AVAssetWriter startSessionAtSourceTime:]无效参数不令人满意:CMTIME_IS_NUMERIC(startTime) 使用sdavexportsession – starterMac 2018-03-08 05:51:29