日期:2019-11-14
1.概述
iOS短视频SDK是适用于iOS平台的短视频SDK。使用此SDK可以实现短视频相关功能。
1.1 功能特性
功能 | 描述 |
---|---|
拍摄 | 支持短视频拍摄 |
摄像头切换 | 支持拍摄过程中切换摄像头 |
断点拍摄 | 支持拍摄过程中可暂停 |
美颜滤镜 | 支持拍摄加入美颜滤镜 |
视频时长剪辑 | 支持选取视频时长剪辑 |
视频区域剪辑 | 支持选取视频区域剪辑 |
视频倍速调整 | 支持选取视频倍速调整 |
多视频合成 | 支持多视频合成 |
视频水印 | 支持根据时段,位置添加视频水印 |
气泡文字 | 支持根据时段,位置添加气泡文字 |
音频插入 | 支持对视频插入背景音乐 |
视频大小修改 | 支持修改视频分辨率 |
1.2 阅读对象
本文档为技术文档,需要阅读者:
-
具备基本的iOS开发能力
-
准备接入CC视频的短视频SDK
2.开发准备
2.1 开发环境
-
Xcode:苹果官方IDE
-
iOS8+
2.2 SDK使用说明
首先,需要下载最新版本的SDK,下载地址为:VOD_iOS_ShortVideo_SDK,然后导入SDK包到工程,在相应地方引入头文件#import "DWShortSDK"
名称 | 描述 |
---|---|
Demo | 使用SDK的示例源码 |
doc | 存放的是iOS短视频SDK开发指南html文档 |
include | SDK开放的头文件及静态库 |
3.快速集成
注:快速集成主要提供的是拍摄功能
3.1 拍摄快速集成
3.1.1 SDK添加到项目后,在info.plist文件设置麦克风 相机 相册 图片权限
<!-- 相册 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>App需要您的同意,才能访问相册</string>
<!-- 相机 -->
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能访问相机</string>
<!-- 麦克风 -->
<key>NSMicrophoneUsageDescription</key>
<string>App需要您的同意,才能访问麦克风</string>
<!-- 图片 -->
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App需要您的同意,才能保存图片到您的相册</string>
3.1.2 基于GPUImage 建议用cocoapods导入 也可手动导入 确保工程中只导入一次GPUImage
3.1.3 GPUImage引入后 修改以下部分:
1.GPUImageMovieWriter.h文件中添加isNeedBreakAudioWhiter属性
@property (nonatomic, assign) BOOL isNeedBreakAudioWhiter;
2.GPUImageMovieWriter.m文件中第377行代码修改如下:
if (CMTIME_IS_INVALID(startTime))
{
if (_isNeedBreakAudioWhiter) {
}else{
runSynchronouslyOnContextQueue(_movieWriterContext, ^{
if ((audioInputReadyCallback == NULL) && (assetWriter.status != AVAssetWriterStatusWriting))
{
[assetWriter startWriting];
}
[assetWriter startSessionAtSourceTime:currentSampleTime];
startTime = currentSampleTime;
});
}
}
3.GPUImageMovieWriter初始化时设置 isNeedBreakAudioWhiter =YES;
具体详情参见demo
3.1.3 初始化相机
//录制相关
self.videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720
cameraPosition:AVCaptureDevicePositionBack];
if ([self.videoCamera.inputCamera lockForConfiguration:nil]) {
//自动对焦
if ([self.videoCamera.inputCamera isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
[self.videoCamera.inputCamera setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
}
//自动曝光
if ([self.videoCamera.inputCamera isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
[self.videoCamera.inputCamera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}
//自动白平衡
if ([self.videoCamera.inputCamera isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) {
[self.videoCamera.inputCamera setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
}
[self.videoCamera.inputCamera unlockForConfiguration];
}
//输出方向为竖屏
self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
//防止允许声音通过的情况下,避免录制第一帧黑屏闪屏
[self.videoCamera addAudioInputsAndOutputs];
self.videoCamera.horizontallyMirrorFrontFacingCamera = YES;
self.videoCamera.horizontallyMirrorRearFacingCamera = NO;
//相机开始运行
[self.videoCamera startCameraCapture];
3.1.4 初始化moviewriter
//苹果默认是MOV格式
NSString *path =[self getVideoSaveFilePathString:@".MOV" addPathArray:YES];
unlink([path UTF8String]);
self.videoURL = [NSURL fileURLWithPath:path];
//写入
CGSize size = CGSizeZero;
if (self.scale == 0) {
//9:16
size = CGSizeMake(720.0, 1280.0);
}else if (self.scale == 1){
//3:4
size = CGSizeMake(720.0, 960.0);
}else{
//1:1
size = CGSizeMake(720.0, 720.0);
}
self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:self.videoURL size:size];
//设置为liveVideo
self.movieWriter.isNeedBreakAudioWhiter =YES;
self.movieWriter.encodingLiveVideo = YES;
self.movieWriter.shouldPassthroughAudio =YES;
//根据实际需求,添加滤镜链
if (self.filter) {
if (self.isBeautyFilter) {
if (self.isBilateralExist) {
[self.bilateralFilter addTarget:self.movieWriter];
}else{
[self.brightnessFilter addTarget:self.movieWriter];
}
}else{
[self.filter addTarget:self.movieWriter];
}
}else{
if (self.isBeautyFilter) {
if (self.isBilateralExist) {
[self.bilateralFilter addTarget:self.movieWriter];
}else{
[self.brightnessFilter addTarget:self.movieWriter];
}
}else{
[self.videoCamera addTarget:self.movieWriter];
}
}
//设置声音
self.videoCamera.audioEncodingTarget = self.movieWriter;
4.功能使用
4.1 删除功能具体使用
BOOL isSuccess = [DWShortTool dw_deleteFileWithFilePath:filePath];
if (self.pathArray.count == 0) {
return YES;
}
if (isSuccess) {
[self.pathArray removeLastObject];
UIView * view = [self.viewArray lastObject];
[view removeFromSuperview];
[self.viewArray removeLastObject];
//要减去相应的录制时间
double recordTime =[[self.secondsArray lastObject] doubleValue];
self.totalTime -= recordTime;
[self.secondsArray removeLastObject];
[self.bottomView setRecordTime:self.totalTime];
NSLog(@"余下录制时间%f__%f",self.totalTime,recordTime);
}
4.2 相机功能具体使用
//闪光灯的使用
//前置摄像头不打开闪光灯
if (self.videoCamera.inputCamera.position == AVCaptureDevicePositionFront) {
return;
}
button.selected = !button.selected;
if (self.videoCamera.inputCamera.position == AVCaptureDevicePositionBack) {
if (self.videoCamera.inputCamera.torchMode ==AVCaptureTorchModeOn) {
[self.videoCamera.inputCamera lockForConfiguration:nil];
[self.videoCamera.inputCamera setTorchMode:AVCaptureTorchModeOff];
[self.videoCamera.inputCamera setFlashMode:AVCaptureFlashModeOff];
[self.videoCamera.inputCamera unlockForConfiguration];
}else{
[self.videoCamera.inputCamera lockForConfiguration:nil];
[self.videoCamera.inputCamera setTorchMode:AVCaptureTorchModeOn];
[self.videoCamera.inputCamera setFlashMode:AVCaptureFlashModeOn];
[self.videoCamera.inputCamera unlockForConfiguration];
}
}
//前后摄像头切换
[self.videoCamera rotateCamera];
4.3 美颜滤镜功能具体使用
//再添加新的滤镜效果前,首先移除响应链上的滤镜
[self removeAllTarget];
if (type == 0) {
self.filter = nil;
}
//根据滤镜效果,添加合适的滤镜。
//这里的滤镜效果仅供参考,更多效果请详见GPUImage功能介绍。
if (type == 1) {
GPUImageSaturationFilter * saturationFilter = [[GPUImageSaturationFilter alloc]init];
saturationFilter.saturation = 2;
self.filter = saturationFilter;
}
if (type == 2) {
GPUImageSaturationFilter * saturationFilter = [[GPUImageSaturationFilter alloc]init];
saturationFilter.saturation = 0.7;
self.filter = saturationFilter;
}
if (type == 3) {
GPUImageWhiteBalanceFilter * whiteBalanceFilter = [[GPUImageWhiteBalanceFilter alloc]init];
whiteBalanceFilter.temperature = 4500;
self.filter = whiteBalanceFilter;
}
if (type == 4) {
GPUImageSepiaFilter * sepiaFilter = [[GPUImageSepiaFilter alloc]init];
self.filter = sepiaFilter;
}
if (type == 5) {
GPUImageExposureFilter * exposureFilter = [[GPUImageExposureFilter alloc]init];
exposureFilter.exposure = 0.3;
self.filter = exposureFilter;
}
//添加新的滤镜响应链
if (self.filter) {
if (self.isBeautyFilter) {
if (self.isBilateralExist) {
[self.videoCamera addTarget:self.filter];
[self.filter addTarget:self.brightnessFilter];
[self.brightnessFilter addTarget:self.bilateralFilter];
[self.bilateralFilter addTarget:self.filterView];
}else{
[self.videoCamera addTarget:self.filter];
[self.filter addTarget:self.brightnessFilter];
[self.brightnessFilter addTarget:self.filterView];
}
}else{
[self.videoCamera addTarget:self.filter];
[self.filter addTarget:self.filterView];
}
}else{
if (self.isBeautyFilter) {
if (self.isBilateralExist) {
[self.videoCamera addTarget:self.brightnessFilter];
[self.brightnessFilter addTarget:self.bilateralFilter];
[self.bilateralFilter addTarget:self.filterView];
}else{
[self.videoCamera addTarget:self.brightnessFilter];
[self.brightnessFilter addTarget:self.filterView];
}
}else{
[self.videoCamera addTarget:self.filterView];
}
}
}
4.4 暂停or开始录制
//开始录制
//UI修改
[self hiddenAllView:YES];
[self.bottomView setStyle:2];
if (self.isDelay) {
//__weak typeof(self) weakSelf = self;
//开始延迟计时
DWDelayView * delayView = [[DWDelayView alloc]init];
[delayView beginAnimation];
delayView.finish = ^{
//进度条
[self initProgressView];
self.seconds = 0;
[self gcdTimer];
//开始录制
[self initMovieWriter];
[self.movieWriter startRecording];
};
return;
}
//进度条
[self initProgressView];
self.seconds = 0;
//启动计时器
[self gcdTimer];
//开始录制
[self initMovieWriter];
[self.movieWriter startRecording];
//暂停录制
//UI修改
[self hiddenAllView:NO];
[self.bottomView setStyle:3];
//移除定时器
[self removeTimer];
//暂停写入
[self.movieWriter finishRecording];
self.videoCamera.audioEncodingTarget = nil;
[self.secondsArray addObject:[NSString stringWithFormat:@"%f",self.seconds]];
//保存视频到本地
[self savePhotosAlbum:self.videoURL];
4.5 断点拍摄功能具体使用
断点拍摄后的几个小视频可以合成为一个视频,DWShortTool提供了接口(4.10.4)用于此功能。
//延迟执行,等待视频写入完成。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//合成视频输出路径
NSString * path = [self getVideoSaveFilePathString:@".MOV" addPathArray:NO];
self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
self.hud.removeFromSuperViewOnHide = YES;
self.hud.label.text = @"视频生成中";
[DWShortTool dw_compositeAndExportVideos:self.pathArray withVideoSize:CGSizeZero outPath:path outputFileType:AVFileTypeQuickTimeMovie presetName:AVAssetExportPresetHighestQuality didComplete:^(NSError *error, NSURL *compressionFileURL) {
[self.hud hideAnimated:YES];
if (!error) {
DWShortVideoEditViewController * shortVideoEditVC = [[DWShortVideoEditViewController alloc]init];
shortVideoEditVC.videoURL = [NSURL fileURLWithPath:path];
[self presentViewController:shortVideoEditVC animated:YES completion:nil];
}else{
[@"合成失败,请重试" showAlert];
}
}];
});
4.6 视频剪辑功能的使用
通过设置裁剪时间,裁剪范围,裁剪倍速来对视频进行剪辑处理。DWShortTool提供了接口(4.10.2)用于此功能。
NSString *videoPath = [self createFilePath];
MBProgressHUD * hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.removeFromSuperViewOnHide = YES;
[DWShortTool dw_videoSizeAndTimeCropAndExportVideo:self.videoURL.absoluteString
size:self.cropView.scaleFrame.size
point:self.cropView.scaleFrame.origin
range:CMTimeRangeMake(self.cropView.start, self.cropView.duration)
videoRate:self.cropView.speed
withOutPath:videoPath
outputFileType:AVFileTypeQuickTimeMovie
presetName:AVAssetExportPresetHighestQuality
didComplete:^(NSError *error, NSURL *compressionFileURL) {
[hud hideAnimated:YES];
if (error) {
[error.localizedDescription showAlert];
return;
}
//剪辑完成,跳转编辑页面
DWShortVideoEditViewController * shortVideoEditVC = [[DWShortVideoEditViewController alloc]init];
shortVideoEditVC.videoURL = compressionFileURL;
[self presentViewController:shortVideoEditVC animated:YES completion:nil];
}];
4.7 插入背景音乐功能的使用
可以设置新的背景音乐插入到原视频中。DWShortTool提供了接口(4.10.5)用于此功能。
//判断是否选择了音频
BOOL select = NO;
for (NSDictionary * dict in self.musicListArray) {
if ([[dict objectForKey:@"isSelect"] boolValue]) {
select = YES;
break;
}
}
if (!select) {
self.musicDict = nil;
[self addStickerWithVideoUrl:videoUrl];
return;
}
//插入音频
NSString * outPath = [self createFilePath];
// NSURL * outPathUrl = [NSURL fileURLWithPath:outPath];
[DWShortTool dw_insertAudioAndExportVideo:videoUrl.absoluteString
withAudioPath:[self.musicDict objectForKey:@"audioPath"]
originalVolume:[[self.musicDict objectForKey:@"originalVolume"] floatValue]
insertVolume:[[self.musicDict objectForKey:@"insertVolume"] floatValue]
timeRange:CMTimeRangeMake([[self.musicDict objectForKey:@"start"] CMTimeValue], [[self.musicDict objectForKey:@"duration"] CMTimeValue])
outPath:outPath
outputFileType:OUTPUTFILETYPE
presetName:PRESETNAME
didComplete:^(NSError *error, NSURL *compressionFileURL) {
if (error) {
[self.editAndUploadVC endEditWithSuccess:NO];
[error.localizedDescription showAlert];
return;
}
}];
4.8 贴纸功能的使用
通过设置贴纸图片,贴纸位置(注意,贴纸point,size的参数为百分比),以及贴纸出现的时间范围为原视频增加视频贴纸。DWShortTool提供了接口(4.10.3)用于此功能。
if (!self.canEdit) {
return;
}
//判断是否添加贴纸
if (self.stickerArray.count == 0) {
[self addBubbleVideoUrl:videoUrl];
return;
}
NSString * outPath = [self createFilePath];
NSArray * images = @[@"icon_sticker_1.png",@"icon_sticker_2.png",@"icon_sticker_3.png",@"icon_sticker_4.png",@"icon_sticker_5.png"];
NSMutableArray * stickerImages = [NSMutableArray array];
NSMutableArray * stickerImagePoints = [NSMutableArray array];
NSMutableArray * stickerImageSizes = [NSMutableArray array];
NSMutableArray * rotateAngles = [NSMutableArray array];
NSMutableArray * timeRanges = [NSMutableArray array];
for (NSDictionary * dict in self.stickerArray) {
UIImage * stickerImage = [UIImage imageNamed:[images objectAtIndex:[[dict objectForKey:@"index"] integerValue]]];
LINConversionView * conversionView = [dict objectForKey:@"object"];
CGRect frame = conversionView.frame;
CGAffineTransform transform = conversionView.transform;
CGFloat rotate = [self getAngleFromAffineTransform:transform];
CGFloat sizeLength = [self getStickerSideLengthWithView:conversionView];
//计算偏移量
CGFloat offset = (conversionView.frame.size.width - sizeLength) / 2.0;
CGPoint offsetPoint = CGPointMake(frame.origin.x + offset, frame.origin.y + offset);
//百分比
CGPoint stickerImagePoint = CGPointMake((offsetPoint.x - self.videoBackground.origin.x) / self.videoBackground.size.width, (offsetPoint.y - self.videoBackground.origin.y) / self.videoBackground.size.height);
CGSize stickerImageSize = CGSizeMake(sizeLength / self.videoBackground.size.width, sizeLength / self.videoBackground.size.height);
CMTime start = [[dict objectForKey:@"start"] CMTimeValue];
CMTime duration = [[dict objectForKey:@"duration"] CMTimeValue];
//如果需要整个视频都添加贴纸,传kCMTimeZero即可。
if (CMTimeCompare(duration, self.videoDuration) == 0) {
duration = kCMTimeZero;
}
CMTimeRange timeRange = CMTimeRangeMake(start, duration);
[stickerImages addObject:stickerImage];
[stickerImagePoints addObject:[NSValue valueWithCGPoint:stickerImagePoint]];
[stickerImageSizes addObject:[NSValue valueWithCGSize:stickerImageSize]];
[rotateAngles addObject:[NSNumber numberWithFloat:rotate]];
[timeRanges addObject:[NSValue valueWithCMTimeRange:timeRange]];
}
[DWShortTool dw_addStickerAndExportVideo:videoUrl.absoluteString
withStickerImages:stickerImages
stickerImagePoints:stickerImagePoints
stickerImageSizes:stickerImageSizes
rotateAngles:rotateAngles
timeRanges:timeRanges
outPath:outPath
outputFileType:OUTPUTFILETYPE
presetName:PRESETNAME
didComplete:^(NSError *error, NSURL *compressionFileURL) {
if (error) {
[self.editAndUploadVC endEditWithSuccess:NO];
return;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self addBubbleVideoUrl:compressionFileURL];
});
}];
4.9 气泡文字功能的使用
添加逻辑同4.8,贴纸图片需要通过背景图与文字生成。
if (!self.canEdit) {
return;
}
if (self.bubbleArray.count == 0) {
[self.editAndUploadVC endEditWithSuccess:YES];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:videoUrl completionBlock:^(NSURL *assetURL, NSError *error)
{
}];
return;
}
NSString * outPath = [self createFilePath];
NSMutableArray * bubbleImages = [NSMutableArray array];
NSMutableArray * bubbleImagePoints = [NSMutableArray array];
NSMutableArray * bubbleImageSizes = [NSMutableArray array];
NSMutableArray * rotateAngles = [NSMutableArray array];
NSMutableArray * timeRanges = [NSMutableArray array];
for (NSDictionary * dict in self.bubbleArray) {
LINConversionView * conversionView = [dict objectForKey:@"object"];
CGRect frame = conversionView.frame;
CGAffineTransform transform = conversionView.transform;
CGFloat rotate = [self getAngleFromAffineTransform:transform];
CGFloat sizeLength = [self getStickerSideLengthWithView:conversionView];
//计算偏移量
CGFloat offset = (conversionView.frame.size.width - sizeLength) / 2.0;
CGPoint offsetPoint = CGPointMake(frame.origin.x + offset, frame.origin.y + offset);
//获取贴纸所占视频区域的百分比
CGPoint bubbleImagePoint = CGPointMake((offsetPoint.x - self.videoBackground.origin.x) / self.videoBackground.size.width, (offsetPoint.y - self.videoBackground.origin.y) / self.videoBackground.size.height);
CGSize bubbleImageSize = CGSizeMake(sizeLength / self.videoBackground.size.width, sizeLength / self.videoBackground.size.height);
CMTime start = [[dict objectForKey:@"start"] CMTimeValue];
CMTime duration = [[dict objectForKey:@"duration"] CMTimeValue];
//如果需要整个视频都添加贴纸,传kCMTimeZero即可。
if (CMTimeCompare(duration, self.videoDuration) == 0) {
duration = kCMTimeZero;
}
CMTimeRange timeRange = CMTimeRangeMake(start, duration);
//生成贴纸图片
[bubbleImages addObject:[self bubbleImageWithBubbleDict:dict]];
[bubbleImagePoints addObject:[NSValue valueWithCGPoint:bubbleImagePoint]];
[bubbleImageSizes addObject:[NSValue valueWithCGSize:bubbleImageSize]];
[rotateAngles addObject:[NSNumber numberWithFloat:rotate]];
[timeRanges addObject:[NSValue valueWithCMTimeRange:timeRange]];
}
[DWShortTool dw_addStickerAndExportVideo:videoUrl.absoluteString
withStickerImages:bubbleImages
stickerImagePoints:bubbleImagePoints
stickerImageSizes:bubbleImageSizes
rotateAngles:rotateAngles
timeRanges:timeRanges
outPath:outPath
outputFileType:OUTPUTFILETYPE
presetName:PRESETNAME
didComplete:^(NSError *error, NSURL *compressionFileURL) {
if (error) {
[self.editAndUploadVC endEditWithSuccess:NO];
return;
}
[self.editAndUploadVC endEditWithSuccess:YES];
//保存视频到本地相册
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:compressionFileURL completionBlock:^(NSURL *assetURL, NSError *error)
{
}];
}];
//生成气泡文字图片
-(UIImage *)bubbleImageWithBubbleDict:(NSDictionary *)dict
{
NSArray * images = @[@"icon_bubble_1.png",@"icon_bubble_2.png",@"icon_bubble_3.png",@"icon_bubble_4.png",@"icon_bubble_5.png"];
//总体生成图片
UIImage * bubbleImage = [UIImage imageNamed:[images objectAtIndex:[[dict objectForKey:@"index"] integerValue]]];
LINConversionView * conversionView = [dict objectForKey:@"object"];
DWBubbleInputView * inputView = (DWBubbleInputView *)conversionView.contentView;
UIImageView * bubbleImageView = [[UIImageView alloc]init];
CGFloat sizeLength = [self getStickerSideLengthWithView:conversionView];
bubbleImageView.frame = CGRectMake(0, 0, sizeLength, sizeLength);
bubbleImageView.image = bubbleImage;
UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(bubbleImageView.frame.size.width * 32 / BUBBLEWIDTH, bubbleImageView.frame.size.height * 102 / BUBBLEWIDTH, bubbleImageView.frame.size.width - (bubbleImageView.frame.size.width * 32 / BUBBLEWIDTH) * 2, bubbleImageView.frame.size.height * 49 / BUBBLEWIDTH)];
label.text = inputView.placeholderLabel.text;
label.font = inputView.placeholderLabel.font;
label.textColor = inputView.placeholderLabel.textColor;
label.textAlignment = inputView.placeholderLabel.textAlignment;
label.numberOfLines = 2;
label.adjustsFontSizeToFitWidth = YES;
[bubbleImageView addSubview:label];
UIGraphicsBeginImageContextWithOptions(bubbleImageView.bounds.size, NO, 0);
if ([bubbleImageView respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[bubbleImageView drawViewHierarchyInRect:bubbleImageView.bounds afterScreenUpdates:YES];
}else{
[bubbleImageView.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
4.10 工具类DWShortTool接口功能
4.10.1 视频压缩
/// 压缩视频
/// @param videoPath 视频路径
/// @param outPath 输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后回调
+ (void)dw_compressionAndExportVideo:(NSString *)videoPath
withOutPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL) )completeBlock;
4.10.2 视频剪辑
4.10.2.1 视频时长剪辑 视频区域不变
/// 视频时长剪辑 视频区域不变
/// @param videoPath 视频路径
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param timeRange 截取视频的时间范围
/// @param completeBlock 完成后回调
+ (void)dw_videoTimeCropAndExportVideo:(NSString *)videoPath
withOutPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
range:(CMTimeRange)timeRange
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.2.2 视频区域剪裁 视频时长不变
/// 视频区域剪裁 视频时长不变
/// @param videoPath 视频路径
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param videoSize 剪裁区域
/// @param videoPoint 剪裁起点
/// @param shouldScale 是否拉伸 YES拉伸 NO不拉伸 剪裁黑背景
/// @param completeBlock 剪裁完成后的回调
+ (void)dw_videoSizeCropAndExportVideo:(NSString *)videoPath
withOutPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
size:(CGSize)videoSize
point:(CGPoint)videoPoint
shouldScale:(BOOL)shouldScale
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.2.3 视频区域兼时长剪裁
/// 视频区域兼时长剪裁
/// @param videoPath 视频路径
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param videoSize 剪裁区域
/// @param videoPoint 剪裁起点
/// @param shouldScale 是否拉伸 YES拉伸 NO不拉伸 剪裁黑背景
/// @param timeRange 截取视频的时间范围
/// @param completeBlock 剪裁完成后的回调
+ (void)dw_videoSizeAndTimeCropAndExportVideo:(NSString *)videoPath
withOutPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
size:(CGSize)videoSize
point:(CGPoint)videoPoint
shouldScale:(BOOL)shouldScale
range:(CMTimeRange)timeRange
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.2.4 视频区域,时长,倍速剪裁
/// 视频区域,时长,倍速剪裁
/// @param videoPath 视频路径
/// @param videoSize 剪裁区域,CGSizeZero不裁剪
/// @param videoPoint 剪裁起点
/// @param timeRange 截取视频的时间范围,kCMTimeRangeZero,不裁剪时长
/// @param videoRate 截取视频倍速
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后的回调
+ (void)dw_videoSizeAndTimeCropAndExportVideo:(NSString *)videoPath
size:(CGSize)videoSize
point:(CGPoint)videoPoint
range:(CMTimeRange)timeRange
videoRate:(CGFloat)videoRate
withOutPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.3 新增视频水印
4.10.3.1 添加单个视频水印
/// 添加单个视频水印
/// @param videoPath 视频路径
/// @param stickerImage 水印图片
/// @param stickerImagePoint 水印位置,point为水印所占视频位置的百分比。eg:CGPointMake(0.1, 0.1)
/// @param stickerImageSize 水印大小,为水印所占视频大小的百分比。eg:CGSizeMake(0.4, 0.4)
/// @param rotateAngle 水印旋转弧度。eg:M_PI_2
/// @param timeRange 添加水印的时间范围,kCMTimeRangeZero时,全部时长都添加水印
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后的回调
+ (void)dw_addStickerAndExportVideo:(NSString *)videoPath
withStickerImage:(UIImage *)stickerImage
stickerImagePoint:(CGPoint)stickerImagePoint
stickerImageSize:(CGSize)stickerImageSize
rotateAngle:(CGFloat)rotateAngle
timeRange:(CMTimeRange)timeRange
outPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.3.2 批量添加视频水印
/// 批量添加视频水印
/// @param videoPath 视频路径
/// @param stickerImages 水印图片数组
/// @param stickerImagePoints 水印位置数组,points为水印所占视频位置的百分比数组。eg:@[[NSValue valueWithCGPoint:CGPointMake(0.1, 0.1)]]
/// @param stickerImageSizes 水印大小数组,sizes为水印所占视频大小的百分比数组。eg:@[[NSValue valueWithCGPoint:CGSizeMake(0.4, 0.4)]]
/// @param rotateAngles 水印旋转弧度数据。eg:[NSNumber numberWithFloat:M_PI_2]
/// @param timeRanges 添加水印的时间范围数组,kCMTimeRangeZero时,全部时长都添加水印
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后的回调
+ (void)dw_addStickerAndExportVideo:(NSString *)videoPath
withStickerImages:(NSArray <UIImage *>*)stickerImages
stickerImagePoints:(NSArray <NSValue *> *)stickerImagePoints
stickerImageSizes:(NSArray <NSValue *> *)stickerImageSizes
rotateAngles:(NSArray <NSNumber *> *)rotateAngles
timeRanges:(NSArray <NSValue *> *)timeRanges
outPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.4 多视频合成
/// 多视频合成
/// @param videosPath 视频路径数组
/// @param videoSize 合成视频尺寸,不设置(CGRectZero)默认取第一个视频大小为基准
/// @param outPath 输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后的回调
+(void)dw_compositeAndExportVideos:(NSArray <NSString *>*)videosPath
withVideoSize:(CGSize)videoSize
outPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.5 插入音频
/// 插入音频
/// @param videoPath 视频路径
/// @param audioPath 待插入音频路径
/// @param originalVolume 原音频音量
/// @param insertVolume 插入音频音量
/// @param timeRange 插入音频范围,kCMTimeRangeZero时,从0开始添加
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后的回调
+(void)dw_insertAudioAndExportVideo:(NSString *)videoPath
withAudioPath:(NSString *)audioPath
originalVolume:(CGFloat)originalVolume
insertVolume:(CGFloat)insertVolume
timeRange:(CMTimeRange)timeRange
outPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.6 修改视频分辨率
/// 修改视频分辨率
/// @param videoPath 视频路径
/// @param videoSize 要输出的视频分辨率
/// @param outPath 视频输出路径
/// @param outputFileType 视频格式
/// @param presetName 视频导出质量
/// @param completeBlock 完成后的回调
+ (void)dw_videoSizeChangeRenderAndExportVideo:(NSString *)videoPath
videoSize:(CGSize)videoSize
withOutPath:(NSString *)outPath
outputFileType:(NSString *)outputFileType
presetName:(NSString *)presetName
didComplete:(void(^)(NSError *error,NSURL *compressionFileURL))completeBlock;
4.10.7 其他开放接口
/// 取得缩略图
/// @param videoPath 文件路径
/// @param time 第几秒的缩略图
+(UIImage *)dw_getThumbnailImage:(NSString *)videoPath time:(NSTimeInterval)time;
/// 十六进制色彩
/// @param string 色值
+(UIColor *)dw_colorWithHexString:(NSString *)string;
/// 删除文件
/// @param filePath 文件路径 并返回是否成功
+(BOOL)dw_deleteFileWithFilePath:(NSString *)filePath;
/// 获取文件大小
/// @param filePath 文件路径
+(CGFloat)dw_fileSizeAtPath:(NSString*)filePath;
4.11 Demo具体使用
Demo是示例源码,可直接用Xcode运行。Demo的设计旨在展示SDK各项功能的使用方法,如果希望应用获得更好的使用体验,要根据需求自行更改。 如果在使用SDK过程中遇到其他问题请联系CC客服进行反馈。
5.API 查询
https://github.com/CCVideo/VOD_iOS_ShortVideo_SDK/tree/master/doc/api