iOS視頻剪輯學習筆記(AVAsset,AVMutableComposition)

一個視頻文件中包含了很多軌道(Track),比如一個或多個音頻軌道,一個或多個視頻軌道。我們可以對這些軌道中的數(shù)據(jù)進行各種操作(裁剪、拼接、旋轉(zhuǎn)等)。

本次我用到的視頻打點裁剪相關(guān)功能用到的類如下:

AVAsset:素材,比如出相冊中取出的數(shù)據(jù)
AVAssetTrack:素材的軌道
AVMutableComposition:視頻的工程文件(是AVAsset的子類,可以用來直接播放)
AVMutableCompositionTrack:工程文件對應(yīng)的軌道

這里我的需求是要裁剪調(diào)一個視頻素材的頭尾,第一步需要獲取到素材的視頻軌道和音頻軌道

 AVAssetTrack *videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
 AVAssetTrack *audioAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

第二步,創(chuàng)建工程文件,將素材的軌道數(shù)據(jù)導入到工程文件的軌道中

AVMutableComposition *mutableComposition = [AVMutableComposition composition];
AVMutableCompositionTrack *audioTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                       preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *videoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                       preferredTrackID:kCMPersistentTrackID_Invalid];

NSError *errorAudio;
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:audioAssetTrack atTime:kCMTimeZero error:&errorAudio];
NSError *errorVideo;
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero error:&errorVideo];

第三步,計算需要裁剪的頭和尾的range,然后將音頻軌道和視頻軌道都進行裁剪

CMTime start = CMTimeMakeWithSeconds(self.startTime, videoAsset.duration.timescale);
CMTime end = CMTimeMakeWithSeconds(self.stopTime - self.startTime, videoAsset.duration.timescale);
CMTime duration = CMTimeMakeWithSeconds(videoAsset.duration.value - self.stopTime, videoAsset.duration.timescale);
CMTimeRange range = CMTimeRangeMake(kCMTimeZero, start);
CMTimeRange range2 = CMTimeRangeMake(end, duration);
[videoTrack removeTimeRange: range];
[audioTrack removeTimeRange: range];
[videoTrack removeTimeRange: range2];
[audioTrack removeTimeRange: range2];

到這里,我們已經(jīng)將工程文件中的視頻進行了裁剪,我們可以直接使用AVPlayer進行播放看裁剪成功沒有

AVPlayerViewController *playerController = [[AVPlayerViewController alloc] init];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:mutableComposition];
AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
playerController.player = player;
[self presentViewController:playerController animated:true completion:nil];

當然,更多的是需要使用AVAssetExportSession將工程文件轉(zhuǎn)碼導出,代碼如下:

AVAssetExportSession* exportSession = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetPassthrough];
NSURL *fileUrl = [NSURL fileURLWithPath:self.tempPath];
exportSession.outputURL = fileUrl;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:
     ^(void ) {
    switch ([exportSession status]) {
        case AVAssetExportSessionStatusFailed:
            NSLog(@"failed: %@", [[exportSession error] localizedDescription]);
            break;
        case AVAssetExportSessionStatusCancelled:
            NSLog(@"canceled");
            break;
        default:
            NSLog(@"success");
            break;
    }
}
];

至此,整個裁剪功能的主要代碼已經(jīng)完成。

遇到的坑

最初我參考別人的demo發(fā)現(xiàn)可以使用AVAssetExportSession的timeRange來實現(xiàn)裁剪。

 CMTimeRange range = CMTimeRangeMake(start, duration);
 self.exportSession.timeRange = range;

但是當裁剪的視頻時長比較長時,這種方法在從頭開始裁剪和裁剪視頻后半部分在耗時上差別巨大。
比如我測試了30分鐘的視頻,我裁剪0-10分鐘大概耗時8秒,但是裁剪20-30分鐘耗時達到了驚人的60秒。我不清楚這個是因為底層來轉(zhuǎn)碼時選擇轉(zhuǎn)碼范圍的算法導致了這一現(xiàn)象還是其他什么原因。
最終我選擇了使用上文中提到的切割軌道數(shù)據(jù)的方式基本做到了在30分鐘的視頻中切割10分鐘,無論切割哪一段視頻,都可以保持8秒完成切割和轉(zhuǎn)碼導出。
如有問題,請指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容