AVAssetWriter输出大文件(即使应用压缩设置)

我正在开发一个个人iOS项目,要求全屏video(15秒长)通过4G连接上传到后端。 虽然我可以拍摄video,但是文件的输出大小已经达到了30MB,这让我觉得我在压缩方面做了很大的错误。 以下是我用来设置AssetWriter的代码:

-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections { NSLog(@"Started Recording! *******************"); self.movieWriter = [AVAssetWriter assetWriterWithURL:fileURL fileType:AVFileTypeMPEG4 error:nil]; [self.movieWriter setShouldOptimizeForNetworkUse:YES]; NSDictionary *videoCleanApertureSettings = @{ AVVideoCleanApertureWidthKey: [NSNumber numberWithFloat:self.view.frame.size.width], AVVideoCleanApertureHeightKey: [NSNumber numberWithFloat:self.view.frame.size.height], AVVideoCleanApertureHorizontalOffsetKey: [NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey: [NSNumber numberWithInt:10], }; NSDictionary *videoCompressionSettings = @{ AVVideoAverageBitRateKey: [NSNumber numberWithFloat:5000000.0], AVVideoMaxKeyFrameIntervalKey: [NSNumber numberWithInteger:1], AVVideoProfileLevelKey: AVVideoProfileLevelH264Baseline30, AVVideoCleanApertureKey: videoCleanApertureSettings, }; NSDictionary *videoSettings = @{AVVideoCodecKey: AVVideoCodecH264, AVVideoWidthKey: [NSNumber numberWithFloat:self.view.frame.size.width], AVVideoHeightKey: [NSNumber numberWithFloat:self.view.frame.size.height], AVVideoCompressionPropertiesKey: videoCompressionSettings, }; self.movieWriterVideoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; self.movieWriterVideoInput.expectsMediaDataInRealTime = YES; [self.movieWriter addInput:self.movieWriterVideoInput]; NSDictionary *audioSettings = @{AVFormatIDKey: [NSNumber numberWithInteger:kAudioFormatMPEG4AAC], AVSampleRateKey: [NSNumber numberWithFloat:44100.0], AVNumberOfChannelsKey: [NSNumber numberWithInteger:1], }; self.movieWriterAudioInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:audioSettings]; self.movieWriterAudioInput.expectsMediaDataInRealTime = YES; [self.movieWriter addInput:self.movieWriterAudioInput]; [self.movieWriter startWriting]; } -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { NSLog(@"Done Recording!"); [self.movieWriterVideoInput markAsFinished]; [self.movieWriterAudioInput markAsFinished]; [self.movieWriter finishWritingWithCompletionHandler:^{ AVURLAsset *compressedVideoAsset = [[AVURLAsset alloc] initWithURL:self.movieWriter.outputURL options:nil]; //Upload video to server }]; } 

对于实际会话的设置,我使用下面的代码:

  //Indicate that some changes will be made to the session [self.captureSession beginConfiguration]; self.captureSession.sessionPreset = AVCaptureSessionPresetHigh; AVCaptureInput* currentCameraInput = [self.captureSession.inputs objectAtIndex:0]; for (AVCaptureInput *captureInput in self.captureSession.inputs) { [self.captureSession removeInput:captureInput]; } //Get currently selected camera and use for input AVCaptureDevice *videoCamera = nil; if(((AVCaptureDeviceInput*)currentCameraInput).device.position == AVCaptureDevicePositionBack) { videoCamera = [self cameraWithPosition:AVCaptureDevicePositionBack]; } else { videoCamera = [self cameraWithPosition:AVCaptureDevicePositionFront]; } //Add input to session AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoCamera error:nil]; [self.captureSession addInput:newVideoInput]; //Add mic input to the session AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; AVCaptureInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil]; [self.captureSession addInput:audioInput]; //Add movie output to session for (AVCaptureOutput *output in self.captureSession.outputs) { [self.captureSession removeOutput:output]; } self.movieOutput = [AVCaptureMovieFileOutput new]; int32_t preferredTimeScale = 30; //Frames per second self.movieOutput.maxRecordedDuration = CMTimeMakeWithSeconds(15, preferredTimeScale); //Setting the max video length [self.captureSession addOutput:self.movieOutput]; //Commit all the configuration changes at once [self.captureSession commitConfiguration]; 

我知道,如果我将AVCaptureSessionPresetHigh更改为不同的预设,我可以减less最终video的文件大小,但不幸的是看起来像AVCaptureSessionPresetiFrame1280x720是唯一一个提供了我试图捕捉的全帧(这留给我一个输出大小约20MB,对4G上传来说仍然太大)。

我花了大量的时间search并通过堆栈溢出的其他职位,但我似乎无法弄清楚我做错了我的生活和任何帮助都将不胜感激。

你需要一个博士学位与AVAssetWriter – 这是不平凡的: https : //developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/05_Export.html#//apple_ref/doc/uid/ TP40010188-CH9-SW1

有一个惊人的库正是你想要的只是一个AVAssetExportSession插件replace更重要的function,如更改比特率: https : //github.com/rs/SDAVAssetExportSession

以下是如何使用它:

 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { SDAVAssetExportSession *encoder = [SDAVAssetExportSession.alloc initWithAsset:[AVAsset assetWithURL:[info objectForKey:UIImagePickerControllerMediaURL]]]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; self.myPathDocs = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:@"lowerBitRate-%d.mov",arc4random() % 1000]]; NSURL *url = [NSURL fileURLWithPath:self.myPathDocs]; encoder.outputURL=url; encoder.outputFileType = AVFileTypeMPEG4; encoder.shouldOptimizeForNetworkUse = YES; encoder.videoSettings = @ { AVVideoCodecKey: AVVideoCodecH264, AVVideoCompressionPropertiesKey: @ { AVVideoAverageBitRateKey: @2300000, // Lower bit rate here AVVideoProfileLevelKey: AVVideoProfileLevelH264High40, }, }; encoder.audioSettings = @ { AVFormatIDKey: @(kAudioFormatMPEG4AAC), AVNumberOfChannelsKey: @2, AVSampleRateKey: @44100, AVEncoderBitRateKey: @128000, }; [encoder exportAsynchronouslyWithCompletionHandler:^ { int status = encoder.status; if (status == AVAssetExportSessionStatusCompleted) { AVAssetTrack *videoTrack = nil; AVURLAsset *asset = [AVAsset assetWithURL:encoder.outputURL]; NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; videoTrack = [videoTracks objectAtIndex:0]; float frameRate = [videoTrack nominalFrameRate]; float bps = [videoTrack estimatedDataRate]; NSLog(@"Frame rate == %f",frameRate); NSLog(@"bps rate == %f",bps/(1024.0 * 1024.0)); NSLog(@"Video export succeeded"); // encoder.outputURL <- this is what you want!! } else if (status == AVAssetExportSessionStatusCancelled) { NSLog(@"Video export cancelled"); } else { NSLog(@"Video export failed with error: %@ (%d)", encoder.error.localizedDescription, encoder.error.code); } }]; }