avfoundation 視訊合成 ,合成兩段視訊和一段音訊
阿新 • • 發佈:2019-02-08
一下程式碼少部分邏輯沒有補全,並不影響閱讀,請自省補全吧,
例如有些變數我都不貼上了
第一段:合併
[code]- (IBAction)mergeClick:(id)sender {
if (self.firstAsset !=nil && self.secondAsset!=nil) {
self.activityView.hidden = NO;
[self.activityView startAnimating];
// 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
// 2 - Video track
AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
[firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.firstAsset.duration)
ofTrack:[self.firstAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:kCMTimeZero error:nil];
[firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.secondAsset.duration)
ofTrack:[self.secondAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:self.firstAsset.duration error:nil];
// 3 - Audio track
if (self.audioAsset!=nil){
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeAdd(self.firstAsset.duration, self.secondAsset.duration))
ofTrack:[self.audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:kCMTimeZero error:nil];
}
// 4 - Get path
NSString *path = [[GG sharedInstance].docPath stringByAppendingPathComponent:
[NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:path];
// 5 - Create exporter
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=url;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
}
}[/code]
第二段:合併後輸出
[code]
-(void)exportDidFinish:(AVAssetExportSession*)session{
if (session.status == AVAssetExportSessionStatusCompleted) {
NSURL *outputURL = session.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputURL completionBlock:^(NSURL *assetURL, NSError *error){
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Video Saving Failed"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"Saved To Photo Album"
delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
});
}];
}
}else{
NSLog(@"export failed");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"export failed" message:[NSString stringWithFormat:@"status=%zd, error=%@", session.status, session.error]
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
self.audioAsset = nil;
self.firstAsset = nil;
self.secondAsset = nil;
[self.activityView stopAnimating];
self.activityView.hidden = YES;
}
[/code]
例如有些變數我都不貼上了
第一段:合併
[code]- (IBAction)mergeClick:(id)sender {
if (self.firstAsset !=nil && self.secondAsset!=nil) {
self.activityView.hidden = NO;
[self.activityView startAnimating];
// 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
// 2 - Video track
AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
[firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.firstAsset.duration)
ofTrack:[self.firstAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:kCMTimeZero error:nil];
[firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.secondAsset.duration)
ofTrack:[self.secondAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:self.firstAsset.duration error:nil];
// 3 - Audio track
if (self.audioAsset!=nil){
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeAdd(self.firstAsset.duration, self.secondAsset.duration))
ofTrack:[self.audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:kCMTimeZero error:nil];
}
// 4 - Get path
NSString *path = [[GG sharedInstance].docPath stringByAppendingPathComponent:
[NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:path];
// 5 - Create exporter
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=url;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
}
}[/code]
第二段:合併後輸出
[code]
-(void)exportDidFinish:(AVAssetExportSession*)session{
if (session.status == AVAssetExportSessionStatusCompleted) {
NSURL *outputURL = session.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputURL completionBlock:^(NSURL *assetURL, NSError *error){
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Video Saving Failed"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"Saved To Photo Album"
delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
});
}];
}
}else{
NSLog(@"export failed");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"export failed" message:[NSString stringWithFormat:@"status=%zd, error=%@", session.status, session.error]
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
self.audioAsset = nil;
self.firstAsset = nil;
self.secondAsset = nil;
[self.activityView stopAnimating];
self.activityView.hidden = YES;
}
[/code]