UGCKitEditViewController.m 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863
  1. // Copyright (c) 2019 Tencent. All rights reserved.
  2. #import <Foundation/Foundation.h>
  3. #import <MediaPlayer/MPMediaPickerController.h>
  4. #import <Photos/Photos.h>
  5. #import "UGCKitEditViewController.h"
  6. #import "UGCKitBGMListViewController.h"
  7. #import "SDKHeader.h"
  8. #import "UGCKitPlayerView.h"
  9. #import "UGCKitVideoRangeSlider.h"
  10. #import "UGCKitVideoRangeConst.h"
  11. #import "UGCKitVideoRecordMusicView.h"
  12. #import "UGCKit_UIViewAdditions.h"
  13. #import "UGCKitColorMacro.h"
  14. #import "UGCKitProgressHUD.h"
  15. #import "UGCKitEditBottomMenu.h"
  16. #import "UGCKitVideoCutView.h"
  17. #import "UGCKitPasterAddView.h"
  18. #import "UGCKitEffectSelectView.h"
  19. #import "UGCKitVideoPasterView.h"
  20. #import "UGCKitVideoTextFiled.h"
  21. #import "UGCKitBGMHelper.h"
  22. #import "UGCKitVideoInfo.h"
  23. #import "UGCKitVideoEffectColorPalette.h"
  24. #import "UGCKitTheme.h"
  25. #import "UGCKitResult.h"
  26. #import "UGCKitConstants.h"
  27. #import "UGCKitReporterInternal.h"
  28. #import "UGCKitVideoEffectManager.h"
  29. #import "UGCKitLocalization.h"
  30. #import "SDKHeader.h"
  31. #import "UGCKitMem.h"
  32. typedef NS_ENUM(NSInteger,TimeType)
  33. {
  34. TimeType_Clear,
  35. TimeType_Back,
  36. TimeType_Repeat,
  37. TimeType_Speed,
  38. };
  39. typedef NS_ENUM(NSInteger,EffectSelectType)
  40. {
  41. EffectSelectType_Effect,
  42. EffectSelectType_Time,
  43. EffectSelectType_Filter,
  44. EffectSelectType_Paster,
  45. EffectSelectType_Text,
  46. };
  47. @interface UGCKitEditViewController ()<TXVideoGenerateListener,VideoPreviewDelegate, VideoCutViewDelegate,UGCKitEffectSelectViewDelegate, UGCKitPasterAddViewDelegate, UGCKitVideoPasterViewDelegate ,VideoTextFieldDelegate ,TCBGMControllerListener,UGCKitVideoRecordMusicViewDelegate,UIActionSheetDelegate, UITabBarDelegate , UIPickerViewDelegate ,UIPickerViewDelegate ,UIAlertViewDelegate>
  48. @end
  49. @implementation UGCKitEditViewController
  50. {
  51. /// 编辑的视频
  52. AVAsset *_videoAsset;
  53. /// 编辑器配置
  54. UGCKitEditConfig *_config;
  55. /// 编辑器主题
  56. UGCKitTheme * _theme;
  57. UGCKitBGMListViewController *_bgmListVC;
  58. TXVideoEditer* _ugcEdit; //sdk编辑器
  59. UGCKitPlayerView* _videoPreview; //视频预览
  60. //特效View
  61. UIView* _effectView;
  62. //cover view
  63. UIImageView* _coverImageView;
  64. //背景音
  65. UGCKitVideoRecordMusicView *_musicView;
  66. //特效确定btn
  67. UIButton * _effectConfirmBtn;
  68. UIButton * _generateCannelBtn;
  69. //生成时的进度浮层
  70. UIView* _generationView;
  71. UIProgressView* _generateProgressView;
  72. UILabel* _generationTitleLabel;
  73. UILabel* _timeLabel;
  74. UIButton* _deleteBtn;
  75. UIButton* _playBtn;
  76. UGCKitEditBottomMenu* _bottomMenu; //底部栏
  77. UGCKitVideoCutView* _videoCutView; //裁剪
  78. UGCKitPasterAddView* _pasterAddView; //贴图
  79. UGCKitEffectSelectView* _effectSelectView; //动效选择
  80. EffectSelectType _effectSelectType;
  81. TimeType _timeType;
  82. NSMutableArray <UGCKitEffectInfo *> *_pasterEffectArray;
  83. NSMutableArray <UGCKitEffectInfo *> *_textEffectArray;
  84. NSMutableArray <UGCKitVideoPasterInfo *>* _videoPasterInfoList;
  85. NSMutableArray <UGCKitVideoTextInfo *>* _videoTextInfoList;
  86. NSMutableArray *_cutPathList;
  87. //裁剪时间
  88. CGFloat _duration;
  89. CGFloat _playTime;
  90. CGFloat _BGMDuration;
  91. CGFloat _BGMVolume;
  92. CGFloat _videoVolume;
  93. NSInteger _effectSelectIndex;
  94. NSInteger _effectType;
  95. NSObject* _BGMPath;
  96. BOOL _isReverse;
  97. BOOL _isSeek;
  98. BOOL _isPlay;
  99. BOOL _navigationBarHidden;
  100. dispatch_queue_t _imageLoadingQueue;
  101. NSArray<UGCKitEffectInfo*> *_effectList;
  102. // 选中的滤镜与速度,用于恢复状态
  103. NSInteger _filterIndex;
  104. NSInteger _timeIndex;
  105. BOOL _isShowingEffectView;
  106. BOOL _isHidingEffectView;
  107. }
  108. - (instancetype)initWithMedia:(UGCKitMedia *)asset config:(UGCKitEditConfig *)config theme:(UGCKitTheme *)theme
  109. {
  110. self = [super initWithNibName:nil bundle:nil];
  111. if (self) {
  112. _videoAsset = asset.videoAsset;
  113. NSAssert(_videoAsset, @"asset is nil");
  114. _config = config ?: [[UGCKitEditConfig alloc] init];
  115. _theme = theme ?: [UGCKitTheme sharedTheme];
  116. _generateMode = _config.generateMode;
  117. _effectType = -1;
  118. _cutPathList = [NSMutableArray array];
  119. _videoOutputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"outputCut.mp4"];
  120. _pasterEffectArray = [NSMutableArray array];
  121. [_pasterEffectArray addObject:({
  122. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  123. v.name = [_theme localizedString:@"UGCKit.Common.AddNew"];
  124. v.icon = _theme.editPanelAddPasterIcon;
  125. v;
  126. })];
  127. _textEffectArray = [NSMutableArray array];
  128. [_textEffectArray addObject:({
  129. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  130. v.name = [_theme localizedString:@"UGCKit.Common.AddNew"];
  131. v.icon = _theme.editPanelAddPasterIcon;
  132. v;
  133. })];
  134. _videoPasterInfoList = [NSMutableArray array];
  135. _videoTextInfoList = [NSMutableArray array];
  136. _BGMVolume = 1.0;
  137. _videoVolume = 1.0;
  138. _imageLoadingQueue = dispatch_queue_create("UGCKitVideoEditImageLoading", DISPATCH_QUEUE_CONCURRENT);
  139. }
  140. return self;
  141. }
  142. - (BOOL)prefersStatusBarHidden {
  143. if (@available(iOS 11, *)) {
  144. if ([UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom > 0) {
  145. return NO;
  146. }
  147. }
  148. return YES;
  149. }
  150. - (void)viewWillAppear:(BOOL)animated
  151. {
  152. [super viewWillAppear:animated];
  153. _navigationBarHidden = self.navigationController.navigationBar.hidden;
  154. self.navigationController.navigationBar.hidden = YES;
  155. if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]){
  156. self.navigationController.interactivePopGestureRecognizer.enabled = NO;
  157. }
  158. }
  159. - (void)viewWillDisappear:(BOOL)animated
  160. {
  161. [super viewWillDisappear:animated];
  162. self.navigationController.navigationBar.hidden = _navigationBarHidden;
  163. [_videoCutView stopGetImageList];
  164. }
  165. - (void)viewDidAppear:(BOOL)animated
  166. {
  167. [super viewDidAppear:animated];
  168. if (!_videoPreview.isPlaying) {
  169. [_videoPreview playVideo];
  170. }
  171. }
  172. - (void)onVideoEnterBackground
  173. {
  174. if (_generationView && !_generationView.hidden) {
  175. [_ugcEdit pauseGenerate];
  176. }else{
  177. [UGCKitProgressHUD hideHUDForView:self.view animated:YES];
  178. [self pausePlay];
  179. }
  180. }
  181. - (void)onVideoWillEnterForeground
  182. {
  183. if (_generationView && !_generationView.hidden) {
  184. [_ugcEdit resumeGenerate];
  185. }else{
  186. [_ugcEdit resumePlay];
  187. [self setPlayBtn:YES];
  188. _isPlay = YES;
  189. }
  190. }
  191. - (void)viewDidLoad {
  192. [super viewDidLoad];
  193. UGCKitTheme *theme = _theme;
  194. __weak __typeof(self) wself = self;
  195. dispatch_async(_imageLoadingQueue, ^{
  196. CFTimeInterval start = CFAbsoluteTimeGetCurrent();
  197. __strong __typeof(wself) self = wself;
  198. if (self) {
  199. self->_effectList = [UGCKitVideoEffectManager effectInfosWithTheme:theme];
  200. }
  201. CFTimeInterval end = CFAbsoluteTimeGetCurrent();
  202. NSLog(@"effect load time: %g", end - start);
  203. });
  204. self.view.backgroundColor = UIColor.blackColor;
  205. _videoPreview = [[UGCKitPlayerView alloc] initWithFrame:self.view.bounds coverImage:nil theme:_theme];
  206. _videoPreview.delegate = self;
  207. [_videoPreview setPlayBtnHidden:YES];
  208. [self.view addSubview:_videoPreview];
  209. // 点隐藏工具h面板
  210. UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapToHideBottomPanel:)];
  211. [_videoPreview addGestureRecognizer:singleTap];
  212. CGFloat offset = 0;
  213. if (@available(iOS 11, *)) {
  214. offset = [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
  215. }
  216. // 配置底部菜单
  217. UGCKitEditBottomMenu *menu = [[UGCKitEditBottomMenu alloc] initWithFrame:CGRectMake(0, self.view.ugckit_height - 62 - offset, self.view.ugckit_width, 62)
  218. items:nil];
  219. menu.textColor = _theme.editPanelTextColor ?: [UIColor whiteColor];
  220. // menu.backgroundColor = _theme.editPanelBackgroundColor;
  221. [menu addItemWithTitle:[_theme localizedString:@"UGCKit.Edit.Tab.Music"]
  222. icon:_theme.editPanelMusicIcon
  223. highlightedIcon:_theme.editPanelMusicHighlightedIcon
  224. action:^{
  225. [wself onMusicBtnClicked];
  226. }];
  227. [menu addItemWithTitle:[_theme localizedString:@"UGCKit.Edit.Tab.Effect"]
  228. icon:_theme.editPanelEffectIcon
  229. highlightedIcon:_theme.editPanelEffectHighlightedIcon
  230. action:^{
  231. [wself onEffectBtnClicked];
  232. }];
  233. [menu addItemWithTitle:[_theme localizedString:@"UGCKit.Edit.Tab.Speed"]
  234. icon:_theme.editPanelSpeedIcon
  235. highlightedIcon:_theme.editPanelSpeedHighlightedIcon
  236. action:^{
  237. [wself onTimeBtnClicked];
  238. }];
  239. [menu addItemWithTitle:[_theme localizedString:@"UGCKit.Edit.Tab.Filter"]
  240. icon:_theme.editPanelFilterIcon
  241. highlightedIcon:_theme.editPanelFilterHighlightedIcon
  242. action:^{
  243. [wself onFilterBtnClicked];
  244. }];
  245. [menu addItemWithTitle:[_theme localizedString:@"UGCKit.Edit.Tab.Paster"]
  246. icon:_theme.editPanelPasterIcon
  247. highlightedIcon:_theme.editPanelPasterHighlightedIcon
  248. action:^{
  249. [wself onPasterBtnClicked];
  250. }];
  251. [menu addItemWithTitle:[_theme localizedString:@"UGCKit.Edit.Tab.Subtitle"]
  252. icon:_theme.editPanelSubtitleIcon
  253. highlightedIcon:_theme.editPanelSubtitleHighlightedIcon
  254. action:^{
  255. [wself onTextBtnClicked];
  256. }];
  257. _bottomMenu = menu;
  258. [self.view addSubview:_bottomMenu];
  259. CGFloat top = [UIApplication sharedApplication].statusBarFrame.size.height + 5;
  260. // 特效取消及后退按钮
  261. UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  262. backBtn.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin;
  263. [backBtn setImage:_theme.backIcon forState:UIControlStateNormal];
  264. backBtn.frame = CGRectMake(10, top, 50, 44);
  265. [backBtn addTarget:self action:@selector(onTapCloseButton:) forControlEvents:UIControlEventTouchUpInside];
  266. [self.view addSubview:backBtn];
  267. CGFloat btnConfirmWidth = 70;
  268. CGFloat btnConfirmHeight = 30;
  269. _effectConfirmBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  270. [_effectConfirmBtn setTitle:[_theme localizedString:@"UGCKit.Common.Done"] forState:UIControlStateNormal];
  271. _effectConfirmBtn.titleLabel.font = [UIFont systemFontOfSize:14];
  272. [_effectConfirmBtn setBackgroundImage:_theme.nextIcon forState:UIControlStateNormal];
  273. _effectConfirmBtn.frame = CGRectMake(CGRectGetWidth(self.view.bounds) - 15 - btnConfirmWidth, CGRectGetMidY(backBtn.frame)-btnConfirmHeight/2,
  274. btnConfirmWidth, btnConfirmHeight);
  275. _effectConfirmBtn.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin;;
  276. [_effectConfirmBtn addTarget:self action:@selector(goFinish) forControlEvents:UIControlEventTouchUpInside];
  277. [self.view addSubview:_effectConfirmBtn];
  278. _coverImageView = [[UIImageView alloc] initWithFrame:_videoPreview.frame];
  279. _coverImageView.hidden = YES;
  280. _coverImageView.contentMode = UIViewContentModeScaleAspectFit;
  281. [self.view addSubview:_coverImageView];
  282. // 特效容器
  283. _effectView= [[UIView alloc] initWithFrame:CGRectMake(0, self.view.ugckit_height, self.view.ugckit_width, 205 * kScaleY)];
  284. [self.view addSubview:_effectView];
  285. _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(15 * kScaleX, 0, 40, 54)];
  286. _timeLabel.textColor = _theme.titleColor;
  287. _timeLabel.text = LocalizationNotNeeded(@"00:00");
  288. _timeLabel.font = [UIFont systemFontOfSize:14];
  289. _timeLabel.textColor = _theme.titleColor;
  290. [_effectView addSubview:_timeLabel];
  291. _playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  292. [_playBtn setBackgroundImage:_theme.editPlayIcon forState:UIControlStateNormal];
  293. [_playBtn setBackgroundImage:_theme.editPlayHighlightedIcon forState:UIControlStateHighlighted];
  294. _playBtn.frame = CGRectMake(self.view.ugckit_width / 2 - 15, 10 * kScaleY, 30, 30);
  295. [_playBtn addTarget:self action:@selector(onPlayVideo) forControlEvents:UIControlEventTouchUpInside];
  296. [_effectView addSubview:_playBtn];
  297. _deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  298. [_deleteBtn setBackgroundImage:_theme.editPanelDeleteIcon forState:UIControlStateNormal];
  299. [_deleteBtn setBackgroundImage:_theme.editPanelDeleteHighlightedIcon forState:UIControlStateHighlighted];
  300. _deleteBtn.frame = CGRectMake(self.view.ugckit_width - 15 * kScaleX - 30, 10 * kScaleY, 30, 30);
  301. [_deleteBtn addTarget:self action:@selector(onDeleteEffect) forControlEvents:UIControlEventTouchUpInside];
  302. [_effectView addSubview:_deleteBtn];
  303. CGFloat cutViewHeight = 34 * kScaleY;
  304. UGCKitRangeContentConfig *config = [[UGCKitRangeContentConfig alloc] initWithTheme:_theme];
  305. config.pinWidth = PIN_WIDTH;
  306. config.thumbHeight = cutViewHeight;
  307. config.borderHeight = 0;
  308. config.imageCount = 20;
  309. _videoCutView = [[UGCKitVideoCutView alloc] initWithFrame:CGRectMake(0,_timeLabel.ugckit_bottom + 3, _effectView.ugckit_width,cutViewHeight) videoPath:nil videoAsset:_videoAsset config:config];
  310. _videoCutView.delegate = self;
  311. [_videoCutView setCenterPanHidden:YES];
  312. [_effectView addSubview:_videoCutView];
  313. UIImageView *flagView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.ugckit_width / 2 - 6, _timeLabel.ugckit_bottom, 12, 48)];
  314. flagView.image = _theme.editTimelineIndicatorIcon;
  315. [_effectView addSubview:flagView];
  316. _effectSelectView = [[UGCKitEffectSelectView alloc] initWithFrame:CGRectMake(0, _videoCutView.ugckit_bottom + 24 * kScaleY,_effectView.ugckit_width,70 * kScaleY)];
  317. _effectSelectView.delegate = self;
  318. _effectSelectView.hidden = NO;
  319. [_effectView addSubview:_effectSelectView];
  320. _pasterAddView = [[UGCKitPasterAddView alloc] initWithFrame:CGRectMake(0,self.view.ugckit_height - 205 * kScaleY, self.view.ugckit_width,205 * kScaleY) theme:_theme];
  321. _pasterAddView.delegate = self;
  322. _pasterAddView.hidden = YES;
  323. [self.view addSubview:_pasterAddView];
  324. _musicView = [[UGCKitVideoRecordMusicView alloc] initWithFrame:CGRectMake(0, self.view.ugckit_bottom - 268 * kScaleY, self.view.ugckit_width, 268 * kScaleY) needEffect:NO theme:_theme];
  325. _musicView.delegate = self;
  326. _musicView.hidden = YES;
  327. [self.view addSubview:_musicView];
  328. _bgmListVC = [[UGCKitBGMListViewController alloc] initWithTheme:_theme];
  329. [_bgmListVC setBGMControllerListener:self];
  330. [self initVideoEditor];
  331. }
  332. - (void)initVideoEditor
  333. {
  334. TXVideoInfo *videoMsg = [TXVideoInfoReader getVideoInfoWithAsset:_videoAsset];
  335. _duration = videoMsg.duration;
  336. TXPreviewParam *param = [[TXPreviewParam alloc] init];
  337. param.videoView = _videoPreview.renderView;
  338. param.renderMode = PREVIEW_RENDER_MODE_FILL_EDGE;
  339. _ugcEdit = [[TXVideoEditer alloc] initWithPreview:param];
  340. _ugcEdit.generateDelegate = self;
  341. _ugcEdit.previewDelegate = _videoPreview;
  342. [_ugcEdit setVideoAsset:_videoAsset];
  343. [_ugcEdit setRenderRotation:(int)_config.rotation * 90];
  344. // UIImage *waterimage = [UIImage imageNamed:@"watermark"];
  345. // [_ugcEdit setWaterMark:waterimage normalizationFrame:CGRectMake(0.01, 0.01, 0.3 , 0)];
  346. [_ugcEdit setTailWaterMark:_config.tailWatermark.image normalizationFrame:_config.tailWatermark.frame duration:_config.tailWatermark.duration];
  347. }
  348. - (UIView*)generatingView
  349. {
  350. /*用作生成时的提示浮层*/
  351. if (!_generationView) {
  352. _generationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.ugckit_width, self.view.ugckit_height + 64)];
  353. _generationView.backgroundColor = UIColor.blackColor;
  354. _generationView.alpha = 0.9f;
  355. _generateProgressView = [UIProgressView new];
  356. _generateProgressView.center = CGPointMake(_generationView.ugckit_width / 2, _generationView.ugckit_height / 2);
  357. _generateProgressView.bounds = CGRectMake(0, 0, 225, 20);
  358. _generateProgressView.progressTintColor = RGB(238, 100, 85);
  359. [_generateProgressView setTrackImage:_theme.progressTrackImage];
  360. //_generateProgressView.trackTintColor = UIColor.whiteColor;
  361. //_generateProgressView.transform = CGAffineTransformMakeScale(1.0, 2.0);
  362. _generationTitleLabel = [UILabel new];
  363. _generationTitleLabel.font = [UIFont systemFontOfSize:14];
  364. _generationTitleLabel.text = [_theme localizedString:@"UGCKit.Edit.VideoGenerating"];
  365. _generationTitleLabel.textColor = UIColor.whiteColor;
  366. _generationTitleLabel.textAlignment = NSTextAlignmentCenter;
  367. _generationTitleLabel.frame = CGRectMake(0, _generateProgressView.ugckit_y - 34, _generationView.ugckit_width, 14);
  368. _generateCannelBtn = [UIButton new];
  369. [_generateCannelBtn setImage:_theme.closeIcon forState:UIControlStateNormal];
  370. _generateCannelBtn.frame = CGRectMake(_generateProgressView.ugckit_right + 15, _generationTitleLabel.ugckit_bottom + 10, 20, 20);
  371. [_generateCannelBtn addTarget:self action:@selector(onCancel:) forControlEvents:UIControlEventTouchUpInside];
  372. [_generationView addSubview:_generationTitleLabel];
  373. [_generationView addSubview:_generateProgressView];
  374. [_generationView addSubview:_generateCannelBtn];
  375. [[[UIApplication sharedApplication] delegate].window addSubview:_generationView];
  376. }
  377. _generateProgressView.progress = 0.f;
  378. return _generationView;
  379. }
  380. -(void)onPlayVideo
  381. {
  382. if (_isPlay) {
  383. [self pausePlay];
  384. }else{
  385. CGFloat currentPos = _videoCutView.videoRangeSlider.currentPos;
  386. if(_isReverse && currentPos != 0){
  387. [self startPlayFromTime:0 toTime:currentPos];
  388. }else{
  389. [self startPlayFromTime:currentPos toTime:_duration];
  390. }
  391. if (_effectSelectType == EffectSelectType_Paster) {
  392. [self removeAllPasterViewFromSuperView];
  393. [self setVideoPastersToSDK];
  394. }
  395. if (_effectSelectType == EffectSelectType_Text) {
  396. [self removeAllTextFieldFromSuperView];
  397. [self setVideoSubtitlesToSDK];
  398. }
  399. }
  400. }
  401. - (void)setPlayBtn:(BOOL)isPlay
  402. {
  403. if (isPlay) {
  404. [_playBtn setBackgroundImage:_theme.editPauseIcon forState:UIControlStateNormal];
  405. [_playBtn setBackgroundImage:_theme.editPauseHighlightedIcon forState:UIControlStateHighlighted];
  406. }else{
  407. [_playBtn setBackgroundImage:_theme.editPlayIcon forState:UIControlStateNormal];
  408. [_playBtn setBackgroundImage:_theme.editPlayHighlightedIcon forState:UIControlStateHighlighted];
  409. }
  410. }
  411. - (void)onTapToHideBottomPanel:(UITapGestureRecognizer*)recognizer
  412. {
  413. CGPoint tapPoint = [recognizer locationInView:recognizer.view];
  414. if (_bottomMenu.isHidden && _musicView.hidden) {
  415. BOOL findEffect = NO;
  416. if (_effectSelectType == EffectSelectType_Paster) {
  417. for (NSInteger i = 0; i < _videoPasterInfoList.count; i++) {
  418. CGRect pasterFrame = [_videoPasterInfoList[i].pasterView pasterFrameOnView:recognizer.view];
  419. if (CGRectContainsPoint(pasterFrame, tapPoint)) {
  420. UGCKitVideoPasterInfo *info = _videoPasterInfoList[i];
  421. if (_playTime >= info.startTime && _playTime <= info.endTime) {
  422. [self removeAllPasterViewFromSuperView];
  423. [_videoPreview addSubview:info.pasterView];
  424. [self setVideoPastersToSDK];
  425. findEffect = YES;
  426. break;
  427. }
  428. }
  429. }
  430. }
  431. else if (_effectSelectType == EffectSelectType_Text){
  432. for (NSInteger i = 0; i < _videoTextInfoList.count; i++) {
  433. CGRect textFrame = [_videoTextInfoList[i].textField textFrameOnView:recognizer.view];
  434. if (CGRectContainsPoint(textFrame, tapPoint)) {
  435. UGCKitVideoTextInfo *info = _videoTextInfoList[i];
  436. if (_playTime >= info.startTime && _playTime <= info.endTime){
  437. [self removeAllTextFieldFromSuperView];
  438. [_videoPreview addSubview:info.textField];
  439. [self setVideoSubtitlesToSDK];
  440. findEffect = YES;
  441. break;
  442. }
  443. }
  444. }
  445. }
  446. if (findEffect) {
  447. [_ugcEdit previewAtTime:_playTime];
  448. [self pausePlay];
  449. }
  450. }else{
  451. _musicView.hidden = YES;
  452. _bottomMenu.hidden = NO;
  453. }
  454. }
  455. - (void)resetConfirmBtn
  456. {
  457. CGFloat y = CGRectGetMinY(_effectConfirmBtn.frame);
  458. if(_bottomMenu.isHidden){
  459. [_effectConfirmBtn setTitle:@"" forState:UIControlStateNormal];
  460. [_effectConfirmBtn setBackgroundImage:_theme.confirmIcon forState:UIControlStateNormal];
  461. [_effectConfirmBtn setBackgroundImage:_theme.confirmHighlightedIcon forState:UIControlStateHighlighted];
  462. _effectConfirmBtn.frame = CGRectMake(self.view.ugckit_width - 15 * kScaleX - 44, y, 44, 30);
  463. }else{
  464. [_effectConfirmBtn setTitle:[_theme localizedString:@"UGCKit.Common.Done"] forState:UIControlStateNormal];
  465. _effectConfirmBtn.titleLabel.font = [UIFont systemFontOfSize:14];
  466. [_effectConfirmBtn setBackgroundImage:_theme.nextIcon forState:UIControlStateNormal];
  467. _effectConfirmBtn.frame = CGRectMake(self.view.ugckit_width - 15 * kScaleX - 70, y, 70, 30);
  468. }
  469. }
  470. - (void)onTapCloseButton:(id)sender {
  471. if (_bottomMenu.hidden) {
  472. [self cancelEdit];
  473. } else {
  474. [self goBack];
  475. }
  476. }
  477. /// 取消编辑状态
  478. - (void)cancelEdit {
  479. UIAlertController *controller = [UIAlertController alertControllerWithTitle:[_theme localizedString:@"UGCKit.Edit.VideoEffect.AbandonEdit"]
  480. message:nil
  481. preferredStyle:UIAlertControllerStyleAlert];
  482. [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.OK"]
  483. style:UIAlertActionStyleDestructive
  484. handler:^(UIAlertAction * _Nonnull action) {
  485. self->_musicView.hidden = YES;
  486. [self clearEffect];
  487. [self onHideEffectView];
  488. [self resetConfirmBtn];
  489. }]];
  490. [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.Cancel"]
  491. style:UIAlertActionStyleCancel
  492. handler:nil]];
  493. [self presentViewController:controller animated:YES completion:nil];
  494. }
  495. - (void)goBack {
  496. UIAlertController *controller = [UIAlertController alertControllerWithTitle:[_theme localizedString:@"UGCKit.Edit.VideoEffect.AbandonEdit"]
  497. message:nil
  498. preferredStyle:UIAlertControllerStyleAlert];
  499. [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.OK"]
  500. style:UIAlertActionStyleDestructive
  501. handler:^(UIAlertAction * _Nonnull action) {
  502. [self->_ugcEdit stopPlay];
  503. [self setPlayBtn:NO];
  504. if (self.completion) {
  505. self.completion([UGCKitResult cancelledResult]);
  506. }
  507. }]];
  508. [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.Cancel"]
  509. style:UIAlertActionStyleCancel
  510. handler:nil]];
  511. [self presentViewController:controller animated:YES completion:nil];
  512. }
  513. - (void)goFinish
  514. {
  515. if (_bottomMenu.hidden) {
  516. if (_effectSelectType == EffectSelectType_Paster) {
  517. [self removeAllPasterViewFromSuperView];
  518. [self setVideoPastersToSDK];
  519. }
  520. if (_effectSelectType == EffectSelectType_Text) {
  521. [self removeAllTextFieldFromSuperView];
  522. [self setVideoSubtitlesToSDK];
  523. }
  524. _bottomMenu.hidden = NO;
  525. _musicView.hidden = YES;
  526. [self onHideEffectView];
  527. [self resetConfirmBtn];
  528. }else{
  529. if (self.onTapNextButton) {
  530. __weak __typeof(self) wself = self;
  531. self.onTapNextButton(^(BOOL shouldSave){
  532. if (shouldSave) {
  533. [wself generateVideo];
  534. }
  535. });
  536. }
  537. }
  538. }
  539. - (BOOL)shouldAutorotate {
  540. return NO;
  541. }
  542. - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
  543. return UIInterfaceOrientationMaskPortrait;
  544. }
  545. - (void)onCancel:(UIButton*)sender
  546. {
  547. _generationView.hidden = YES;
  548. [_ugcEdit cancelGenerate];
  549. [self startPlayFromTime:0 toTime:_duration];
  550. }
  551. - (void)onSelectMusic
  552. {
  553. if (_BGMPath) {
  554. _musicView.hidden = !_musicView.hidden;
  555. }else{
  556. [self resetVideoProgress];
  557. UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:_bgmListVC];
  558. [nv.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
  559. nv.navigationBar.barTintColor = RGB(25, 29, 38);
  560. nv.modalPresentationStyle = UIModalPresentationFullScreen;
  561. [self presentViewController:nv animated:YES completion:nil];
  562. [_bgmListVC loadBGMList];
  563. }
  564. }
  565. /// 特效入口点击事件响应函数
  566. - (void)onShowEffectView
  567. {
  568. _isHidingEffectView = NO;
  569. _isShowingEffectView = YES;
  570. [_effectView.layer removeAllAnimations];
  571. [_coverImageView.layer removeAllAnimations];
  572. [self resetVideoProgress];
  573. _coverImageView.hidden = NO;
  574. _coverImageView.image = [TXVideoInfoReader getSampleImage:_playTime videoAsset:_videoAsset];
  575. _videoPreview.hidden = YES;
  576. [UIView animateWithDuration:0.3 animations:^{
  577. self->_coverImageView.frame = CGRectMake(0, 54 * kScaleY, self.view.ugckit_width, 410 * kScaleY);
  578. self->_effectView.frame = CGRectMake(0, self.view.ugckit_height - 205 * kScaleY, self->_effectView.ugckit_width, self->_effectView.ugckit_height);
  579. } completion:^(BOOL finished) {
  580. self->_videoPreview.frame = self->_coverImageView.frame;
  581. if (self->_isShowingEffectView) {
  582. self->_bottomMenu.hidden = YES;
  583. }
  584. }];
  585. WEAKIFY(self);
  586. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  587. STRONGIFY_OR_RETURN(self);
  588. if (self->_isShowingEffectView) {
  589. self->_isShowingEffectView = NO;
  590. self->_videoPreview.hidden = NO;
  591. self->_coverImageView.hidden = YES;
  592. }
  593. });
  594. }
  595. - (void)onHideEffectView
  596. {
  597. _isHidingEffectView = YES;
  598. _isShowingEffectView = NO;
  599. [_effectView.layer removeAllAnimations];
  600. [_coverImageView.layer removeAllAnimations];
  601. _coverImageView.hidden = NO;
  602. _coverImageView.image = [TXVideoInfoReader getSampleImage:_playTime videoAsset:_videoAsset];
  603. _videoPreview.hidden = YES;
  604. _bottomMenu.hidden = NO;
  605. [UIView animateWithDuration:0.3 animations:^{
  606. self->_coverImageView.frame = CGRectMake(0, 0, self.view.ugckit_width,self.view.ugckit_height);
  607. self->_effectView.frame = CGRectMake(0, self.view.ugckit_height, self->_effectView.ugckit_width, self->_effectView.ugckit_height);
  608. } completion:^(BOOL finished) {
  609. self->_videoPreview.frame = self->_coverImageView.frame;
  610. [self startPlayFromTime:0 toTime:self->_duration];
  611. }];
  612. WEAKIFY(self);
  613. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  614. STRONGIFY_OR_RETURN(self);
  615. if (self->_isHidingEffectView) {
  616. self->_isHidingEffectView = NO;
  617. self->_videoPreview.hidden = NO;
  618. self->_coverImageView.hidden = YES;
  619. }
  620. });
  621. }
  622. -(void)onDeleteEffect
  623. {
  624. CGFloat endTime = 0;
  625. if (_effectSelectType == EffectSelectType_Effect) {
  626. UGCKitVideoColorInfo *info = [_videoCutView removeLastColoration:UGCKitRangeColorType_Effect];
  627. if (info) {
  628. float time = _isReverse ? MAX(info.endPos, info.startPos) : MIN(info.endPos, info.startPos);
  629. [_videoCutView setPlayTime:time];
  630. _playTime = time;
  631. }
  632. [_ugcEdit deleteLastEffect];
  633. }
  634. else if (_effectSelectType == EffectSelectType_Paster){
  635. if (_pasterEffectArray.count <= 1) {
  636. return;
  637. }
  638. UGCKitVideoPasterInfo *info = [_videoPasterInfoList lastObject];
  639. [info.pasterView removeFromSuperview];
  640. [_videoPasterInfoList removeLastObject];
  641. [_pasterEffectArray removeObjectAtIndex:_pasterEffectArray.count - 2];
  642. [_effectSelectView setEffectList:_pasterEffectArray];
  643. [_videoCutView removeLastColoration:UGCKitRangeColorType_Paster];
  644. if (_videoPasterInfoList.count > 0) {
  645. UGCKitVideoPasterInfo *info = [_videoPasterInfoList lastObject];
  646. [self setLeftPanFrame:info.startTime rightPanFrame:info.endTime];
  647. endTime = info.endTime;
  648. }else{
  649. [self setLeftPanFrame:0 rightPanFrame:0];
  650. endTime = 0;
  651. }
  652. [self setVideoPastersToSDK];
  653. [_ugcEdit previewAtTime:endTime];
  654. }
  655. else if (_effectSelectType == EffectSelectType_Text){
  656. if (_textEffectArray.count <= 1) {
  657. return;
  658. }
  659. UGCKitVideoTextInfo *info = [_videoTextInfoList lastObject];
  660. [info.textField removeFromSuperview];
  661. [_videoTextInfoList removeLastObject];
  662. [_textEffectArray removeObjectAtIndex:_textEffectArray.count - 2];
  663. [_effectSelectView setEffectList:_textEffectArray];
  664. [_videoCutView removeLastColoration:UGCKitRangeColorType_Text];
  665. if (_videoTextInfoList.count > 0) {
  666. UGCKitVideoTextInfo *info = [_videoTextInfoList lastObject];
  667. [self setLeftPanFrame:info.startTime rightPanFrame:info.endTime];
  668. endTime = info.endTime;
  669. }else{
  670. [self setLeftPanFrame:0 rightPanFrame:0];
  671. endTime = 0;
  672. }
  673. [self setVideoSubtitlesToSDK];
  674. [_ugcEdit previewAtTime:endTime];
  675. }
  676. }
  677. - (void)removeAllPasterViewFromSuperView
  678. {
  679. for (UGCKitVideoPasterInfo* pasterInfo in _videoPasterInfoList) {
  680. [pasterInfo.pasterView removeFromSuperview];
  681. }
  682. }
  683. - (void)removeAllTextFieldFromSuperView
  684. {
  685. for (UGCKitVideoTextInfo* textInfo in _videoTextInfoList) {
  686. [textInfo.textField removeFromSuperview];
  687. }
  688. }
  689. - (void)removeCurrentPasterInfo
  690. {
  691. if (_effectSelectIndex >= _videoPasterInfoList.count
  692. || _effectSelectIndex >= _pasterEffectArray.count - 1
  693. || _effectSelectIndex < 0) {
  694. return;
  695. }
  696. [_videoPasterInfoList removeObjectAtIndex:_effectSelectIndex];
  697. [_pasterEffectArray removeObjectAtIndex:_effectSelectIndex];
  698. [_effectSelectView setEffectList:_pasterEffectArray];
  699. [_videoCutView removeColoration:UGCKitRangeColorType_Paster index:_effectSelectIndex];
  700. if (_videoPasterInfoList.count > 0) {
  701. UGCKitVideoPasterInfo *info = [_videoPasterInfoList lastObject];
  702. [self setLeftPanFrame:info.startTime rightPanFrame:info.endTime];
  703. }else{
  704. [self setLeftPanFrame:0 rightPanFrame:0];
  705. }
  706. _effectSelectIndex = _pasterEffectArray.count - 2;
  707. [self setVideoPastersToSDK];
  708. }
  709. - (void)removeCurrentTextInfo
  710. {
  711. if (_effectSelectIndex >= _videoTextInfoList.count
  712. || _effectSelectIndex >= _textEffectArray.count - 1
  713. || _effectSelectIndex < 0) {
  714. return;
  715. }
  716. [_videoTextInfoList removeObjectAtIndex:_effectSelectIndex];
  717. [_textEffectArray removeObjectAtIndex:_effectSelectIndex];
  718. [_effectSelectView setEffectList:_textEffectArray];
  719. [_videoCutView removeColoration:UGCKitRangeColorType_Text index:_effectSelectIndex];
  720. if (_videoTextInfoList.count > 0) {
  721. UGCKitVideoTextInfo *info = [_videoTextInfoList lastObject];
  722. [self setLeftPanFrame:info.startTime rightPanFrame:info.endTime];
  723. }else{
  724. [self setLeftPanFrame:0 rightPanFrame:0];
  725. }
  726. _effectSelectIndex = _textEffectArray.count - 2;
  727. [self setVideoSubtitlesToSDK];
  728. }
  729. - (CGFloat)getLastPasterEndTime
  730. {
  731. if (_videoPasterInfoList.count > 0) {
  732. return [_videoPasterInfoList lastObject].endTime;
  733. }
  734. return 0;
  735. }
  736. - (CGFloat)getLastTextEndTime
  737. {
  738. if (_videoTextInfoList.count > 0) {
  739. return [_videoTextInfoList lastObject].endTime;
  740. }
  741. return 0;
  742. }
  743. - (void)clearEffect
  744. {
  745. switch (_effectSelectType) {
  746. case EffectSelectType_Effect:
  747. break;
  748. case EffectSelectType_Time:
  749. {
  750. [_ugcEdit setSpeedList:nil];
  751. [_ugcEdit setReverse:NO];
  752. [_ugcEdit setRepeatPlay:nil];
  753. [_videoCutView setCenterPanHidden:YES];
  754. _timeIndex = 0;
  755. }
  756. break;
  757. case EffectSelectType_Filter:
  758. {
  759. [_ugcEdit setFilter:nil];
  760. _filterIndex = 0;
  761. }
  762. break;
  763. case EffectSelectType_Paster:
  764. {
  765. NSInteger i = _videoPasterInfoList.count;
  766. while (i > 0) {
  767. [_videoCutView removeLastColoration:UGCKitRangeColorType_Paster];
  768. i -- ;
  769. }
  770. [self removeAllPasterViewFromSuperView];
  771. [_videoPasterInfoList removeAllObjects];
  772. [_pasterEffectArray removeObjectsInRange:NSMakeRange(0, _pasterEffectArray.count - 1)];
  773. [_ugcEdit setPasterList:nil];
  774. [_ugcEdit setAnimatedPasterList:nil];
  775. }
  776. break;
  777. case EffectSelectType_Text:
  778. {
  779. NSInteger i = _videoTextInfoList.count;
  780. while (i > 0) {
  781. [_videoCutView removeLastColoration:UGCKitRangeColorType_Text];
  782. i -- ;
  783. }
  784. [self removeAllTextFieldFromSuperView];
  785. [_videoTextInfoList removeAllObjects];
  786. [_textEffectArray removeObjectsInRange:NSMakeRange(0, _textEffectArray.count - 1)];
  787. [_ugcEdit setSubtitleList:nil];
  788. }
  789. break;
  790. default:
  791. break;
  792. }
  793. }
  794. - (void)resetVideoProgress
  795. {
  796. _playTime = 0;
  797. _isSeek = YES;
  798. _isPlay = NO;
  799. _timeLabel.text = LocalizationNotNeeded(@"00:00");
  800. [_ugcEdit previewAtTime:_playTime];
  801. [self setPlayBtn:NO];
  802. }
  803. //设置特效选中区间
  804. - (void)setLeftPanFrame:(CGFloat)leftTime rightPanFrame:(CGFloat)rightTime
  805. {
  806. if (leftTime == 0 && rightTime == 0) {
  807. [_videoCutView setLeftPanHidden:YES];
  808. [_videoCutView setRightPanHidden:YES];
  809. [_videoCutView setLeftPanFrame:0];
  810. [_videoCutView setRightPanFrame:0];
  811. [_videoCutView setPlayTime:0];
  812. }else{
  813. [_videoCutView setLeftPanHidden:NO];
  814. [_videoCutView setRightPanHidden:NO];
  815. [_videoCutView setLeftPanFrame:leftTime];
  816. [_videoCutView setRightPanFrame:rightTime];
  817. [_videoCutView setPlayTime:leftTime];
  818. }
  819. }
  820. - (void)startPlayFromTime:(CGFloat)startTime toTime:(CGFloat)endTime
  821. {
  822. [_ugcEdit startPlayFromTime:startTime toTime:endTime];
  823. _isSeek = NO;
  824. _isPlay = YES;
  825. [self setPlayBtn:YES];
  826. }
  827. - (void)pausePlay
  828. {
  829. [_ugcEdit pausePlay];
  830. [self setPlayBtn:NO];
  831. _isPlay = NO;
  832. }
  833. #pragma mark - To SDK
  834. - (void)generateVideo
  835. {
  836. [self pausePlay];
  837. [self confirmGenerateVideo];
  838. }
  839. - (void)confirmGenerateVideo
  840. {
  841. [_videoPreview stopObservingAudioNotification];
  842. _generationView = [self generatingView];
  843. _generationView.hidden = NO;
  844. _generateCannelBtn.hidden = NO;
  845. [_ugcEdit setCutFromTime:0 toTime:_duration];
  846. if (_config.videoBitrate > 0) {
  847. [_ugcEdit setVideoBitrate:_config.videoBitrate];
  848. }
  849. if (self.generateMode == UGCKitGenerateModeTwoPass) {
  850. [_ugcEdit generateVideoWithTwoPass:_config.compressResolution videoOutputPath:_videoOutputPath];
  851. } else {
  852. [_ugcEdit generateVideo:_config.compressResolution videoOutputPath:_videoOutputPath];
  853. }
  854. }
  855. //设置贴纸(静态/动态贴纸)
  856. - (void)setVideoPastersToSDK
  857. {
  858. NSMutableArray* animatePasters = [NSMutableArray new];
  859. NSMutableArray* staticPasters = [NSMutableArray new];
  860. for (UGCKitVideoPasterInfo* pasterInfo in _videoPasterInfoList) {
  861. if ([_videoPreview.subviews containsObject:pasterInfo.pasterView]) {
  862. continue;
  863. }
  864. if (pasterInfo.pasterInfoType == UGCKitPasterInfoType_Animate) {
  865. TXAnimatedPaster* paster = [TXAnimatedPaster new];
  866. paster.startTime = pasterInfo.startTime;
  867. paster.endTime = pasterInfo.endTime;
  868. paster.frame = [pasterInfo.pasterView pasterFrameOnView:_videoPreview];
  869. paster.rotateAngle = pasterInfo.pasterView.rotateAngle * 180 / M_PI;
  870. paster.animatedPasterpath = pasterInfo.path;
  871. [animatePasters addObject:paster];
  872. }
  873. else if (pasterInfo.pasterInfoType == UGCKitPasterInfoType_static){
  874. TXPaster *paster = [TXPaster new];
  875. paster.startTime = pasterInfo.startTime;
  876. paster.endTime = pasterInfo.endTime;
  877. paster.frame = [pasterInfo.pasterView pasterFrameOnView:_videoPreview];
  878. paster.pasterImage = pasterInfo.pasterView.staticImage;
  879. [staticPasters addObject:paster];
  880. }
  881. }
  882. [_ugcEdit setAnimatedPasterList:animatePasters];
  883. [_ugcEdit setPasterList:staticPasters];
  884. }
  885. //设置字幕(气泡)
  886. - (void)setVideoSubtitlesToSDK
  887. {
  888. NSMutableArray* subtitles = [NSMutableArray new];
  889. NSMutableArray<UGCKitVideoTextInfo*>* emptyVideoTexts;
  890. for (UGCKitVideoTextInfo* textInfo in _videoTextInfoList) {
  891. if (textInfo.textField.text.length < 1) {
  892. [emptyVideoTexts addObject:textInfo];
  893. continue;
  894. }
  895. if ([_videoPreview.subviews containsObject:textInfo.textField]) {
  896. continue;
  897. }
  898. TXSubtitle* subtitle = [TXSubtitle new];
  899. subtitle.titleImage = textInfo.textField.textImage;
  900. subtitle.frame = [textInfo.textField textFrameOnView:_videoPreview];
  901. subtitle.startTime = textInfo.startTime;
  902. subtitle.endTime = textInfo.endTime;
  903. [subtitles addObject:subtitle];
  904. }
  905. [_ugcEdit setSubtitleList:subtitles];
  906. }
  907. - (void)setFilter:(NSInteger)index
  908. {
  909. _filterIndex = index;
  910. if (index == 0) {
  911. [_ugcEdit setFilter:nil];
  912. } else {
  913. TCFilter *filter = [TCFilterManager defaultManager].allFilters[index-1];
  914. UIImage *image = [UIImage imageWithContentsOfFile:filter.lookupImagePath];
  915. [_ugcEdit setFilter:image];
  916. }
  917. }
  918. #pragma mark VideoPreviewDelegate
  919. - (void)onVideoPlay
  920. {
  921. [self startPlayFromTime:0 toTime:_duration];
  922. }
  923. - (void)onVideoPlayProgress:(CGFloat)time
  924. {
  925. if (!_isSeek) {
  926. _playTime = time;
  927. [_videoCutView setPlayTime:_playTime];
  928. _timeLabel.text = [NSString stringWithFormat:@"%02d:%02d",(int)_playTime / 60 , (int)_playTime % 60];
  929. }
  930. }
  931. - (void)onVideoPlayFinished
  932. {
  933. if (_effectType != -1) {
  934. [self onEffectBtnEndSelect:nil];
  935. }else{
  936. [self startPlayFromTime:0 toTime:_duration];
  937. }
  938. }
  939. #pragma mark TXVideoGenerateDelegate
  940. -(void) onGenerateProgress:(float)progress
  941. {
  942. _generateProgressView.progress = progress;
  943. }
  944. -(void) onGenerateComplete:(TXGenerateResult *)result
  945. {
  946. _generationView.hidden = YES;
  947. [UGCKitReporter report:UGCKitReportItem_videoedit userName:nil code:result.retCode msg:result.descMsg];
  948. [_ugcEdit stopPlay];
  949. if (self.completion) {
  950. UGCKitResult *r = [[UGCKitResult alloc] init];
  951. if (result.retCode == 0) {
  952. r.media = [UGCKitMedia mediaWithVideoPath:self->_videoOutputPath];
  953. } else {
  954. r.code = result.retCode;
  955. r.info = @{NSLocalizedDescriptionKey: result.descMsg};
  956. }
  957. self.completion(r);
  958. }
  959. }
  960. #pragma mark - TXVideoPublishListener
  961. - (void)dismissViewController
  962. {
  963. [_ugcEdit stopPlay];
  964. if (self.completion) {
  965. UGCKitResult *result = [[UGCKitResult alloc] init];
  966. result.media = [UGCKitMedia mediaWithVideoPath:_videoOutputPath];
  967. self.completion(result);
  968. }
  969. //缓存视频状态置nil
  970. [[NSUserDefaults standardUserDefaults] setObject:nil forKey:CACHE_PATH_LIST];
  971. }
  972. #pragma mark - Menu Actions
  973. - (void)onMusicBtnClicked
  974. {
  975. _bottomMenu.hidden = YES;
  976. [self onSelectMusic];
  977. [self setLeftPanFrame:0 rightPanFrame:0];
  978. [self resetConfirmBtn];
  979. }
  980. - (void)onEffectBtnClicked
  981. {
  982. _bottomMenu.hidden = YES;
  983. _deleteBtn.hidden = NO;
  984. [self resetConfirmBtn];
  985. [self onShowEffectView];
  986. [self removeAllTextFieldFromSuperView];
  987. [self removeAllPasterViewFromSuperView];
  988. [self setLeftPanFrame:0 rightPanFrame:0];
  989. _effectSelectType = EffectSelectType_Effect;
  990. [_videoCutView setColorType:UGCKitRangeColorType_Effect];
  991. [_videoCutView setCenterPanHidden:YES];
  992. __block NSArray <UGCKitEffectInfo *> *effectArray = nil;
  993. dispatch_barrier_sync(_imageLoadingQueue, ^{
  994. effectArray = _effectList;
  995. });
  996. [_effectSelectView setEffectList:effectArray momentary:YES];
  997. }
  998. -(void)onTimeBtnClicked
  999. {
  1000. _bottomMenu.hidden = YES;
  1001. _deleteBtn.hidden = YES;
  1002. [self resetConfirmBtn];
  1003. [self onShowEffectView];
  1004. [self removeAllTextFieldFromSuperView];
  1005. [self removeAllPasterViewFromSuperView];
  1006. [self setLeftPanFrame:0 rightPanFrame:0];
  1007. _effectSelectType = EffectSelectType_Time;
  1008. [_videoCutView setColorType:UGCKitRangeColorType_Time];
  1009. // dispatch_async(dispatch_get_global_queue(0, 0), ^{
  1010. NSMutableArray <UGCKitEffectInfo *> *effectArray = [NSMutableArray array];
  1011. [effectArray addObject:({
  1012. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1013. v.name = [_theme localizedString:@"UGCKit.Common.None"];
  1014. v.icon = _theme.editTimeEffectNormalIcon;
  1015. v.selectIcon = _theme.editFilterSelectionIcon;
  1016. v;
  1017. })];
  1018. [effectArray addObject:({
  1019. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1020. v.name = [_theme localizedString:@"UGCKit.Edit.VideoEffect.TimeEffect.BackInTime"];
  1021. v.icon = _theme.editTimeEffectReveseIcon;
  1022. v.selectIcon = _theme.editFilterSelectionIcon;
  1023. v;
  1024. })];
  1025. [effectArray addObject:({
  1026. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1027. v.name = [_theme localizedString:@"UGCKit.Edit.VideoEffect.TimeEffect.Repeat"];
  1028. v.icon = _theme.editTimeEffectRepeatIcon;
  1029. v.selectIcon = _theme.editFilterSelectionIcon;
  1030. v;
  1031. })];
  1032. [effectArray addObject:({
  1033. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1034. v.name = [_theme localizedString:@"UGCKit.Edit.VideoEffect.TimeEffect.SlowMotion"];
  1035. v.icon = _theme.editTimeEffectSlowMotionIcon;
  1036. v.selectIcon = _theme.editFilterSelectionIcon;
  1037. v;
  1038. })];
  1039. // dispatch_async(dispatch_get_main_queue(), ^{
  1040. [_effectSelectView setEffectList:effectArray];
  1041. _effectSelectView.selectedIndex = _timeIndex;
  1042. // });
  1043. // });
  1044. }
  1045. - (void)onFilterBtnClicked
  1046. {
  1047. _bottomMenu.hidden = YES;
  1048. _deleteBtn.hidden = YES;
  1049. [self resetConfirmBtn];
  1050. [self onShowEffectView];
  1051. [self setLeftPanFrame:0 rightPanFrame:0];
  1052. NSArray<TCFilter *> *filters = [[TCFilterManager defaultManager] allFilters];
  1053. NSMutableArray <UGCKitEffectInfo *> *effectArray = [NSMutableArray arrayWithCapacity:filters.count + 1];
  1054. UGCKitEffectInfo *info = [[UGCKitEffectInfo alloc]init];
  1055. info.name = [_theme localizedString:@"UGCKit.Common.None"];
  1056. info.icon = [_theme iconForFilter:nil];
  1057. info.selectIcon = _theme.editFilterSelectionIcon;
  1058. [effectArray addObject:info];
  1059. for (TCFilter *filter in filters) {
  1060. NSString *key = [NSString stringWithFormat:@"TC.Common.Filter_%@", filter.identifier];
  1061. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1062. v.name = [_theme localizedString:key];
  1063. v.icon = [_theme iconForFilter:filter.identifier];
  1064. v.selectIcon = _theme.editFilterSelectionIcon;
  1065. [effectArray addObject:v];
  1066. }
  1067. [_effectSelectView setEffectList:effectArray];
  1068. _effectSelectType = EffectSelectType_Filter;
  1069. _effectSelectView.selectedIndex = _filterIndex;
  1070. [_videoCutView setColorType:UGCKitRangeColorType_Filter];
  1071. [_videoCutView setCenterPanHidden:YES];
  1072. [self removeAllTextFieldFromSuperView];
  1073. [self removeAllPasterViewFromSuperView];
  1074. }
  1075. - (void)onPasterBtnClicked
  1076. {
  1077. _bottomMenu.hidden = YES;
  1078. _deleteBtn.hidden = NO;
  1079. [self resetConfirmBtn];
  1080. [self onShowEffectView];
  1081. [self removeAllTextFieldFromSuperView];
  1082. [self setLeftPanFrame:0 rightPanFrame:0];
  1083. [_effectSelectView setEffectList:_pasterEffectArray];
  1084. [_videoCutView setColorType:UGCKitRangeColorType_Paster];
  1085. [_videoCutView setCenterPanHidden:YES];
  1086. _effectSelectType = EffectSelectType_Paster;
  1087. }
  1088. - (void)onTextBtnClicked
  1089. {
  1090. _bottomMenu.hidden = YES;
  1091. _deleteBtn.hidden = NO;
  1092. [self resetConfirmBtn];
  1093. [self onShowEffectView];
  1094. [self removeAllPasterViewFromSuperView];
  1095. [self setLeftPanFrame:0 rightPanFrame:0];
  1096. [_effectSelectView setEffectList:_textEffectArray];
  1097. [_videoCutView setColorType:UGCKitRangeColorType_Text];
  1098. [_videoCutView setCenterPanHidden:YES];
  1099. _effectSelectType = EffectSelectType_Text;
  1100. }
  1101. #pragma mark UGCKitEffectSelectViewDelegate
  1102. -(void)onEffectBtnBeginSelect:(UIButton *)btn
  1103. {
  1104. if (_effectSelectType != EffectSelectType_Effect) {
  1105. return;
  1106. }
  1107. _effectType = (TXEffectType)btn.tag;
  1108. UIColor *color = UGCKitVideoEffectColorPaletteColorAtIndex(btn.tag);
  1109. [_videoCutView startColoration:color alpha:0.7];
  1110. [_ugcEdit startEffect:(TXEffectType)_effectType startTime:_playTime];
  1111. if (!_isReverse) {
  1112. [self startPlayFromTime:_playTime toTime:_duration];
  1113. }else{
  1114. [self startPlayFromTime:0 toTime:_playTime];
  1115. }
  1116. }
  1117. -(void)onEffectBtnEndSelect:(UIButton *)btn
  1118. {
  1119. if (_effectType != -1) {
  1120. [_videoCutView stopColoration];
  1121. [_ugcEdit stopEffect:_effectType endTime:_playTime];
  1122. [self pausePlay];
  1123. _effectType = -1;
  1124. }
  1125. }
  1126. -(void)onEffectBtnSelected:(UIButton *)btn
  1127. {
  1128. _effectSelectIndex = btn.tag;
  1129. switch (_effectSelectType) {
  1130. case EffectSelectType_Time:
  1131. {
  1132. switch (_effectSelectIndex) {
  1133. case 0:
  1134. [self onVideoTimeEffectsClear];
  1135. break;
  1136. case 1:
  1137. [self onVideoTimeEffectsBackPlay];
  1138. break;
  1139. case 2:
  1140. [self onVideoTimeEffectsRepeat];
  1141. break;
  1142. case 3:
  1143. [self onVideoTimeEffectsSpeed];
  1144. break;
  1145. default:
  1146. break;
  1147. }
  1148. _timeIndex = _effectSelectIndex;
  1149. } break;
  1150. case EffectSelectType_Filter:
  1151. {
  1152. [self setFilter:_effectSelectIndex];
  1153. // if (!_isPlay) {
  1154. // [_ugcEdit resumePlay];
  1155. // [self setPlayBtn:YES];
  1156. // _isPlay = YES;
  1157. // _isSeek = NO;
  1158. // }
  1159. } break;
  1160. case EffectSelectType_Paster:
  1161. {
  1162. [self pausePlay];
  1163. [self removeAllPasterViewFromSuperView];
  1164. if (_effectSelectIndex == _pasterEffectArray.count - 1) {
  1165. _pasterAddView.hidden = NO;
  1166. [_pasterAddView setUGCKitPasterType:UGCKitPasterType_Animate];
  1167. }else{
  1168. UGCKitVideoPasterInfo* pasterInfo = _videoPasterInfoList[_effectSelectIndex];
  1169. [_videoPreview addSubview:pasterInfo.pasterView];
  1170. [self setLeftPanFrame:pasterInfo.startTime rightPanFrame:pasterInfo.endTime];
  1171. [_ugcEdit previewAtTime:pasterInfo.endTime];
  1172. }
  1173. } break;
  1174. case EffectSelectType_Text:
  1175. {
  1176. [self pausePlay];
  1177. [self removeAllTextFieldFromSuperView];
  1178. if (_effectSelectIndex == _textEffectArray.count - 1) {
  1179. _pasterAddView.hidden = NO;
  1180. [_pasterAddView setUGCKitPasterType:UGCKitPasterType_Qipao];
  1181. }else{
  1182. UGCKitVideoTextInfo* textInfo = _videoTextInfoList[_effectSelectIndex];
  1183. [_videoPreview addSubview:textInfo.textField];
  1184. [self setLeftPanFrame:textInfo.startTime rightPanFrame:textInfo.endTime];
  1185. [_ugcEdit previewAtTime:textInfo.endTime];
  1186. }
  1187. } break;
  1188. default:
  1189. break;
  1190. }
  1191. }
  1192. - (void)onVideoTimeEffectsClear
  1193. {
  1194. _timeType = TimeType_Clear;
  1195. _isReverse = NO;
  1196. [_ugcEdit setReverse:_isReverse];
  1197. [_ugcEdit setRepeatPlay:nil];
  1198. [_ugcEdit setSpeedList:nil];
  1199. [self startPlayFromTime:0 toTime:_duration];
  1200. [_videoCutView setCenterPanHidden:YES];
  1201. }
  1202. - (void)onVideoTimeEffectsBackPlay
  1203. {
  1204. _timeType = TimeType_Back;
  1205. _isReverse = YES;
  1206. [_ugcEdit setReverse:_isReverse];
  1207. [_ugcEdit setRepeatPlay:nil];
  1208. [_ugcEdit setSpeedList:nil];
  1209. [self startPlayFromTime:0 toTime:_duration];
  1210. [_videoCutView setCenterPanHidden:YES];
  1211. }
  1212. - (void)onVideoTimeEffectsRepeat
  1213. {
  1214. _timeType = TimeType_Repeat;
  1215. _isReverse = NO;
  1216. [_ugcEdit setReverse:_isReverse];
  1217. [_ugcEdit setSpeedList:nil];
  1218. TXRepeat *repeat = [[TXRepeat alloc] init];
  1219. repeat.startTime = _duration / 5;
  1220. repeat.endTime = repeat.startTime + 0.5;
  1221. repeat.repeatTimes = 3;
  1222. [_ugcEdit setRepeatPlay:@[repeat]];
  1223. [self startPlayFromTime:0 toTime:_duration];
  1224. [_videoCutView setCenterPanHidden:NO];
  1225. [_videoCutView setCenterPanFrame:repeat.startTime];
  1226. }
  1227. - (void)onVideoTimeEffectsSpeed
  1228. {
  1229. _timeType = TimeType_Speed;
  1230. _isReverse = NO;
  1231. [_ugcEdit setReverse:_isReverse];
  1232. [_ugcEdit setRepeatPlay:nil];
  1233. TXSpeed *speed1 =[[TXSpeed alloc] init];
  1234. speed1.startTime = _duration* 1.5 / 5;
  1235. speed1.endTime = speed1.startTime + 0.5;
  1236. speed1.speedLevel = SPEED_LEVEL_SLOW;
  1237. TXSpeed *speed2 =[[TXSpeed alloc] init];
  1238. speed2.startTime = speed1.endTime;
  1239. speed2.endTime = speed2.startTime + 0.5;
  1240. speed2.speedLevel = SPEED_LEVEL_SLOWEST;
  1241. TXSpeed *speed3 =[[TXSpeed alloc] init];
  1242. speed3.startTime = speed2.endTime;
  1243. speed3.endTime = speed3.startTime + 0.5;
  1244. speed3.speedLevel = SPEED_LEVEL_SLOW;
  1245. [_ugcEdit setSpeedList:@[speed1,speed2,speed3]];
  1246. [self startPlayFromTime:0 toTime:_duration];
  1247. [_videoCutView setCenterPanHidden:NO];
  1248. [_videoCutView setCenterPanFrame:speed1.startTime];
  1249. }
  1250. #pragma mark UGCKitPasterAddViewDelegate
  1251. - (void)onPasterQipaoSelect:(UGCKitPasterQipaoInfo *)info
  1252. {
  1253. [self removeAllTextFieldFromSuperView];
  1254. int width = 170;
  1255. int height = info.height / info.width * width;
  1256. UGCKitVideoTextFiled* videoTextField = [[UGCKitVideoTextFiled alloc] initWithFrame:CGRectMake((_videoPreview.ugckit_width - 170) / 2, (_videoPreview.ugckit_height - 50) / 2, 170, 50)
  1257. theme:_theme];
  1258. [videoTextField setTextBubbleImage:info.image textNormalizationFrame:CGRectMake(info.textLeft / info.width, info.textTop / info.height, (info.width - info.textLeft - info.textRight) / info.width, (info.height - info.textTop - info.textBottom) / info.height)];
  1259. videoTextField.frame = CGRectMake((_videoPreview.ugckit_width - width) / 2, (_videoPreview.ugckit_height - height) / 2, width, height);
  1260. videoTextField.delegate = self;
  1261. [_videoPreview addSubview:videoTextField];
  1262. CGFloat percent = _duration / 10.0;
  1263. CGFloat startTime = ([self getLastTextEndTime] == 0 ? 0 : [self getLastTextEndTime] + percent);
  1264. if (startTime > _duration) {
  1265. startTime = 0;
  1266. }
  1267. CGFloat endTime = startTime + percent;
  1268. if(endTime > _duration){
  1269. endTime = _duration;
  1270. }
  1271. UGCKitVideoTextInfo* textInfo = [UGCKitVideoTextInfo new];
  1272. textInfo.textField = videoTextField;
  1273. textInfo.startTime = startTime;
  1274. textInfo.endTime = endTime;
  1275. [_videoTextInfoList addObject:textInfo];
  1276. [_textEffectArray insertObject:({
  1277. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1278. v.name = [_theme localizedString:@"UGCKit.Edit.VideoEffect.BubbleSubtitle"];
  1279. v.icon = info.iconImage;
  1280. v;
  1281. }) atIndex:_textEffectArray.count - 1];
  1282. [_effectSelectView setEffectList:_textEffectArray];
  1283. _effectSelectIndex = _textEffectArray.count - 2;
  1284. [self setLeftPanFrame:startTime rightPanFrame:endTime];
  1285. [_ugcEdit previewAtTime:endTime];
  1286. [_videoCutView startColoration:[UIColor redColor] alpha:0.7];
  1287. }
  1288. - (void)onPasterAnimateSelect:(UGCKitPasterAnimateInfo *)info
  1289. {
  1290. [self removeAllPasterViewFromSuperView];
  1291. int width = 170;
  1292. int height = info.height / info.width * width;
  1293. UGCKitVideoPasterView *pasterView = [[UGCKitVideoPasterView alloc] initWithFrame:CGRectMake((_videoPreview.ugckit_width - width) / 2, (_videoPreview.ugckit_height - height) / 2, width, height)
  1294. theme:_theme];
  1295. pasterView.delegate = self;
  1296. [pasterView setImageList:info.imageList imageDuration:info.duration];
  1297. [_videoPreview addSubview:pasterView];
  1298. CGFloat percent = _duration / 10.0;
  1299. CGFloat startTime = ([self getLastPasterEndTime] == 0 ? 0 : [self getLastPasterEndTime] + percent);
  1300. if (startTime > _duration) {
  1301. startTime = 0;
  1302. }
  1303. CGFloat endTime = startTime + percent;
  1304. if(endTime > _duration){
  1305. endTime = _duration;
  1306. }
  1307. UGCKitVideoPasterInfo* pasterInfo = [[UGCKitVideoPasterInfo alloc] init];
  1308. pasterInfo.pasterView = pasterView;
  1309. pasterInfo.pasterInfoType = UGCKitPasterInfoType_Animate;
  1310. pasterInfo.path = info.path;
  1311. pasterInfo.iconImage = info.iconImage;
  1312. pasterInfo.startTime = startTime;
  1313. pasterInfo.endTime = endTime;
  1314. [_videoPasterInfoList addObject:pasterInfo];
  1315. [_pasterEffectArray insertObject:({
  1316. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1317. v.name = [_theme localizedString:@"UGCKit.Edit.Paster.Dynamic"];
  1318. v.icon = info.iconImage;
  1319. v;
  1320. }) atIndex:_pasterEffectArray.count - 1];
  1321. [_effectSelectView setEffectList:_pasterEffectArray];
  1322. _effectSelectIndex = _pasterEffectArray.count - 2;
  1323. [self setLeftPanFrame:startTime rightPanFrame:endTime];
  1324. [_ugcEdit previewAtTime:endTime];
  1325. [_videoCutView startColoration:[UIColor redColor] alpha:0.7];
  1326. }
  1327. - (void)onPasterStaticSelect:(UGCKitPasterStaticInfo *)info
  1328. {
  1329. [self removeAllPasterViewFromSuperView];
  1330. int width = 170;
  1331. int height = info.height / info.width * width;
  1332. UGCKitVideoPasterView *pasterView = [[UGCKitVideoPasterView alloc] initWithFrame:CGRectMake((_videoPreview.ugckit_width - width) / 2, (_videoPreview.ugckit_height - height) / 2, width, height)
  1333. theme:_theme];
  1334. pasterView.delegate = self;
  1335. [pasterView setImageList:@[info.image] imageDuration:0];
  1336. [_videoPreview addSubview:pasterView];
  1337. CGFloat percent = _duration / 10.0;
  1338. CGFloat startTime = ([self getLastPasterEndTime] == 0 ? 0 : [self getLastPasterEndTime] + percent);
  1339. if (startTime > _duration) {
  1340. startTime = 0;
  1341. }
  1342. CGFloat endTime = startTime + percent;
  1343. if(endTime > _duration){
  1344. endTime = _duration;
  1345. }
  1346. UGCKitVideoPasterInfo* pasterInfo = [[UGCKitVideoPasterInfo alloc] init];
  1347. pasterInfo.pasterView = pasterView;
  1348. pasterInfo.pasterInfoType = UGCKitPasterInfoType_static;
  1349. pasterInfo.image = info.image;
  1350. pasterInfo.iconImage = info.iconImage;
  1351. pasterInfo.startTime = startTime;
  1352. pasterInfo.endTime = endTime;
  1353. [_videoPasterInfoList addObject:pasterInfo];
  1354. [_pasterEffectArray insertObject:({
  1355. UGCKitEffectInfo * v= [UGCKitEffectInfo new];
  1356. v.name = [_theme localizedString:@"UGCKit.Edit.Paster.Static"];
  1357. v.icon = info.iconImage;
  1358. v;
  1359. }) atIndex:_pasterEffectArray.count - 1];
  1360. [_effectSelectView setEffectList:_pasterEffectArray];
  1361. _effectSelectIndex = _pasterEffectArray.count - 2;
  1362. [self setLeftPanFrame:startTime rightPanFrame:endTime];
  1363. [_ugcEdit previewAtTime:endTime];
  1364. [_videoCutView startColoration:[UIColor redColor] alpha:0.7];
  1365. }
  1366. #pragma mark VideoPasterViewDelegate
  1367. - (void)onPasterViewTap
  1368. {
  1369. }
  1370. - (void)onRemovePasterView:(UGCKitVideoPasterView*)pasterView
  1371. {
  1372. [pasterView removeFromSuperview];
  1373. [self removeCurrentPasterInfo];
  1374. }
  1375. #pragma mark VideoTextFieldDelegate
  1376. - (void)onBubbleTap
  1377. {
  1378. }
  1379. - (void)onTextInputBegin
  1380. {
  1381. _effectConfirmBtn.enabled = NO;
  1382. }
  1383. - (void)onTextInputDone:(NSString*)text
  1384. {
  1385. _effectConfirmBtn.enabled = YES;
  1386. }
  1387. - (void)onRemoveTextField:(UGCKitVideoTextFiled*)textField
  1388. {
  1389. [textField removeFromSuperview];
  1390. [self removeCurrentTextInfo];
  1391. }
  1392. #pragma mark - VideoCutViewDelegate
  1393. - (void)onVideoRangeTap:(CGFloat)tapTime
  1394. {
  1395. if (_effectSelectType == EffectSelectType_Paster) {
  1396. [self removeAllPasterViewFromSuperView];
  1397. for (UGCKitVideoPasterInfo *info in _videoPasterInfoList) {
  1398. if (tapTime >= info.startTime && tapTime <= info.endTime) {
  1399. [_videoPreview addSubview:info.pasterView];
  1400. [self setPlayBtn:NO];
  1401. [_ugcEdit previewAtTime:info.startTime];
  1402. [self setLeftPanFrame:info.startTime rightPanFrame:info.endTime];
  1403. _effectSelectIndex = [_videoPasterInfoList indexOfObject:info];
  1404. break;
  1405. }
  1406. }
  1407. }
  1408. else if (_effectSelectType == EffectSelectType_Text) {
  1409. [self removeAllTextFieldFromSuperView];
  1410. for (UGCKitVideoTextInfo *info in _videoTextInfoList) {
  1411. if (tapTime >= info.startTime && tapTime <= info.endTime) {
  1412. [_videoPreview addSubview:info.textField];
  1413. [self setPlayBtn:NO];
  1414. [_ugcEdit previewAtTime:info.startTime];
  1415. [self setLeftPanFrame:info.startTime rightPanFrame:info.endTime];
  1416. _effectSelectIndex = [_videoTextInfoList indexOfObject:info];
  1417. break;
  1418. }
  1419. }
  1420. }
  1421. }
  1422. - (void)onVideoRangeLeftChanged:(UGCKitVideoRangeSlider *)sender
  1423. {
  1424. [self setPlayBtn:NO];
  1425. [_ugcEdit previewAtTime:sender.leftPos];
  1426. }
  1427. - (void)onVideoRangeLeftChangeEnded:(UGCKitVideoRangeSlider *)sender
  1428. {
  1429. if (_effectSelectType == EffectSelectType_Paster) {
  1430. UGCKitVideoPasterInfo *info = _videoPasterInfoList[_effectSelectIndex];
  1431. info.startTime = sender.leftPos;
  1432. }
  1433. else if (_effectSelectType == EffectSelectType_Text) {
  1434. UGCKitVideoTextInfo *info = _videoTextInfoList[_effectSelectIndex];
  1435. info.startTime = sender.leftPos;
  1436. }
  1437. }
  1438. - (void)onVideoRangeRightChanged:(UGCKitVideoRangeSlider *)sender
  1439. {
  1440. [self setPlayBtn:NO];
  1441. [_ugcEdit previewAtTime:sender.rightPos];
  1442. }
  1443. - (void)onVideoRangeRightChangeEnded:(UGCKitVideoRangeSlider *)sender
  1444. {
  1445. if (_effectSelectType == EffectSelectType_Paster) {
  1446. UGCKitVideoPasterInfo *info = _videoPasterInfoList[_effectSelectIndex];
  1447. info.endTime = sender.rightPos;
  1448. }
  1449. else if (_effectSelectType == EffectSelectType_Text) {
  1450. UGCKitVideoTextInfo *info = _videoTextInfoList[_effectSelectIndex];
  1451. info.endTime = sender.rightPos;
  1452. }
  1453. }
  1454. - (void)onVideoRangeCenterChanged:(UGCKitVideoRangeSlider*)sender
  1455. {
  1456. [self setPlayBtn:NO];
  1457. [_ugcEdit previewAtTime:sender.centerPos];
  1458. }
  1459. - (void)onVideoRangeCenterChangeEnded:(UGCKitVideoRangeSlider*)sender;
  1460. {
  1461. if (_timeType == TimeType_Repeat) {
  1462. TXRepeat *repeat = [[TXRepeat alloc] init];
  1463. repeat.startTime = sender.centerPos;
  1464. repeat.endTime = sender.centerPos + 0.5;
  1465. repeat.repeatTimes = 3;
  1466. [_ugcEdit setRepeatPlay:@[repeat]];
  1467. [_ugcEdit setSpeedList:nil];
  1468. }
  1469. else if (_timeType == TimeType_Speed) {
  1470. TXSpeed *speed1 =[[TXSpeed alloc] init];
  1471. speed1.startTime = sender.centerPos;;
  1472. speed1.endTime = speed1.startTime + 0.5;
  1473. speed1.speedLevel = SPEED_LEVEL_SLOW;
  1474. TXSpeed *speed2 =[[TXSpeed alloc] init];
  1475. speed2.startTime = speed1.endTime;
  1476. speed2.endTime = speed2.startTime + 0.5;
  1477. speed2.speedLevel = SPEED_LEVEL_SLOWEST;
  1478. TXSpeed *speed3 =[[TXSpeed alloc] init];
  1479. speed3.startTime = speed2.endTime;
  1480. speed3.endTime = speed3.startTime + 0.5;
  1481. speed3.speedLevel = SPEED_LEVEL_SLOW;
  1482. [_ugcEdit setSpeedList:@[speed1,speed2,speed3]];
  1483. [_ugcEdit setRepeatPlay:nil];
  1484. }
  1485. if (_isReverse) {
  1486. [self startPlayFromTime:0 toTime:sender.centerPos + 1.5];
  1487. }else{
  1488. [self startPlayFromTime:sender.centerPos toTime:_duration];
  1489. }
  1490. }
  1491. - (void)onVideoSeekChange:(UGCKitVideoRangeSlider *)sender seekToPos:(CGFloat)pos
  1492. {
  1493. _playTime = pos;
  1494. _timeLabel.text = [NSString stringWithFormat:@"%02d:%02d",(int)_playTime / 60 , (int)_playTime % 60];
  1495. [_ugcEdit previewAtTime:_playTime];
  1496. [self setPlayBtn:NO];
  1497. }
  1498. #pragma mark - TCFilterSettingViewDelegate
  1499. //美颜
  1500. - (void)onSetBeautyDepth:(float)beautyDepth WhiteningDepth:(float)whiteningDepth
  1501. {
  1502. [_ugcEdit setBeautyFilter:beautyDepth setWhiteningLevel:whiteningDepth];
  1503. }
  1504. #pragma mark TCBGMControllerListener
  1505. -(void) onBGMControllerPlay:(NSObject*) path
  1506. {
  1507. [self dismissViewControllerAnimated:YES completion:nil];
  1508. if (path == nil) {
  1509. _bottomMenu.hidden = NO;
  1510. [self resetConfirmBtn];
  1511. [self startPlayFromTime:0 toTime:_duration];
  1512. return;
  1513. }else{
  1514. _BGMPath = path;
  1515. }
  1516. __weak __typeof(self) ws = self;
  1517. if([_BGMPath isKindOfClass:[NSString class]]){
  1518. NSString* strPath = (NSString*)_BGMPath;
  1519. AVURLAsset* audioAsset = nil;
  1520. NSDictionary* dic = @{AVURLAssetPreferPreciseDurationAndTimingKey:@(YES)};
  1521. if ([strPath hasPrefix:@"http://"]) {
  1522. audioAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:strPath] options:dic];
  1523. }else {
  1524. audioAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:strPath] options:dic];
  1525. }
  1526. _BGMDuration = CMTimeGetSeconds(audioAsset.duration);
  1527. [_ugcEdit setBGM:(NSString *)_BGMPath result:^(int result) {
  1528. if (result == 0) {
  1529. [ws setBGMStartTime:0 endTime:MAXFLOAT];
  1530. }
  1531. }];
  1532. } else if([_BGMPath isKindOfClass:[AVURLAsset class]]) {
  1533. AVURLAsset* bgm = (AVURLAsset*)_BGMPath;
  1534. _BGMDuration = CMTimeGetSeconds(bgm.duration);
  1535. [_ugcEdit setBGMAsset:(AVAsset *)_BGMPath result:^(int result) {
  1536. if (result == 0) {
  1537. [ws setBGMStartTime:0 endTime:MAXFLOAT];
  1538. }
  1539. }];
  1540. }
  1541. }
  1542. - (void)setBGMStartTime:(CGFloat)startTime endTime:(CGFloat)endTime
  1543. {
  1544. if (!_BGMPath ) return;
  1545. if (endTime == MAXFLOAT) {
  1546. endTime = _BGMDuration;
  1547. }
  1548. dispatch_async(dispatch_get_main_queue(), ^{
  1549. [self->_ugcEdit setBGMStartTime:startTime endTime:endTime];
  1550. [self->_ugcEdit setBGMVolume:self->_BGMVolume];
  1551. [self->_ugcEdit setVideoVolume:self->_videoVolume];
  1552. [self startPlayFromTime:0 toTime:self->_duration];
  1553. self->_musicView.hidden = NO;
  1554. self->_bottomMenu.hidden = YES;
  1555. [self resetConfirmBtn];
  1556. });
  1557. }
  1558. #pragma mark UGCKitVideoRecordMusicViewDelegate
  1559. -(void)onBtnMusicSelected
  1560. {
  1561. [self resetVideoProgress];
  1562. UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:_bgmListVC];
  1563. [nv.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
  1564. nv.navigationBar.barTintColor = RGB(25, 29, 38);
  1565. nv.modalPresentationStyle = UIModalPresentationFullScreen;
  1566. [self presentViewController:nv animated:YES completion:nil];
  1567. [_bgmListVC loadBGMList];
  1568. }
  1569. -(void)onBtnMusicStoped
  1570. {
  1571. _BGMPath = nil;
  1572. [_ugcEdit setBGM:nil result:^(int result) {
  1573. }];
  1574. _musicView.hidden = YES;
  1575. _bottomMenu.hidden = NO;
  1576. [self resetConfirmBtn];
  1577. [self startPlayFromTime:0 toTime:_duration];
  1578. }
  1579. -(void)onBGMValueChange:(CGFloat)percent
  1580. {
  1581. _BGMVolume = 1.0 * percent;
  1582. [_ugcEdit setBGMVolume:_BGMVolume];
  1583. }
  1584. -(void)onVoiceValueChange:(CGFloat)percent
  1585. {
  1586. _videoVolume = 1.0 * percent;
  1587. [_ugcEdit setVideoVolume:_videoVolume];
  1588. }
  1589. -(void)onBGMRangeChange:(CGFloat)startPercent endPercent:(CGFloat)endPercent
  1590. {
  1591. [self setBGMStartTime:_BGMDuration * startPercent endTime:_BGMDuration * endPercent];
  1592. }
  1593. #pragma mark - Utils
  1594. - (void)checkVideoOutputPath
  1595. {
  1596. NSFileManager *manager = [[NSFileManager alloc] init];
  1597. if ([manager fileExistsAtPath:_videoOutputPath]) {
  1598. BOOL success = [manager removeItemAtPath:_videoOutputPath error:nil];
  1599. if (success) {
  1600. NSLog(@"Already exist. Removed!");
  1601. }
  1602. }
  1603. }
  1604. - (float) heightForString:(UITextView *)textView andWidth:(float)width{
  1605. CGSize sizeToFit = [textView sizeThatFits:CGSizeMake(width, MAXFLOAT)];
  1606. return sizeToFit.height;
  1607. }
  1608. - (void) toastTip:(NSString*)toastInfo
  1609. {
  1610. CGRect frameRC = [[UIScreen mainScreen] bounds];
  1611. frameRC.origin.y = frameRC.size.height - 110;
  1612. frameRC.size.height -= 110;
  1613. __block UITextView * toastView = [[UITextView alloc] init];
  1614. toastView.editable = NO;
  1615. toastView.selectable = NO;
  1616. frameRC.size.height = [self heightForString:toastView andWidth:frameRC.size.width];
  1617. toastView.frame = frameRC;
  1618. toastView.text = toastInfo;
  1619. toastView.backgroundColor = [UIColor whiteColor];
  1620. toastView.alpha = 0.5;
  1621. [self.view addSubview:toastView];
  1622. dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
  1623. dispatch_after(popTime, dispatch_get_main_queue(), ^(){
  1624. [toastView removeFromSuperview];
  1625. toastView = nil;
  1626. });
  1627. }
  1628. -(NSString *)getCoverPath:(UIImage *)coverImage
  1629. {
  1630. UIImage *image = coverImage;
  1631. if (image == nil) {
  1632. return nil;
  1633. }
  1634. NSString *coverPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"TXUGC"];
  1635. coverPath = [coverPath stringByAppendingPathComponent:[self getFileNameByTimeNow:@"TXUGC" fileType:@"jpg"]];
  1636. if (coverPath) {
  1637. // 保证目录存在
  1638. [[NSFileManager defaultManager] createDirectoryAtPath:[coverPath stringByDeletingLastPathComponent]
  1639. withIntermediateDirectories:YES
  1640. attributes:nil
  1641. error:nil];
  1642. [UIImageJPEGRepresentation(image, 1.0) writeToFile:coverPath atomically:YES];
  1643. }
  1644. return coverPath;
  1645. }
  1646. -(NSString *)getFileNameByTimeNow:(NSString *)type fileType:(NSString *)fileType {
  1647. NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
  1648. NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
  1649. [formatter setDateFormat:@"yyyyMMdd_HHmmss"];
  1650. NSDate * NowDate = [NSDate dateWithTimeIntervalSince1970:now];
  1651. ;
  1652. NSString * timeStr = [formatter stringFromDate:NowDate];
  1653. NSString *fileName = ((fileType == nil) ||
  1654. (fileType.length == 0)
  1655. ) ? [NSString stringWithFormat:@"%@_%@",type,timeStr] : [NSString stringWithFormat:@"%@_%@.%@",type,timeStr,fileType];
  1656. return fileName;
  1657. }
  1658. - (void)dealloc
  1659. {
  1660. [_videoPreview removeNotification];
  1661. _videoPreview = nil;
  1662. }
  1663. @end
  1664. @implementation UGCKitEditConfig
  1665. - (instancetype)init {
  1666. if (self = [super init]) {
  1667. _rotation = TCEditRotation0;
  1668. _videoBitrate = -1; // auto
  1669. _compressResolution = VIDEO_COMPRESSED_720P;
  1670. }
  1671. return self;
  1672. }
  1673. @end