我正在尝试从UIImagePickerController创建的源视频中导出.mov文件。问题是输出文件AVAssetExportSession创建的只有668个字节。它为什么失败?我的代码:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSURL *imagePickerVideoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSString *filename = @"vid1.mov";
AVAsset *video = [AVAsset assetWithURL:imagePickerVideoURL];
AVAssetExportSession *exportSession
= [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.outputURL = [pathToSavedVideosDirectory URLByAppendingPathComponent:filename];
NSLog(@"processing video...: %@", exportSession);
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSLog(@"done processing video!");
}];
}
答案 0 :(得分:5)
我猜它是因为exportSession
没有保留在内存中,因此在didFinishPickingMediaWithInfo
完成后(在导出会话完成处理程序运行之前)被杀死。
将exportSession
存储到@property
或更改完成处理程序以将引用复制到exportSession
,如下所示:
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(@"done processing video!");
}
}];
答案 1 :(得分:2)
您需要使用AVAssetExportSession ..
写下视频文件的步骤从Asset
开始
把你的fileURL
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:fileURL options:nil];
创建AVMutableComposition
AVMutableComposition* mixComposition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:clipVideoTrack atTime:kCMTimeZero error:nil];
[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]];
AVAssetTrack *clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,videoAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
如果需要,可以使用Aniamtion图层创建AVMutableVideoComposition
AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain];
videoComp.renderSize = CGSizeMake(videoSize.width, videoSize.height);
videoComp.frameDuration = CMTimeMake(1, 30);
videoComp.renderScale = 1.0;
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
如果您需要传递nil
,动画层就在这里
CGSize videoSize = [videoAsset naturalSize];
//layer mixing
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
[parentLayer addSublayer:videoLayer];
在所选图层中添加aniamtion,您需要在sublayer
parentLayer
在提及动画图层和持续时间的视频合成中添加说明。
AVMutableVideoCompositionInstruction
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mixComposition duration]);
AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject: instruction];
现在使用AVAssetExportSession
和AVMutableComposition
AVMutableVideoComposition
_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.videoComposition = videoComp;
//为导出的视频文件创建tmepory路径。 .m4a将是AVFoundation的首选扩展名。
NSString *videoName = @"demo.m4a";
NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
{
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
在导出会话中添加网址和一些必需的属性。
_assetExport.outputFileType = AVFileTypeQuickTimeMovie;
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;
启动导出会话并在收到完整消息时执行操作。
[_assetExport exportAsynchronouslyWithCompletionHandler:
^(void ) {
switch (_assetExport.status)
{
case AVAssetExportSessionStatusUnknown:
NSLog(@"Unknown");
case AVAssetExportSessionStatusExporting:
NSLog(@"Exporting");
case AVAssetExportSessionStatusFailed:
NSLog(@"exporting failed");
break;
case AVAssetExportSessionStatusCompleted:
NSLog(@"exporting completed");
[self performSelectorOnMainThread:@selector(completeVideoExport) withObject:nil waitUntilDone:YES];
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"export cancelled");
break;
}
_assetExport = nil;
[_assetExport release];
}
];
如果你还需要让我知道..
答案 2 :(得分:1)
exportSession具有“error”属性,您可以检查该属性以确定错误。很多时候这些错误并不是特别有用,但它至少是一个起点。
请注意,我发现.mov文件存在问题,其中AVFoundation不支持其中的编解码器。
答案 3 :(得分:1)
对于调试,请尝试此操作...
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"exportSessionMetaData:%@", exportSession.metadata);
if(exportSession.status == AVAssetExportSessionStatusCompleted){
NSError *dataReadingError = nil;
NSData *videoData = nil;
videoData =
[NSData dataWithContentsOfURL:[pathToSavedVideosDirectory
URLByAppendingPathComponent:filename];
options:NSDataReadingMapped
error:&dataReadingError];
if (videoData != nil) {
// You got video data, do you work here...
} else {
NSLog(@"Failed to load the video data. ERROR:%@", dataReadingError);
}
}
});
}];
答案 4 :(得分:0)
查看TSLibraryImport - 导入代码有效。