UGCKitCutViewController.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. // Copyright (c) 2019 Tencent. All rights reserved.
  2. #import "SDKHeader.h"
  3. #import "UGCKitCutViewController.h"
  4. #import <MediaPlayer/MPMediaPickerController.h>
  5. #import <AVFoundation/AVFoundation.h>
  6. #import "UGCKit_UIViewAdditions.h"
  7. #import "UGCKitProgressHUD.h"
  8. #import "UGCKitVideoCutView.h"
  9. #import "UGCKitPlayerView.h"
  10. #import "UGCKitPhotoTransitionToolbar.h"
  11. #import "UGCKitColorMacro.h"
  12. #import "UGCKitSmallButton.h"
  13. #import "UGCKitMem.h"
  14. #import "UGCKitTheme.h"
  15. #import "UGCKitReporterInternal.h"
  16. #import "UGCKitSmallButton.h"
  17. typedef NS_ENUM(NSInteger,VideoType)
  18. {
  19. VideoType_Video,
  20. VideoType_Picture,
  21. };
  22. @interface UGCKitCutViewController ()<TXVideoGenerateListener,VideoPreviewDelegate, VideoCutViewDelegate,TransitionViewDelegate>
  23. @property(nonatomic,strong) TXVideoEditer *ugcEdit;
  24. @property(nonatomic,strong) UGCKitPlayerView *videoPreview;
  25. @property CGFloat duration;
  26. @end
  27. @implementation UGCKitCutViewController
  28. {
  29. UGCKitTheme *_theme;
  30. UGCKitMedia *_media;
  31. NSMutableArray *_cutPathList;
  32. NSString *_videoOutputPath;
  33. CGFloat _leftTime;
  34. CGFloat _rightTime;
  35. UILabel* _generationTitleLabel;
  36. UIView* _generationView;
  37. UIProgressView* _generateProgressView;
  38. UIButton* _generateCannelBtn;
  39. UIColor *_barTintColor;
  40. NSString* _filePath;
  41. unsigned long long _fileSize;
  42. BOOL _navigationBarHidden;
  43. BOOL _hasQuickGenerate;
  44. BOOL _hasNomalGenerate;
  45. UGCKitVideoCutView* _videoCutView;
  46. UGCKitPhotoTransitionToolbar* _photoTransitionToolbar;
  47. UGCKitRangeContentConfig *_config;
  48. int _renderRotation;
  49. CGFloat bottomToolbarHeight;
  50. CGFloat bottomInset;
  51. }
  52. - (instancetype)initWithMedia:(UGCKitMedia *)media theme:(UGCKitTheme *)theme;
  53. {
  54. if (self = [super init]) {
  55. _theme = theme ?: [UGCKitTheme sharedTheme];
  56. _media = media;
  57. _cutPathList = [NSMutableArray array];
  58. _videoOutputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"outputCut.mp4"];
  59. _config = [[UGCKitRangeContentConfig alloc] initWithTheme:_theme];
  60. _config.pinWidth = PIN_WIDTH;
  61. _config.thumbHeight = 50;
  62. _config.borderHeight = BORDER_HEIGHT;
  63. _config.imageCount = 15;
  64. }
  65. return self;
  66. }
  67. - (void)viewWillAppear:(BOOL)animated
  68. {
  69. [super viewWillAppear:animated];
  70. _navigationBarHidden = self.navigationController.navigationBar.hidden;
  71. self.navigationController.navigationBar.hidden = YES;
  72. self.navigationController.interactivePopGestureRecognizer.enabled = NO;
  73. }
  74. - (void)viewWillDisappear:(BOOL)animated
  75. {
  76. [super viewWillDisappear:animated];
  77. self.navigationController.navigationBar.hidden = _navigationBarHidden;
  78. }
  79. - (void)viewDidDisappear:(BOOL)animated
  80. {
  81. [super viewDidDisappear:animated];
  82. }
  83. - (void)viewDidAppear:(BOOL)animated
  84. {
  85. [super viewDidAppear:animated];
  86. [_videoPreview playVideo];
  87. }
  88. - (void)dealloc
  89. {
  90. [_videoPreview removeNotification];
  91. _videoPreview = nil;
  92. }
  93. - (void)viewDidLoad {
  94. [super viewDidLoad];
  95. bottomToolbarHeight = 52;
  96. bottomInset = 10;
  97. _videoPreview = [[UGCKitPlayerView alloc] initWithFrame:CGRectMake(0, 0, self.view.ugckit_width, self.view.ugckit_height) coverImage:nil theme:_theme];
  98. _videoPreview.delegate = self;
  99. [self.view addSubview:_videoPreview];
  100. CGFloat top = [UIApplication sharedApplication].statusBarFrame.size.height;
  101. if (@available(iOS 11, *)) {
  102. bottomInset += [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
  103. }
  104. if (kScaleY < 1) {
  105. bottomToolbarHeight = round(bottomToolbarHeight * kScaleY);
  106. }
  107. UILabel *barTitleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0 , 100, 44)];
  108. barTitleLabel.backgroundColor = [UIColor clearColor];
  109. barTitleLabel.font = [UIFont boldSystemFontOfSize:17];
  110. barTitleLabel.textColor = [UIColor whiteColor];
  111. barTitleLabel.textAlignment = NSTextAlignmentCenter;
  112. barTitleLabel.text = [_theme localizedString:@"UGCKit.Edit.VideoEdit"];
  113. self.navigationItem.titleView = barTitleLabel;
  114. self.view.backgroundColor = UIColor.blackColor;
  115. UIButton *goBackButton = [UGCKitSmallButton buttonWithType:UIButtonTypeCustom];
  116. [goBackButton setImage:_theme.backIcon forState:UIControlStateNormal];
  117. [goBackButton addTarget:self action:@selector(onBtnPopClicked) forControlEvents:UIControlEventTouchUpInside];
  118. goBackButton.frame = CGRectMake(15, 5 + top, 14 , 23);
  119. [self.view addSubview:goBackButton];
  120. CGFloat btnNextWidth = 70;
  121. CGFloat btnNextHeight = 30;
  122. UIButton *btnNext = [UIButton buttonWithType:UIButtonTypeCustom];
  123. btnNext.frame = CGRectMake(CGRectGetWidth(self.view.bounds) - 15 - btnNextWidth, 5 + top, btnNextWidth, btnNextHeight);
  124. [btnNext setTitle:[_theme localizedString:@"UGCKit.Common.Next"] forState:UIControlStateNormal];
  125. btnNext.titleLabel.font = [UIFont systemFontOfSize:14];
  126. [btnNext setBackgroundImage:_theme.nextIcon forState:UIControlStateNormal];
  127. [btnNext addTarget:self action:@selector(onBtnNextClicked) forControlEvents:UIControlEventTouchUpInside];
  128. [self.view addSubview:btnNext];
  129. // CGFloat heightDist = 52 * kScaleY;
  130. // _videoCutView = [[VideoCutView alloc] initWithFrame:CGRectMake(0, self.view.height - heightDist - 20 * kScaleY, self.view.width,heightDist) videoPath:_videoPath videoAssert:_videoAsset config:config];
  131. // _videoCutView.delegate = self;
  132. // [self.view addSubview:_videoCutView];
  133. TXPreviewParam *param = [[TXPreviewParam alloc] init];
  134. param.videoView = _videoPreview.renderView;
  135. param.renderMode = PREVIEW_RENDER_MODE_FILL_EDGE;
  136. _ugcEdit = [[TXVideoEditer alloc] initWithPreview:param];
  137. _ugcEdit.generateDelegate = self;
  138. _ugcEdit.previewDelegate = _videoPreview;
  139. CGPoint rotateButtonCenter = CGPointZero;
  140. //video
  141. if (_media.isVideo) {
  142. // if (_videoAsset != nil) {
  143. AVAsset *asset = _media.videoAsset;
  144. [_ugcEdit setVideoAsset:asset];
  145. [self initVideoCutView];
  146. TXVideoInfo *videoMsg = [TXVideoInfoReader getVideoInfoWithAsset:asset];
  147. _fileSize = videoMsg.fileSize;
  148. _duration = videoMsg.duration;
  149. _rightTime = _duration;
  150. _renderRotation = videoMsg.angle;
  151. rotateButtonCenter = CGPointMake(_videoCutView.ugckit_right - 20, _videoCutView.ugckit_top - 20);
  152. } else {
  153. //image
  154. // if (_imageList != nil) {
  155. CGRect frame = CGRectMake(0, self.view.ugckit_height - bottomInset - bottomToolbarHeight, self.view.ugckit_width, bottomToolbarHeight);
  156. _photoTransitionToolbar = [[UGCKitPhotoTransitionToolbar alloc] initWithFrame:frame
  157. theme:_theme];
  158. _photoTransitionToolbar.delegate = self;
  159. [self.view addSubview:_photoTransitionToolbar];
  160. _photoTransitionToolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
  161. [_ugcEdit setPictureList:_media.images fps:30];
  162. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  163. [self onVideoTransitionLefRightSlipping];
  164. });
  165. rotateButtonCenter = CGPointMake(_photoTransitionToolbar.ugckit_right - 20 - bottomToolbarHeight, _photoTransitionToolbar.ugckit_top - bottomToolbarHeight - 10 - 20);
  166. }
  167. if (_media.isVideo) {
  168. // rotation button
  169. UIButton *rotateButton = [UGCKitSmallButton buttonWithType:UIButtonTypeCustom];
  170. [rotateButton setImage:_theme.editRotateIcon forState:UIControlStateNormal];
  171. [rotateButton sizeToFit];
  172. rotateButton.center = rotateButtonCenter;
  173. [rotateButton addTarget:self action:@selector(onRotatePreview:) forControlEvents:UIControlEventTouchUpInside];
  174. [self.view addSubview:rotateButton];
  175. }
  176. }
  177. - (UIView*)generatingView
  178. {
  179. /*用作生成时的提示浮层*/
  180. if (!_generationView) {
  181. _generationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.ugckit_width, self.view.ugckit_height + 64)];
  182. _generationView.backgroundColor = UIColor.blackColor;
  183. _generationView.alpha = 0.9f;
  184. _generateProgressView = [UIProgressView new];
  185. _generateProgressView.center = CGPointMake(_generationView.ugckit_width / 2, _generationView.ugckit_height / 2);
  186. _generateProgressView.bounds = CGRectMake(0, 0, 225, 20);
  187. _generateProgressView.progressTintColor = _theme.progressColor;
  188. [_generateProgressView setTrackImage:_theme.progressTrackImage];
  189. //_generateProgressView.trackTintColor = UIColor.whiteColor;
  190. //_generateProgressView.transform = CGAffineTransformMakeScale(1.0, 2.0);
  191. _generationTitleLabel = [UILabel new];
  192. _generationTitleLabel.font = [UIFont systemFontOfSize:14];
  193. _generationTitleLabel.text = [_theme localizedString:@"UGCKit.Edit.VideoGenerating"];
  194. _generationTitleLabel.textColor = UIColor.whiteColor;
  195. _generationTitleLabel.textAlignment = NSTextAlignmentCenter;
  196. _generationTitleLabel.frame = CGRectMake(0, _generateProgressView.ugckit_y - 34, _generationView.ugckit_width, 14);
  197. _generateCannelBtn = [UIButton new];
  198. [_generateCannelBtn setImage:_theme.closeIcon forState:UIControlStateNormal];
  199. _generateCannelBtn.frame = CGRectMake(_generateProgressView.ugckit_right + 15, _generationTitleLabel.ugckit_bottom + 10, 20, 20);
  200. [_generateCannelBtn addTarget:self action:@selector(onCancelBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
  201. [_generationView addSubview:_generationTitleLabel];
  202. [_generationView addSubview:_generateProgressView];
  203. [_generationView addSubview:_generateCannelBtn];
  204. }
  205. _generateProgressView.progress = 0.f;
  206. [[[UIApplication sharedApplication] delegate].window addSubview:_generationView];
  207. return _generationView;
  208. }
  209. - (void)initVideoCutView
  210. {
  211. if (_media.isVideo) {
  212. CGRect frame = CGRectMake(0, self.view.ugckit_height - bottomToolbarHeight - bottomInset, self.view.ugckit_width,bottomToolbarHeight);
  213. if(_videoCutView) [_videoCutView removeFromSuperview];
  214. _videoCutView = [[UGCKitVideoCutView alloc] initWithFrame:frame videoPath:nil videoAsset:_media.videoAsset config:_config];
  215. [self.view addSubview:_videoCutView];
  216. }else{
  217. CGRect frame = CGRectMake(0, self.view.ugckit_height - bottomToolbarHeight - bottomInset - 10 - bottomToolbarHeight, self.view.ugckit_width,bottomToolbarHeight);
  218. if (_videoCutView) {
  219. [_videoCutView updateFrame:_duration];
  220. }else{
  221. [_videoCutView removeFromSuperview];
  222. _videoCutView = [[UGCKitVideoCutView alloc] initWithFrame:frame pictureList:_media.images duration:_duration fps:30 config:_config];
  223. [self.view addSubview:_videoCutView];
  224. }
  225. }
  226. _videoCutView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
  227. _videoCutView.delegate = self;
  228. [_videoCutView setCenterPanHidden:YES];
  229. }
  230. - (void)pause
  231. {
  232. [_ugcEdit pausePlay];
  233. [_videoPreview setPlayBtn:NO];
  234. }
  235. #pragma makr - Actions
  236. - (void)onRotatePreview:(id)sender
  237. {
  238. _renderRotation += 90;
  239. [_ugcEdit setRenderRotation:_renderRotation];
  240. }
  241. - (void)onBtnPopClicked
  242. {
  243. [self pause];
  244. [self _goBack];
  245. }
  246. - (void)_goBack {
  247. UINavigationController *nav = self.navigationController;
  248. if (nav.presentedViewController) {
  249. [nav.presentedViewController dismissViewControllerAnimated:YES completion:nil];
  250. } else {
  251. [nav popToRootViewControllerAnimated:YES];
  252. }
  253. }
  254. -(void)onBtnNextClicked
  255. {
  256. [self pause];
  257. [_videoPreview setPlayBtn:NO];
  258. if (_media.isVideo) {
  259. TXVideoInfo *videoInfo = [TXVideoInfoReader getVideoInfoWithAsset:_media.videoAsset];
  260. BOOL largerThan1080p = videoInfo.width * videoInfo.height > 1920*1080;
  261. BOOL hasBeenRotated = _renderRotation % 360 != 0;
  262. if (_leftTime == 0 && _rightTime == _duration && !largerThan1080p && !hasBeenRotated) {
  263. //视频如果没发生剪裁,也没有旋转,这里不用走编辑逻辑,减少画面质量损失
  264. if (self.completion) {
  265. UGCKitResult *result = [[UGCKitResult alloc] init];
  266. result.media = _media;
  267. self.completion(result, _renderRotation);
  268. }
  269. }else{
  270. _generationView = [self generatingView];
  271. _generationView.hidden = NO;
  272. [_ugcEdit setCutFromTime:_leftTime toTime:_rightTime];
  273. if (largerThan1080p || _renderRotation % 360 != 0) {
  274. [_ugcEdit generateVideo:VIDEO_COMPRESSED_720P videoOutputPath:_videoOutputPath];
  275. } else {
  276. //使用快速剪切,速度快
  277. _hasQuickGenerate = YES;
  278. [_ugcEdit quickGenerateVideo:VIDEO_COMPRESSED_720P videoOutputPath:_videoOutputPath];
  279. }
  280. }
  281. }else{
  282. //图片编辑只能走正常生成逻辑,这里使用高码率,保留更多图片细节
  283. _generationView = [self generatingView];
  284. _generationView.hidden = NO;
  285. _hasNomalGenerate = YES;
  286. [_ugcEdit setVideoBitrate:10000];
  287. [_ugcEdit setCutFromTime:_leftTime toTime:_rightTime];
  288. [_ugcEdit quickGenerateVideo:VIDEO_COMPRESSED_720P videoOutputPath:_videoOutputPath];
  289. }
  290. }
  291. - (void)onCancelBtnClicked:(UIButton*)sender
  292. {
  293. _generationView.hidden = YES;
  294. [_ugcEdit cancelGenerate];
  295. }
  296. #pragma mark TransitionViewDelegate
  297. - (void)_onVideoTransition:(TXTransitionType)type {
  298. __weak __typeof(self) weakSelf = self;
  299. WEAKIFY(self);
  300. [_ugcEdit setPictureTransition:type duration:^(CGFloat duration) {
  301. STRONGIFY_OR_RETURN(self);
  302. self->_duration = duration;
  303. self->_rightTime = duration;
  304. [self initVideoCutView];
  305. [self.ugcEdit startPlayFromTime:0 toTime:weakSelf.duration];
  306. [self.videoPreview setPlayBtn:YES];
  307. }];
  308. }
  309. - (void)onVideoTransitionLefRightSlipping
  310. {
  311. [self _onVideoTransition:TXTransitionType_LefRightSlipping];
  312. }
  313. - (void)onVideoTransitionUpDownSlipping
  314. {
  315. [self _onVideoTransition:TXTransitionType_UpDownSlipping];
  316. }
  317. - (void)onVideoTransitionEnlarge
  318. {
  319. [self _onVideoTransition:TXTransitionType_Enlarge];
  320. }
  321. - (void)onVideoTransitionNarrow
  322. {
  323. [self _onVideoTransition:TXTransitionType_Narrow];
  324. }
  325. - (void)onVideoTransitionRotationalScaling
  326. {
  327. [self _onVideoTransition:TXTransitionType_RotationalScaling];
  328. }
  329. - (void)onVideoTransitionFadeinFadeout
  330. {
  331. [self _onVideoTransition:TXTransitionType_FadeinFadeout];
  332. }
  333. #pragma mark TXVideoGenerateListener
  334. -(void) onGenerateProgress:(float)progress
  335. {
  336. _generateProgressView.progress = progress;
  337. }
  338. -(void) onGenerateComplete:(TXGenerateResult *)result
  339. {
  340. _generationView.hidden = YES;
  341. if (result.retCode == 0) {
  342. if (_media.isVideo) {
  343. NSFileManager *fm = [[NSFileManager alloc] init];
  344. NSString *rename = [_videoOutputPath stringByAppendingString:@"-tmp.mp4"];
  345. [fm removeItemAtPath:rename error:nil];
  346. [fm moveItemAtPath:_videoOutputPath toPath:rename error:nil];
  347. UGCKitResult *result = [[UGCKitResult alloc]init];
  348. result.media = [UGCKitMedia mediaWithVideoPath:rename];
  349. if (self.completion) {
  350. self.completion(result, 0);
  351. }
  352. } else {
  353. UGCKitResult *result = [[UGCKitResult alloc]init];
  354. result.media = [UGCKitMedia mediaWithVideoPath:_videoOutputPath];
  355. if (self.completion) {
  356. self.completion(result, 0);
  357. }
  358. }
  359. }else{
  360. //系统剪切如果失败,这里使用SDK正常剪切,设置高码率,保留图像更多的细节
  361. if (_hasQuickGenerate && !_hasNomalGenerate) {
  362. _generationView = [self generatingView];
  363. _generationView.hidden = NO;
  364. [_ugcEdit cancelGenerate];
  365. [_ugcEdit setVideoBitrate:10000];
  366. [_ugcEdit setCutFromTime:_leftTime toTime:_rightTime];
  367. [_ugcEdit generateVideo:VIDEO_COMPRESSED_720P videoOutputPath:_videoOutputPath];
  368. _hasNomalGenerate = YES;
  369. }else{
  370. UGCKitResult *r = [[UGCKitResult alloc] init];
  371. r.code = result.retCode;
  372. NSString *msg = [NSString stringWithFormat:[_theme localizedString:@"UGCKit.Common.HintErrorCodeMessage"],(long)result.retCode,result.descMsg];
  373. r.info = @{NSLocalizedDescriptionKey: msg};
  374. if (self.completion) {
  375. self.completion(r, _renderRotation);
  376. }
  377. // UIAlertController *controller = [UIAlertController alertControllerWithTitle:[_theme localizedString:@"UGCKit.Edit.HintVideoGeneratingFailed"]
  378. // message:msg
  379. // preferredStyle:UIAlertControllerStyleAlert];
  380. // [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.GotIt"] style:UIAlertActionStyleCancel handler:nil]];
  381. // [self presentViewController:controller animated:YES completion:nil];
  382. }
  383. }
  384. if (_media.isVideo) {
  385. [UGCKitReporter report:UGCKitReportItem_videoedit userName:nil code:result.retCode msg:result.descMsg];
  386. }else{
  387. [UGCKitReporter report:UGCKitReportItem_pictureedit userName:nil code:result.retCode msg:result.descMsg];
  388. }
  389. }
  390. #pragma mark UGCKitPlayerViewDelegate
  391. - (void)onVideoPlay
  392. {
  393. CGFloat currentPos = _videoCutView.videoRangeSlider.currentPos;
  394. if (currentPos < _leftTime || currentPos > _rightTime)
  395. currentPos = _leftTime;
  396. [_ugcEdit startPlayFromTime:currentPos toTime:_videoCutView.videoRangeSlider.rightPos];
  397. }
  398. - (void)onVideoPause
  399. {
  400. [_ugcEdit pausePlay];
  401. }
  402. - (void)onVideoResume
  403. {
  404. [self onVideoPlay];
  405. }
  406. - (void)onVideoPlayProgress:(CGFloat)time
  407. {
  408. [_videoCutView setPlayTime:time];
  409. }
  410. - (void)onVideoPlayFinished
  411. {
  412. [_ugcEdit startPlayFromTime:_leftTime toTime:_rightTime];
  413. }
  414. - (void)onVideoEnterBackground
  415. {
  416. if (_generationView && !_generationView.hidden) {
  417. [_ugcEdit pauseGenerate];
  418. }else{
  419. [UGCKitProgressHUD hideHUDForView:self.view animated:YES];
  420. [_ugcEdit pausePlay];
  421. [_videoPreview setPlayBtn:NO];
  422. }
  423. }
  424. - (void)onVideoWillEnterForeground
  425. {
  426. if (_generationView && !_generationView.hidden) {
  427. [_ugcEdit resumeGenerate];
  428. }
  429. }
  430. #pragma mark - VideoCutViewDelegate
  431. - (void)onVideoRangeLeftChanged:(UGCKitVideoRangeSlider *)sender
  432. {
  433. //[_ugcEdit pausePlay];
  434. [_videoPreview setPlayBtn:NO];
  435. [_ugcEdit previewAtTime:sender.leftPos];
  436. }
  437. - (void)onVideoRangeRightChanged:(UGCKitVideoRangeSlider *)sender
  438. {
  439. [_videoPreview setPlayBtn:NO];
  440. [_ugcEdit previewAtTime:sender.rightPos];
  441. }
  442. - (void)onVideoRangeLeftChangeEnded:(UGCKitVideoRangeSlider *)sender
  443. {
  444. _leftTime = sender.leftPos;
  445. _rightTime = sender.rightPos;
  446. [_ugcEdit startPlayFromTime:sender.leftPos toTime:sender.rightPos];
  447. [_videoPreview setPlayBtn:YES];
  448. }
  449. - (void)onVideoRangeRightChangeEnded:(UGCKitVideoRangeSlider *)sender
  450. {
  451. _leftTime = sender.leftPos;
  452. _rightTime = sender.rightPos;
  453. [_ugcEdit startPlayFromTime:sender.leftPos toTime:sender.rightPos];
  454. [_videoPreview setPlayBtn:YES];
  455. }
  456. - (void)onVideoSeekChange:(UGCKitVideoRangeSlider *)sender seekToPos:(CGFloat)pos
  457. {
  458. [_ugcEdit previewAtTime:pos];
  459. [_videoPreview setPlayBtn:NO];
  460. }
  461. @end