您的位置:首页 > 移动开发 > IOS开发

媒体合成和编辑

2017-06-29 14:12 489 查看

媒体合成和编辑

组合媒体



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
,不过也可使用AVMediaTypeSubtitleAVMediaTypeText

与视听数据相关联的每个轨道都具有一个称为
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开发秘籍》中也有介绍

资源

Editing

Merging Audio and Video in Native iOS
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 视频 合成 编辑