美文网首页短视频专题
美摄SDK的使用(四)—— 短视频的编辑工具类的封装

美摄SDK的使用(四)—— 短视频的编辑工具类的封装

作者: 刀客传奇 | 来源:发表于2017-08-17 15:32 被阅读183次

    版本记录

    版本号 时间
    V1.0 2017.08.17

    前言

    针对短视频的上传、编辑等功能有很多的SDK,比如腾讯的SDK、七牛的SDK等,这里我就说一下我用过的美摄的SDK - 1.8.0,希望对大家有所帮助。感兴趣的可以看我上面几篇。
    1. 美摄SDK的使用(一)—— 产品介绍
    2. 美摄SDK的使用(二)—— 框架介绍
    3. 美摄SDK的使用(三)—— 短视频的录制工具类的封装

    短视频编辑工具类的封装

    下面我就封装了一下短视频编辑的工具。

    1. JJShortVideoEditManager.h
    
    
    @class NvsStreamingContext;
    @class NvsLiveWindow;
    @class NvsTimeline;
    @class JJEditVideoModel;
    
    @protocol JJShortVideoEditDelegate <NSObject>
    
    - (void)beginLoadShortVideo:(NSString *)path;
    
    - (void)loadLoaderProcess:(NSInteger)process;
    
    - (void)shortVideoUploadFaile;
    
    - (void)saveToLibrary;
    
    - (void)didPlaybackEOF:(NvsTimeline *)timeline;
    
    - (void)didPlaySuccess;
    
    @end
    
    @interface JJShortVideoEditManager : NSObject
    
    @property (nonatomic, weak) id<JJShortVideoEditDelegate>delegate;
    @property (nonatomic, assign) int type;
    
    - (void)loadPreView:(NvsLiveWindow *)preview;
    
    //取得默认封面
    - (UIImage *)selectDefaletCoverImage;
    
    //加载短视频
    - (void)loadVideoPath:(NSMutableArray <JJEditVideoModel *>*)videoArray;
    
    - (NvsStreamingContext *)context;
    
    - (NvsTimeline *)timeLine;
    
    - (void)loadPlay;
    
    - (void)saveShortVideo:(NSString *)path;
    
    - (NSArray *)loadStickerArray;
    
    - (NSArray *)loadFxArray;
    
    - (void)addStickerForShortVideo:(NSInteger)index;
    
    - (void)addFxForShortVideo:(NSInteger)index;
    
    - (void)clearCache;
    
    - (void)stopPlay;
    
    @end
    
    2.JJShortVideoEditManager.m
    
    #import "JJShortVideoEditManager.h"
    #import "NvsStreamingContext.h"
    #import "NvsVideoTrack.h"
    #import "NvsTimeline.h"
    #import "JJEditVideoModel.h"
    #import "NvsVideoClip.h"
    #import "NvsFxDescription.h"
    
    @interface JJShortVideoEditManager () <NvsStreamingContextDelegate>
    
    @property (nonatomic, strong) NvsStreamingContext *context;
    @property (nonatomic, strong) NvsTimeline *timeLine;
    @property (nonatomic, strong) NvsVideoTrack *videoTrack;
    @property (nonatomic, strong) NvsLiveWindow *preView;
    @property (nonatomic, strong) NSArray <JJEditVideoModel *>*videoArray;
    @property (nonatomic, copy) NSString *path;
    @property (nonatomic, copy) NSMutableString *stickerPackageId;
    @property (nonatomic, copy) NSMutableString *videoFxPackageId;
    @property (nonatomic, strong) NSArray *lstVideoFx;
    @property (nonatomic, strong) NSArray *lstVideoTransition;
    @property (nonatomic, assign) BOOL isSave;
    @property (nonatomic, assign) BOOL hasAddedSticker;
    
    @end
    
    @implementation JJShortVideoEditManager
    
    #pragma mark - Override Base Function
    
    - (void)dealloc
    {
        DDLogWarn(@"%@ 已释放", self);
    }
    
    #pragma mark - Object Public Function
    
    //加载预览视图
    - (void)loadPreView:(NvsLiveWindow *)preview
    {
        _preView = preview;
    }
    
    //加载短视频
    - (void)loadVideoPath:(NSArray <JJEditVideoModel *>*)videoArray
    {
        _videoArray = videoArray;
    }
    
    //时间线
    
    - (NvsTimeline *)timeLine
    {
        if (!_timeLine) {
            if (!_timeLine) {
                NvsVideoResolution videoEditRes;
                videoEditRes.imageWidth = 720/2;
                videoEditRes.imageHeight = 1280/2;
                videoEditRes.imagePAR = (NvsRational){1, 1};
                NvsRational videoFps = {25, 1};
                NvsAudioResolution audioEditRes;
                audioEditRes.sampleRate = 48000;
                audioEditRes.channelCount = 2;
                audioEditRes.sampleFormat = NvsAudSmpFmt_S16;
                NvsTimeline *timeLine = [self.context createTimeline:&videoEditRes videoFps:&videoFps audioEditRes:&audioEditRes];
                _timeLine = timeLine;
                _videoTrack = [timeLine appendVideoTrack];
                for (JJEditVideoModel *model in self.videoArray) {
                    [_videoTrack appendClip:model.path];
                }
            }
            if (!self.context.delegate) {
                self.context.delegate = self;
            }
            [self.context connectTimeline:_timeLine withLiveWindow:self.preView];
        }
        if (!self.context.delegate) {
            self.context.delegate = self;
            [self.context connectTimeline:self.timeLine withLiveWindow:self.preView];
        }
        return _timeLine;
    }
    
    //播放
    
    - (void)loadPlay
    {
        self.context.delegate = self;
        [self.context connectTimeline:self.timeLine withLiveWindow:self.preView];
        if ([self.context playbackTimeline:self.timeLine startTime:0 endTime:self.timeLine.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0]) {
            NSLog(@"播放成功");
        }
    //    [self.context playbackTimeline:self.timeLine startTime:0 endTime:self.timeLine.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
    }
    
    - (void)saveShortVideo:(NSString *)path
    {
        if (self.context.delegate == nil) {
            self.context.delegate = self;
        }
         _path = path;
        NvsCompileVideoResolutionGrade grade;
        if (ZebraUIDevice_iphone5 || ZebraUIDevice_iphone4 || ZebraUIDevice_iphone4S) {
            grade = NvsCompileVideoResolutionGrade480;
        }
        else if (ZebraUIDevice_iphone5S || ZebraUIDevice_iphone5C){
            grade = NvsCompileVideoResolutionGrade720;
        }
        else {
            grade = NvsCompileVideoResolutionGrade1080;
        }
        
        if ([self.context compileTimeline:self.timeLine startTime:0 endTime:self.timeLine.duration outputFilePath:path videoResolutionGrade:grade videoBitrateGrade:NvsCompileBitrateGradeHigh flags:0]) {
        }
        else {
            NSLog(@"上传失败,请重试");
            if (_type == 1) {
                if ([self.delegate respondsToSelector:@selector(shortVideoUploadFaile)]) {
                    [self.delegate shortVideoUploadFaile];
                }
            }        
        }
    }
    
    //贴纸
    - (void)addStickerForShortVideo:(NSInteger)index
    {
        if (_hasAddedSticker) {
            NvsTimelineAnimatedSticker *sticker = [self.timeLine getFirstAnimatedSticker];
            while (sticker)
                sticker = [self.timeLine removeAnimatedSticker:sticker];
            _hasAddedSticker = NO;
            
        }
        else {
            if ([_stickerPackageId isEqualToString:@""])
                return;
            
            for (unsigned int i = 0; i < _videoTrack.clipCount; i++) {
                NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
                [videoClip setPan:0 andScan:1];
                [self.timeLine addAnimatedSticker:videoClip.inPoint duration:videoClip.outPoint - videoClip.inPoint animatedStickerPackageId:_stickerPackageId];
            }
            _hasAddedSticker = YES;
        }
        [self loadPlay];
    }
    
    - (void)addFxForShortVideo:(NSInteger)index
    {
        if (_videoTrack.clipCount <= 0)
            return;
        if (index > 0) {
            NSString *fxName = [_lstVideoFx objectAtIndex:index];
            if ([fxName isEqualToString:@"Beauty"]) {
                
                NvsFxDescription *fxDescription = [_context getVideoFxDescription:fxName];
                NSArray *paramsInfo = [fxDescription getAllParamsInfo];
                for (unsigned int i = 0; i < _videoTrack.clipCount; i++) {
                    NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
                    [videoClip removeAllFx];
                    [videoClip appendBeautyFx];
                }
            }
            else {
                
                if ([fxName isEqualToString:@"None"]) {
                    for (unsigned int i = 0; i < _videoTrack.clipCount; i++)
                        [[_videoTrack getClipWithIndex:i] removeAllFx];
                } else if ([fxName isEqualToString:@"Package1"]) {
                    for (unsigned int i = 0; i < _videoTrack.clipCount; i++) {
                        NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
                        [videoClip removeAllFx];
                        [videoClip appendPackagedFx:_videoFxPackageId];
                    }
                } else {
                    for (unsigned int i = 0; i < _videoTrack.clipCount; i++) {
                        NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
                        [videoClip removeAllFx];
                        [videoClip appendBuiltinFx:fxName];
                    }
                }
            }
        }
        else {
            NSString *transName = [_lstVideoTransition objectAtIndex:index];
            if ([transName isEqualToString:@"None"])
                transName = @"";
            for (unsigned int i = 0; i < _videoTrack.clipCount - 1; i++)
                [_videoTrack setBuiltinTransition:i withName:transName];
        }
        
        [self loadPlay];
    }
    
    - (void)stopPlay
    {
        [self.context stop];
    }
    
    - (void)clearCache
    {
        [self.context stop];
        [self.context clearCachedResources:YES];
        self.context.delegate = nil;
    }
    
    - (UIImage *)selectDefaletCoverImage
    {
        int64_t timeInterval = 1000*500;
        UIImage *image = [self.context grabImageFromTimeline:self.timeLine timestamp:timeInterval proxyScale:nil];
        return image;
    }
    
    - (NSArray *)loadStickerArray
    {
        _stickerPackageId = [[NSMutableString alloc] initWithString:@""];
        NSString *sitckerFilePath = [[[NSBundle mainBundle]bundlePath ]stringByAppendingPathComponent:@"89740AEA-80D6-432A-B6DE-E7F6539C4121.animatedsticker"];
        if (![[NSFileManager defaultManager] fileExistsAtPath:sitckerFilePath]) {
            DDLogError(@"Sticker package file is not exist!");
        } else {
            NvsAssetPackageManagerError error = [self.context.assetPackageManager installAssetPackage:sitckerFilePath license:nil type:NvsAssetPackageType_AnimatedSticker sync:YES assetPackageId:_stickerPackageId];
            if (error != NvsAssetPackageManagerError_NoError && error != NvsAssetPackageManagerError_AlreadyInstalled) {
                DDLogError(@"Failed to install sticker package!");
            }
        }
        return @[@"贴纸"];
    }
    
    - (NSArray *)loadFxArray
    {
        _videoFxPackageId = [[NSMutableString alloc] initWithString:@""];
        bool package1Valid = true;
        NSString *appPath =[[NSBundle mainBundle] bundlePath];
        NSString *package1Path = [appPath stringByAppendingPathComponent:@"7FFCF99A-5336-4464-BACD-9D32D5D2DC5E.videofx"];
        if (![[NSFileManager defaultManager] fileExistsAtPath:package1Path]) {
            DDLogError(@"Video fx package file is not exist!");
            package1Valid = false;
        } else {
            NvsAssetPackageManagerError error = [_context.assetPackageManager installAssetPackage:package1Path license:nil type:NvsAssetPackageType_VideoFx sync:YES assetPackageId:_videoFxPackageId];
            if (error != NvsAssetPackageManagerError_NoError && error != NvsAssetPackageManagerError_AlreadyInstalled) {
                DDLogError(@"Failed to install video fx package!");
                package1Valid = false;
            }
        }
        
        NSMutableArray *lstVideoFx = [NSMutableArray arrayWithObject:@"None"];
        [lstVideoFx addObject:@"Beauty"];
        [lstVideoFx addObjectsFromArray:[_context getAllBuiltinVideoFxNames]];
        if (package1Valid)
            [lstVideoFx addObject:@"Package1"];
        _lstVideoFx = lstVideoFx.copy;
        NSMutableArray *lstVideoTransition = [NSMutableArray arrayWithObject:@"None"];
        [lstVideoTransition addObjectsFromArray:[self.context getAllBuiltinVideoTransitionNames]];
        _lstVideoTransition = lstVideoFx.copy;
        return _lstVideoFx.copy;
    }
    
    #pragma mark - Object Private Function
    
    - (void)beginLoadShortVideo:(NSString *)path
    {
        if ([self.delegate respondsToSelector:@selector(beginLoadShortVideo:)]) {
            [self.delegate beginLoadShortVideo:path];
        }
    }
    
    - (void)saveToLibrary
    {
        if ([self.delegate respondsToSelector:@selector(saveToLibrary)]) {
            [self.delegate saveToLibrary];
        }
    }
    
    - (void)loadLoaderProcess:(NSInteger)process
    {
        if ([self.delegate respondsToSelector:@selector(loadLoaderProcess:)]) {
            [self.delegate loadLoaderProcess:process];
        }
    }
    
    //监听
    
    - (void)didPlaybackEOF:(NvsTimeline *)timeline
    {
        if ([self.delegate respondsToSelector:@selector(didPlaybackEOF:)]) {
            [self.delegate didPlaybackEOF:timeline];
        }
    }
    
    #pragma mark - Lazy Load
    
    - (NvsStreamingContext *)context
    {
        if (!_context) {
            _context = [NvsStreamingContext sharedInstance];
            _context.delegate = self;
        }
        return _context;
    }
    
    #pragma mark - NvsStreamingContextDelegate
    
    - (void)didPlaybackStopped:(NvsTimeline *)timeline
    {
        if ([self.delegate respondsToSelector:@selector(didPlaybackEOF:)]) {
            [self.delegate didPlaybackEOF:timeline];
        }
    }
    
    - (void)didStreamingEngineStateChanged:(NvsStreamingEngineState)state
    {
        if (state == NvsStreamingEngineState_CapturePreview) {
            if ([self.delegate respondsToSelector:@selector(didPlaybackEOF:)]) {
                [self.delegate didPlaybackEOF:_timeLine];
            }
        }
    }
    
    - (void)didFirstVideoFramePresented:(NvsTimeline *)timeline
    {
        if ([self.delegate respondsToSelector:@selector(didPlaySuccess)]) {
            [self.delegate didPlaySuccess];
        }
    }
    
    - (void)didCompileProgress:(NvsTimeline *)timeline progress:(int)progress
    {
        NSLog(@"process  :   %d", progress);
        if (_type == 1) {
            [self loadLoaderProcess:progress/2];
        }
    }
    
    - (void)didCompileFailed:(NvsTimeline *)timeline
    {
        NSLog(@"生成失败");
        if ([self.delegate respondsToSelector:@selector(shortVideoUploadFaile)]) {
            [self.delegate shortVideoUploadFaile];
        }
    }
    
    - (void)didCompileFinished:(NvsTimeline *)timeline
    {
        NSLog(@"生成成功");
        if (_type == 1) {
            [self beginLoadShortVideo:_path];
        }
        else {
            if (_isSave) {
                return;
            }
            if ([self.delegate respondsToSelector:@selector(saveToLibrary)]) {
                _isSave = YES;
                [self.delegate saveToLibrary];
            }
        }
    }
    
    @end
    

    这个工具可以实现对短视频进行特效编辑、背景音乐加载等功能。

    后记

    未完,待续~~~

    金色的路

    相关文章

      网友评论

        本文标题:美摄SDK的使用(四)—— 短视频的编辑工具类的封装

        本文链接:https://www.haomeiwen.com/subject/cxxnrxtx.html