iPhone:以编程方式压缩录制的视频以进行共享?

时间:2011-04-16 14:58:25

标签: iphone

我在录制视频之前调用了摄像机视图时实现了叠加视图。

pickerController.cameraOverlayView =myOverlay;

视频录制并在录制视频并通过电子邮件等共享后将视频保存到相册中。一切正常。

如果我将视频质量用作“高品质”,则录制的视频已变得庞大。例如,如果我以高质量录制视频30秒,则录制的视频大约为30 - 40 mb。

pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;

如何在共享之前对高质量录制视频进行压缩编程,就像Apple使用内置录像机一样?

请指导我解决此问题。

谢谢!

更新:

这是我最近的尝试,但仍然没有成功:我想压缩拍摄的录制视频来到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];
});
}

7 个答案:

答案 0 :(得分:67)

如果您要压缩视频以进行远程共享并保持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");

         }
     }];

}

答案 1 :(得分: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

答案 2 :(得分:11)

pickerController.videoQuality = UIImagePickerControllerQualityTypeMedium;

这些是您可以选择的所有值。

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

答案 3 :(得分:5)

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

        }

答案 4 :(得分: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);

    }];

答案 5 :(得分:1)

我找到了一个很棒的自定义类(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

答案 6 :(得分:0)

我破解了这个。

使用exportSession.fileLengthLimit = 1048576 * 10 //10 MB

10MB是硬编码号码。根据所需的比特率使用。