最近项目要搞视频编辑相关的东西。于是就有了这些文章。
视频相关入门
『ios』视频编辑入门 【视频背景音乐合成】
『ios』视频编辑入门【添加水印】
『ios』视频编辑入门【画中画实现】改变视频尺寸
视频编辑主要用的AVFoundation。
涉及到的AVFoundation的类。
AVAsset:素材库里的素材;
AVAssetTrack:素材的轨道;
AVMutableComposition :一个用来合成视频的工程文件;
AVMutableCompositionTrack :工程文件中的轨道,有音频轨、视频轨等,里面可以插入各种对应的素材;
AVMutableVideoComposition:用来生成video的组合指令,包含多段instruction。可以决定最终视频的尺寸,裁剪需要在这里进行;
AVMutableVideoCompositionInstruction:一个指令,决定一个timeRange内每个轨道的状态,包含多个layerInstruction;
AVMutableVideoCompositionLayerInstruction 可以用来设置 video track 的图形变换、图形渐变、透明度、透明度渐变等等。一个 video composition instruction 的 layerInstructions 属性中所存储的 layer instructions 的顺序决定了 tracks 中的视频帧是如何被放置和组合的;
AVAssetExportSession:导出视频需要用到的类
视频背景音乐合成
1.拿到两个视频跟一个背景音乐的路径
NSURL *videoPath1 = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"1" ofType:@"mp4"]];
NSURL *videoPath2 = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"2" ofType:@"mp4"]];
NSURL *music = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"]];
AVAsset *firstAsset = [AVAsset assetWithURL:firstVideoPath];
AVAsset *secondAsset = [AVAsset assetWithURL:secondVideo];
AVAsset *musciAsset = [AVAsset assetWithURL:musicPath];
2.创建合成文件
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
3.创建视频轨道轨道并合成
AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
[firstTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, firstAsset.duration)
ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];
[firstTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, secondAsset.duration)
ofTrack:[[secondAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:firstAsset.duration error:nil];
4.创建音频轨道并合成
if (musciAsset!=nil){
//把音频 Adds an empty track to a mutable composition
AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
[AudioTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, CMTimeAdd(firstAsset.duration, secondAsset.duration))
ofTrack:[[musciAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
}
5.调整声音
AVMutableAudioMix *videoAudioMixTools = [AVMutableAudioMix audioMix];
if (musciAsset) {
//调节音量
//获取音频轨道
AVMutableAudioMixInputParameters *firstAudioParam = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:AudioTrack];
//设置音轨音量,可以设置渐变,设置为1.0就是全音量
[firstAudioParam setVolumeRampFromStartVolume:1.0 toEndVolume:1.0 timeRange:CMTimeRangeMake(kCMTimeZero, CMTimeAdd(firstAsset.duration, secondAsset.duration))];
[firstAudioParam setTrackID:AudioTrack.trackID];
videoAudioMixTools.inputParameters = [NSArray arrayWithObject:firstAudioParam];
}
6.获取视频存储路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"mergeVideo-%d.mp4",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];
7.导出视频 存到相册
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=url;//导出的路径
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.audioMix = videoAudioMixTools;//声音
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
- (void)exportDidFinish:(AVAssetExportSession*)session {
if (session.status == AVAssetExportSessionStatusCompleted) {
NSURL *outputURL = session.outputURL;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
__block PHObjectPlaceholder *placeholder;
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL.path)) {
NSError *error;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputURL];
placeholder = [createAssetRequest placeholderForCreatedAsset];
} error:&error];
if (error) {
[SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"%@",error]];
}
else{
[SVProgressHUD showSuccessWithStatus:@"视频已经保存到相册"];
}
}else {
[SVProgressHUD showErrorWithStatus:NSLocalizedString(@"视频保存相册失败,请设置软件读取相册权限", nil)];
}
});
}
}
后面还会继续研究别的功能。。。