必须保证应用包名和license匹配
必须保证素材资源包和license匹配
必须保证license在有效期内
素材的路径输入是正确的
如果初始化成功,请检查设置的美颜素材路径对应的文件是否存在。
检测素材路径是否正确设置
示例:
// 如果bgm本身的时长比视频长,则保持音频素材的出点trimOut为视频的时长10s (trimOut不能传-1) editor.addAudioTrack(path, 0, 10*1000 , 0, 10*1000 , false , true )
参数说明:
/** * 添加背景音乐 * 如果needPrepare为true,则该接口调完后,engine会处于prepared状态 {@link VEState} * 注: 该接口添加的音乐支持调整所添加的音乐在视频中开始播放的时间点,支持变速播放 * (trimOut-trimIn) / (sequenceOut - sequenceIn) != 1 时会变速播放 * * @param file 背景音乐全路径。 * @param trimIn 背景音乐素材自身入点 单位:毫秒 * @param trimOut 背景音乐素材自身出点 单位:毫秒 * @param sequenceIn 开始播放时间点 单位:毫秒 * @param sequenceOut 结束播放时间点 单位:毫秒 * @param isCycle 背景音乐是否循环播放填充满整个视频 * @param needPrepare 添加的音乐是否有可能影响整体时长,是的话必须为true,添加后从头播放 * @return 非负值:添加的trackindex,负值:添加失败({@link VEResult}) * @since 2.1.0 */ public int addAudioTrack(String file, int trimIn, int trimOut, int sequenceIn, int sequenceOut, boolean isCycle, boolean needPrepare)
添加音频时自定义音频长度,主要是设置音频的clipRang
1、修改下 clipRang - (void)addAudioResource:(NSURL *)audioUrl audioName:(NSString *)audioName startTime:(NSTimeInterval)startTime Duration:(NSTimeInterval)duration { AVURLAsset *asset = [AVURLAsset assetWithURL:audioUrl]; // NLE [self addAudioTrack:asset targetStartTime:self.mediaContext.currentTime audioName:audioName Duration:duration]; IESMMVideoDataClipRange *clipRang = IESMMVideoDataClipRangeMakeV2(0, duration, self.editManager.currentPlayerTime, 0); [self.editManager hotAppendAudioAsset:asset withRange:clipRang]; [self updateVideoDataMaxTrack]; } 2、修改下NLE的rang - (void)addAudioTrack:(AVURLAsset *)asset targetStartTime:(CMTime)targetStartTime audioName:(NSString *)audioName Duration:(NSTimeInterval)duration { NSTimeInterval startTime = CMTimeGetSeconds(targetStartTime); NLETrack_OC *track = [[NLETrack_OC alloc] init]; track.extraTrackType = NLETrackAUDIO; NLEResourceAV_OC *audioResource = [[NLEResourceAV_OC alloc] init]; [audioResource setupForAudioWithAsset:asset]; audioResource.name = audioName; audioResource.resourceFile = asset.URL.absoluteString.lastPathComponent; NLESegmentAudio_OC *audioSegment = [[NLESegmentAudio_OC alloc] init]; audioSegment.audioFile = audioResource; audioSegment.timeClipStart = CMTimeMake(0 * USEC_PER_SEC, USEC_PER_SEC); audioSegment.timeClipEnd = CMTimeMake(duration * USEC_PER_SEC, USEC_PER_SEC);; NLETrackSlot_OC *trackSlot = [[NLETrackSlot_OC alloc] init]; [trackSlot setSegmentAudio:audioSegment]; trackSlot.startTime = CMTimeMake(startTime * USEC_PER_SEC, USEC_PER_SEC); trackSlot.duration = CMTimeMake(duration * USEC_PER_SEC, USEC_PER_SEC); [self.mediaContext addSlotsWithSlots:@[trackSlot] assets:@[asset] inTrack:track]; [[self.mediaContext.editor getModel] addTrack:track]; [self.slotMap setValue:asset forKey:trackSlot.slotID]; [self commitNLE:YES]; }
android { buildTypes { release { aaptOptions { ignoreAssetsPattern '!model:' } } debug { aaptOptions { ignoreAssetsPattern '!model:' } } } }
EditToBActivity 里面调用 trackPanel.findViewById(R.id.ivAdd).setVisibility(View.GONE);
addButton该属性设置隐藏
//拍照和预览的分辨率 //录制视频的配置 VEVideoEncodeSettings videoEncodeSettings = new VEVideoEncodeSettings.Builder(VEVideoEncodeSettings.USAGE_RECORD) .setVideoRes(720, 1280) //录制的视频分辨率 .build(); //预览及其策略的配置 VEPreviewSettings previewSettings = new VEPreviewSettings.Builder() .setRenderSize(new VESize(720, 1280)) //设置预览分辨率即sdk渲染的纹理大小 .blockRenderExit(true) .enableCheckStatusWhenStopPreview(true) .build();
VEDisplaySettings settings = new VEDisplaySettings.Builder() /** * 设置显示比例,视频高/视频宽 比如宽高比=18:9,则ratio=9.0f / 18 = 0.5f */ .setDisplayRatio(height * 1.0f / width) .build(); //1. 切换预览 recorder.setDisplaySettings(settings); //2. 同时设置输出视频的分辨率,即拍摄后合成的视频的分辨率 recorder.changeVideoOutputSize( 720 , 720 );
关于画面比例和分辨率的设置参考以下方法
1、初始化设置 _config = [[IESMMCameraConfig alloc] init]; _config.capturePreset = AVCaptureSessionPreset1920x1080;//设置分辨率 _config.captureRatio = IESMMCaptureRatio9_16; //设置画面比例 2、调整分辨率 参考Demo - (void)dealResolutionWithValue:(VEBarValue *)barValue [self.recorder resetCapturePreset:self.curPreset then:^{}]; 3、调整比例 参考Demo - (void)dealRatioWithValue:(VEBarValue *)barValue [self ratioWithCommand:self.curRatio orientation:self.preDeviceOrientation]; 4、导出设置 参考Demo - (void)exportVideoWithVideoData:(HTSVideoData *)videodata Progress:(void (^_Nullable )(CGFloat progress))progressBlock resultBlock:(void (^)(NSError *error,id result))exportBlock videoData.canvasSize = videodata.transParam.targetVideoSize;//设置这个参数
轨道上显示的帧缩略图是某个时刻的预览效果图,因为缩放问题,不可能每帧都显示在轨道上,所以是间隔一段时间来展示帧缩略图,在这一段时间里视频变化并不能体现在当前缩略图上,可以双指缩放来提高精度。
1.普通水印,即一张静止图片
// 初始化水印 UIImage *image = [UIImage imageNamed:@"logo"]; CGSize imageSize = CGSizeMake(image.size.width / config.outputSize.width, image.size.height / config.outputSize.height); CGRect frame = CGRectMake(0.5, 0.5, imageSize.width, imageSize.height); //注意这里frame都是相对于导出视频大小的比例 IESSticker *sticker = [IESSticker stickerWithImage:image frame:frame rotate:1 opaque:1.0]; // 配置到recorder config.isRecordWithWaterMark = YES; config.recorderSticker = sticker;
2.动画水印
// 组成抖音logo的五张图片 UIImage *image0 = [UIImage imageNamed:@"logo0"]; UIImage *image1 = [UIImage imageNamed:@"logo1"]; UIImage *image2 = [UIImage imageNamed:@"logo2"]; UIImage *image3 = [UIImage imageNamed:@"logo3"]; UIImage *image4 = [UIImage imageNamed:@"logo4"]; // 水印动画关键帧,表示在某个时间点展示哪张图片 IESStickerAnimation *animation = [[IESStickerAnimation alloc] init]; animation.frameTs = @[[NSValue valueWithCMTime:CMTimeMake(000, 1000)], [NSValue valueWithCMTime:CMTimeMake(100, 1000)], [NSValue valueWithCMTime:CMTimeMake(200, 1000)], [NSValue valueWithCMTime:CMTimeMake(300, 1000)], [NSValue valueWithCMTime:CMTimeMake(400, 1000)]]; animation.values = @[image0, image1, image2, image3, image4]; animation.repeatType = kIESAnimationRepeatFromBegin; animation.type = kIESStickerAttributeTypeImage; animation.isAbsoluteFrameTs = NO; // 初始化水印 CGSize imageSize = CGSizeMake(image.size.width / config.outputSize.width, image.size.height / config.outputSize.height); CGRect frame = CGRectMake(0.5, 0.5, imageSize.width, imageSize.height); //注意这里frame都是相对于导出视频大小的比例 IESAnimationSticker *sticker = [IESAnimationSticker stickerWithImage:image frame:frame rotate:1 opaque:1.0]; [sticker addAnimation:animation]; // 配置到recorder里 config.isRecordWithWaterMark = YES; config.recorderSticker = sticker;