Tôi đang quay các video clip nhỏ (khoảng một giây hoặc lâu hơn, với cả camera phía trước và phía sau, với các hướng khác nhau có thể). Và sau đó cố gắng hợp nhất chúng bằng cách sử dụng AVAssetExportSession. Về cơ bản, tôi tạo bố cục và videoComposition với các biến thể thích hợp và âm thanh & các bản nhạc video.exportAsynchronouslyWithCompletionHandler không thành công với nhiều tệp video (Code = -11820)
Vấn đề là trên iOS 5 nó không thành công nếu bạn có nhiều hơn 4 video clip và trên iOS 6 giới hạn có vẻ là 16 clip.
Điều này với tôi có vẻ thực sự khó hiểu. Có phải AVAssetExportSession đang làm điều gì đó kỳ quặc hoặc nó có một số giới hạn không có giấy tờ về số lượng clip có thể được truyền cho nó không? Dưới đây là một số trích đoạn từ mã của tôi:
-(void)exportVideo
{
AVMutableComposition *composition = video.composition;
AVMutableVideoComposition *videoComposition = video.videoComposition;
NSString * presetName = AVAssetExportPresetMediumQuality;
AVAssetExportSession *_assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:presetName];
self.exportSession = _assetExport;
videoComposition.renderSize = CGSizeMake(640, 480);
_assetExport.videoComposition = videoComposition;
NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent: @"export.mov"];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];
// Delete the currently exported files if it exists
if([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
_assetExport.outputFileType = AVFileTypeQuickTimeMovie;
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;
[_assetExport exportAsynchronouslyWithCompletionHandler:^{
switch (_assetExport.status)
{
case AVAssetExportSessionStatusCompleted:
NSLog(@"Completed exporting!");
break;
case AVAssetExportSessionStatusFailed:
NSLog(@"Failed:%@", _assetExport.error.description);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Canceled:%@", _assetExport.error);
break;
default:
break;
}
}];
}
Và dưới đây là cách các tác phẩm được thực hiện:
-(void)setVideoAndExport
{
video = nil;
video = [[VideoComposition alloc] initVideoTracks];
CMTime localTimeline = kCMTimeZero;
// Create the composition of all videofiles
for (NSURL *url in outputFileUrlArray) {
AVAsset *asset = [[AVURLAsset alloc]initWithURL:url options:nil];
[video setVideo:url at:localTimeline];
localTimeline = CMTimeAdd(localTimeline, asset.duration); // Increment the timeline
}
[self exportVideo];
}
Và đây là thịt của lớp VideoComposition:
-(id)initVideoTracks
{
if((self = [super init]))
{
composition = [[AVMutableComposition alloc] init];
addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instructions = [[NSMutableArray alloc] init];
videoComposition = [AVMutableVideoComposition videoComposition];
}
return self;
}
-(void)setVideo:(NSURL*) url at:(CMTime)to
{
asset = [[AVURLAsset alloc]initWithURL:url options:nil];
AVAssetTrack *assetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableCompositionTrack *compositionTrackVideo = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionTrackVideo insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack: assetTrack atTime:to error:nil];
AVMutableCompositionTrack *compositionTrackAudio = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionTrackAudio insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:to error:nil];
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeAdd(to, asset.duration));
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionTrackVideo];
[layerInstruction setTransform: assetTrack.preferredTransform atTime: kCMTimeZero];
[layerInstruction setOpacity:0.0 atTime:CMTimeAdd(to, asset.duration)];
[instructions addObject:layerInstruction];
mainInstruction.layerInstructions = instructions;
videoComposition.instructions = [NSArray arrayWithObject:mainInstruction];
videoComposition.frameDuration = CMTimeMake(1, 30);
}
Tốt, tôi nghĩ rằng tôi cần phải thử điều này. Tôi đã phá vỡ vấn đề bằng cách luôn làm một bố cục sau mỗi lần ghi âm (trong nền) nên không quá hai video thực sự được tổng hợp. – Karvapallo
Tôi thực sự không thể làm việc này. Có lẽ các biến đổi cần phải được áp dụng khác nhau (hoặc chúng sẽ không hoạt động) với cách tiếp cận này. Bạn sẽ có một số mã ví dụ nằm xung quanh? – Karvapallo
Mã tạo thành phần gần đây trong dự án của chúng tôi được viết lại bằng cách sử dụng AVCompositionTrackSegment. Chúng tôi tạo ra một mảng các phân đoạn theo dõi, xác nhận chúng và gán cho các thuộc tính phân đoạn của AVMutableCompositionTrack. Chúng tôi đang làm rất nhiều thời gian kéo dài/nén (thay đổi tốc độ video) và phương pháp này cung cấp thành phần chính xác hơn. – Jeepston