视频提取音频和音频裁剪

2,942 阅读1分钟

最近项目中需要从视频中提取音频,并需要根据音频时间间隔进行裁剪,所以在此记录下实现过程。

音频提取

音频提取原理是通过创建只包含原始文件的音频音轨并使用 AVAssetExportSession导出组合文件的AVMutableComposition 来完成音频提取。

/*
输出路径
self.cachePath: 获取缓存路径
*/
NSString *outPath = [self.cachePath stringByAppendingPathComponent: [NSString stringWithFormat:@"%@.m4a", name]];
// 创建组合文件
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
NSURL *url = [NSURL fileURLWithPath:path];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetTrack *track = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
AVMutableCompositionTrack *comTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
NSError *error;
[comTrack insertTimeRange:track.timeRange ofTrack:track atTime:kCMTimeZero error:&error];
if (error) {
    NSLog(@"创建失败");
}
// 创建只包含原始文件的音频音轨
AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetPassthrough];
// 导出文件类型.m4a格式
session.outputFileType = AVFileTypeAppleM4A;
session.outputURL = [NSURL fileURLWithPath:outPath];
// 音频导出
[session exportAsynchronouslyWithCompletionHandler:^{
    AVAssetExportSessionStatus status = session.status;
    if(AVAssetExportSessionStatusCompleted == status) {
        NSLog(@"音频导出成功");
    } else {
	    NSLog(@"音频导出失败");
    }
}];

音频裁剪

/*
根据时间间隔裁剪音频
path: 音频路径
time: 时间间隔
*/
- (void)cutAudioWithPath:(NSString *)path intervalTime:(NSInteger)time {
	// 获取音频时长
	NSURL *url = [NSURL fileURLWithPath:path];
	AVURLAsset*audioAsset = [AVURLAsset URLAssetWithURL:url options:nil];
	CMTime totalDuration = audioAsset.duration;
	CGFloat audioSeconds = CMTimeGetSeconds(totalDuration);
	
	if (audioSeconds > time) {
	    NSInteger number = ceil(audioSeconds / time);
	    for (NSInteger idx = 0; idx < number; idx ++) {
	        NSInteger t = idx * time;
	        CMTime startTime = CMTimeMake(t, 1);;
	        CMTime endTime;
	        if (t > audioSeconds) {
	            endTime = CMTimeMake(audioSeconds, 1);
	        } else {
	            endTime = CMTimeMake(time, 1);
	        }
	        NSString *fileName = [NSString stringWithFormat:@"%zi.m4a", t];
	        NSString *outPutPath = [[self composeDir] stringByAppendingPathComponent:fileName];
	        NSURL *audioFileOutput = [NSURL fileURLWithPath:outPutPath];
	        [[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
	        AVAsset *asset = [AVAsset assetWithURL:url];
	        AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A];
	        CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, endTime);
	        
	        exportSession.outputURL = audioFileOutput;
	        exportSession.outputFileType = AVFileTypeAppleM4A;
	        exportSession.timeRange = exportTimeRange;
	        
	        [exportSession exportAsynchronouslyWithCompletionHandler:^{
	            if (AVAssetExportSessionStatusCompleted == exportSession.status) {
	                NSLog(@"导出完成: %@", outPutPath);
	            } else if (AVAssetExportSessionStatusFailed == exportSession.status) {
	                NSLog(@"导出失败: %@", exportSession.error.localizedDescription);
	            }
	        }];
	    }
	} else {
	    NSLog(@"音频时长小于裁剪时间间隔");
	}
}