媒体合成和编辑
媒体合成和编辑
组合媒体
AVFoundation有关资源组合的功能源于AVAsset
的子类AVComposition。一个组合就是将其他几种媒体资源组合成一个自定义的临时排列,再将这个临时排列视为一个可以呈现或处理的独立媒体项目。就比如AVAsset
对象,组合相当于包含了一个或多个给定类型的媒体轨道的容器。AVComposition
中轨道都是AVAssetTrack的子类AVCompositionTrack。一个组合轨道本身由一个或多个媒体片段组成,由AVCompositionTrackSegment类定义,代表这个组合中的实际媒体区域。
AVComposition
和AVCompositionTrack
都是不可变对象,提供对资源的只读操作。这些对象提供了一个合适的接口让应用程序的一部分可以进行播放或处理。不过,当创建自己的组合时,就需要使用AVMutableComposition
和AVMutableCompositionTrack
所提供的可变子类。这些对象提供的接口需要操作轨道和轨道分段,这样就可以创建所需的临时排列了。
要创建自定义组合,需指定在将要添加到组合的源媒体的时间范围,还要指定要添加片段的每个轨道的位置。
AVMutableComposition和AVMutableCompositionTrack
AVMutableComposition
AVMutableComposition
可以添加或删除tracks
,和添加、删除、缩放time range
。 AVMutableComposition
把assets
集合在一起,如下所示:
创建Composition
使用AVMutableComposition
类创建Composition
,为把媒体数据添加到composition
中,需添加一个或多个由AVMutableCompositionTrack
类表示的composition tracks
最简单的例子是使用一个video track
和一个audio track
创建一个可变的composition
,如下:
AVMutableComposition *mutableComposition = [AVMutableComposition composition];
// Create the video composition track.
AVMutableCompositionTrack *mutableCompositionVideoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
// Create the audio composition track.
AVMutableCompositionTrack *mutableCompositionAudioTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
当把一个tracks
添加到一个composition
中时,需提供一个media type
和一个track ID
-
media type
最常用的media type
的是AVMediaTypeVideo
和AVMediaTypeAudio
,不过也可使用AVMediaTypeSubtitle和AVMediaTypeText - 与视听数据相关联的每个轨道都具有一个称为
track ID
的唯一标识符。可使用kCMPersistentTrackID_Invalid来表示AVFoundation应该自动生成一个正确的轨道ID。
addMutableTrackWithMediaType:preferredTrackID:方法添加一个空的track
到composition
添加数据到Composition
创建好composition
后,就需要把媒体数据添加到对应的track
中,需通过AVAsset
对象。如下的例子,把添加2个不同的的video asset tracks
到同一个composition track
:
// You can retrieve AVAssets from a number of places, like the camera roll for example.
AVAsset *videoAsset = <#AVAsset with at least one video track#>;
AVAsset *anotherVideoAsset = <#another AVAsset with at least one video track#>;
// Get the first video track from each asset.
AVAssetTrack *videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack *anotherVideoAssetTrack = [[anotherVideoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
// Add them both to the composition.
[mutableCompositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,videoAssetTrack.timeRange.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero error:nil];
[mutableCompositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,anotherVideoAssetTrack.timeRange.duration) ofTrack:anotherVideoAssetTrack atTime:videoAssetTrack.timeRange.duration error:nil];
insertTimeRange:ofTrack:atTime:error:方法添加一个时间范围的track
导出组合
使用AVAssetExportSession对象导出组合,设置其输出的URL
,并设置其输出文件类型
// Create the export session with the composition and set the preset to the highest quality.
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality];
// Set the desired output URL for the file created by the export process.
exporter.outputURL = [[[[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:@YES error:nil] URLByAppendingPathComponent:[kDateFormatter stringFromDate:[NSDate date]]] URLByAppendingPathExtension:CFBridgingRelease(UTTypeCopyPreferredTagWithClass((CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension))];
// Set the output file type to be a QuickTime movie.
exporter.outputFileType = AVFileTypeQuickTimeMovie;
调用其exportAsynchronouslyWithCompletionHandler:方法开始导出过程,如下
首先在在主队列检查导出会话状态,如果导出成功完成,则将导出的视频文件写入AssetsLibrary
[self.exportSession exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
AVAssetExportSessionStatus status = self.exportSession.status;
if (status == AVAssetExportSessionStatusCompleted) {
[self writeExportedVideoToAssetsLibrary];
} else {
[UIAlertView showAlertWithTitle:@"Export Failed"
message:@"The request export failed."];
}
});
}];
......
- (void)writeExportedVideoToAssetsLibrary {
NSURL *exportURL = self.exportSession.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:exportURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:exportURL
completionBlock:^(NSURL *assetURL,
NSError *error) {
if (error) {
NSString *message = @"Unable to write to Photos library.";
[UIAlertView showAlertWithTitle:@"Write Failed"
message:message];
}
[[NSFileManager defaultManager] removeItemAtURL:exportURL
error:nil];
}];
} else {
NSLog(@"Video could not be exported to assets library.");
}
self.exportSession = nil;
}
例子
合成的例子,可参考Merging Audio and Video in Native iOS,一个简单的音频和视频合成的例子:
另外在《AV Foundation开发秘籍》中也有介绍
资源
上一篇: 用TS实现链表结构