這段時間由于工作需要呀狼,了解了一些關于iOS中視頻處理功能浩蓉,發(fā)現(xiàn)AVFoundation功能強大础钠,今天聊一聊視頻截取和添加背景音樂的一些功能浩峡,這里面涉及到得一些類類名和方法都比較長,但是用法還是相對簡單岸售,主要是能理解多媒體的一些概念践樱,先來介紹一下常用到的幾個AVFoundation下得類:
AVURLAsset:AVAsset的子類,此類主要用于獲取多媒體的信息凸丸,包括視頻拷邢、音頻的類型、時長屎慢、每秒幀數(shù)瞭稼,其實還可以用來獲取視頻的指定位置的縮略圖忽洛。
AVMutableCompositionTrack:視頻和音頻的采集都需要通過這個類,我覺得可以理解為采集的一個視頻或音頻資源對應一個track對象环肘。
AVMutableComposition:這個類點進去你會發(fā)現(xiàn)其實它也是AVAsset的子類欲虚,對應有一個方法[AVMutableComposition composition],返回一個nil的AVMutableComposition對象悔雹。
CMTime:這個時間并不是平時我們說到的分秒的時間复哆,后面用到的時候會再說。
AVAssetExportSession:用于合并你采集的視頻和音頻荠商,最終會保存為一個新文件寂恬,可以設置文件的輸出類型、路徑莱没,以及合并的一個狀態(tài)AVAssetExportSessionStatus。
這里單獨創(chuàng)建了一個工具類MediaManager來做操作
下面是MediaManager.h的方法接口:
#import#import/**
添加音樂完成回調(diào)的block
*/typedefvoid(^MixcompletionBlock)(void);@interfaceMediaManager:NSObject/**
截取視頻并添加背景音樂
*/+ (void)addBackgroundMiusicWithVideoUrlStr:(NSURL*)videoUrl audioUrl:(NSURL*)audioUrl andCaptureVideoWithRange:(NSRange)videoRange completion:(MixcompletionBlock)completionHandle;/**
獲取多媒體時長
*/+ (CGFloat)getMediaDurationWithMediaUrl:(NSString*)mediaUrlStr;/**
獲取合并后的多媒體文件路徑
*/+ (NSString*)getMediaFilePath;@end
MediaManager.m中方法實現(xiàn):
在添加背景音樂的方法中先創(chuàng)建視頻和音頻對應的AVURLAsset對象
//AVURLAsset此類主要用于獲取媒體信息酷鸦,包括視頻饰躲、聲音等AVURLAsset* audioAsset = [[AVURLAssetalloc] initWithURL:audioUrl options:nil];AVURLAsset* videoAsset = [[AVURLAssetalloc] initWithURL:videoUrl options:nil];//創(chuàng)建AVMutableComposition對象來添加視頻音頻資源的AVMutableCompositionTrackAVMutableComposition* mixComposition = [AVMutableCompositioncomposition];
我們要截取一段視頻就一定涉及到截取的時間點和長度,下面來具體介紹一下CMTime和CMTimeRange臼隔。
CMTime一個用于描述多媒體幀數(shù)和播放速率的結構體嘹裂,可以通過? CMTimeMake(int64_t value, int32_t timescale)? 來生成一個CMTime變量,value視頻的總幀數(shù)摔握,timescale是指每秒視頻播放的幀數(shù)寄狼,視頻播放速率,(value / timescale)才是視頻實際的秒數(shù)時長氨淌,timescale一般情況下不改變泊愧,截取視頻長度通過改變value的值。
或者通過 CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimeScale)? 方法也可以盛正,這里的seconds對應的是平時說的秒數(shù)删咱,preferredTimeScale是每秒播放的幀數(shù)。
CMTimeRange有點類似NSRange豪筝,只不過它對應的是視頻的起始時間點和視頻的長度痰滋,可以通過方法CMTimeRangeMake(start, duration)創(chuàng)建變量,start起始時間续崖,duration時長敲街,都是CMTime類型。方法中我直接傳入NSRange严望,在內(nèi)部做了一些轉換多艇。
了解完這些就可以開始采集視頻音頻了,下面是對視頻的采集著蟹,如果需要也可以去獲取視頻原有的音軌墩蔓。
這里經(jīng)常會遇到到tracksWithMediaType方法返回empty的數(shù)組梢莽,導致程序奔潰,我從Stack Overflow弄下來的一段解釋:
屏幕快照 2015-12-02 下午2.25.17.png
//開始位置startTimeCMTime startTime = CMTimeMakeWithSeconds(videoRange.location, videoAsset.duration.timescale);//截取長度videoDurationCMTime videoDuration = CMTimeMakeWithSeconds(videoRange.length, videoAsset.duration.timescale);? ? CMTimeRange videoTimeRange = CMTimeRangeMake(startTime, videoDuration);//視頻采集compositionVideoTrackAVMutableCompositionTrack*compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideopreferredTrackID:kCMPersistentTrackID_Invalid];#warning 避免數(shù)組越界 tracksWithMediaType 找不到對應的文件時候返回空數(shù)組//TimeRange截取的范圍長度//ofTrack來源//atTime插放在視頻的時間位置[compositionVideoTrack insertTimeRange:videoTimeRange ofTrack:([videoAsset tracksWithMediaType:AVMediaTypeVideo].count>0) ? [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject:nilatTime:kCMTimeZero error:nil];
對背景音頻的采集
//聲音長度截取范圍==視頻長度CMTimeRange audioTimeRange = CMTimeRangeMake(kCMTimeZero, videoDuration);//音頻采集compositionCommentaryTrackAVMutableCompositionTrack*compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudiopreferredTrackID:kCMPersistentTrackID_Invalid];? ? [compositionAudioTrack insertTimeRange:audioTimeRange ofTrack:([audioAsset tracksWithMediaType:AVMediaTypeAudio].count>0) ? [audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject:nilatTime:kCMTimeZero error:nil];
然后就是合并獲取的視頻和背景音頻奸披,這里需要對輸出的文件設置保存路徑以及文件類型昏名。
//AVAssetExportSession用于合并文件,導出合并后文件阵面,presetName文件的輸出類型AVAssetExportSession*assetExportSession = [[AVAssetExportSessionalloc] initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough];NSString*outPutPath = [NSTemporaryDirectory() stringByAppendingPathComponent:MediaFileName];//混合后的視頻輸出路徑NSURL*outPutPath = [NSURLfileURLWithPath:outPutPath];if([[NSFileManagerdefaultManager] fileExistsAtPath:outPutPath])? ? {? ? ? ? [[NSFileManagerdefaultManager] removeItemAtPath:outPutPath error:nil];? ? }//輸出視頻格式 AVFileTypeMPEG4 AVFileTypeQuickTimeMovie...assetExportSession.outputFileType=AVFileTypeQuickTimeMovie;//? ? NSArray *fileTypes = assetExportSession.assetExportSession.outputURL= outPutPath;//輸出文件是否網(wǎng)絡優(yōu)化assetExportSession.shouldOptimizeForNetworkUse=YES;? ? [assetExportSession exportAsynchronouslyWithCompletionHandler:^{? ? ? ? completionHandle();? ? }];
這是獲取多媒體文件時長的方法實現(xiàn)轻局。
+ (CGFloat)getMediaDurationWithMediaUrl:(NSString*)mediaUrlStr {NSURL*mediaUrl = [NSURLURLWithString:mediaUrlStr];AVURLAsset*mediaAsset = [[AVURLAssetalloc] initWithURL:mediaUrl options:nil];? ? CMTime duration = mediaAsset.duration;returnduration.value/ duration.timescale;? ? }
最后只要在外部添加背景音樂的方法簡單的調(diào)用即可。
- (IBAction)addBackgroundmusic:(id)sender {if(_videoUrl && _audioUrl &&self.endTextField.text&&self.startTextField.text) {? ? ? ? [MediaManager addBackgroundMiusicWithVideoUrlStr:_videoUrl audioUrl:_audioUrl andCaptureVideoWithRange:NSMakeRange([self.startTextField.textfloatValue], [self.endTextField.textfloatValue] - [self.startTextField.textfloatValue]) completion:^{NSLog(@"視頻合并完成");? ? ? ? }];? ? }}
代碼上傳到Github:
https://github.com/ShelinShelin/VideoEditing.git
界面做的比較簡陋样刷,......大家多包涵仑扑,最好運行在真機上,視頻采集是通過相機或者相冊資源置鼻,最近也想利用業(yè)余時間寫一個相對完整的開源項目互相學習镇饮,剛起了個頭,希望能堅持下去!