| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944 |
- // Copyright (c) 2019 Tencent. All rights reserved.
- #import "UGCKitRecordViewController.h"
- #import <MediaPlayer/MediaPlayer.h>
- #import <TCBeautyPanel/TCBeautyPanel.h>
- #import "SDKHeader.h"
- #import "UGCKitMem.h"
- #import "UGCKitMediaPickerViewController.h"
- #import "UGCKitEditViewController.h"
- #import "UGCKitVideoRecordMusicView.h"
- #import "UGCKitVideoRecordProcessView.h"
- #import "UGCKitProgressHUD.h"
- #import "UGCKitBGMListViewController.h"
- #import "UGCKitAudioEffectPanel.h"
- #import "UGCKitLabel.h"
- #import "UGCKitTheme.h"
- #import "UGCKitSlideButton.h"
- #import "UGCKitRecordControlView.h"
- #import "UGCKitSmallButton.h"
- #import "UGCKit_UIViewAdditions.h"
- #import "UGCKitConstants.h"
- #import <objc/runtime.h>
- #import "UGCKitReporterInternal.h"
- #import "SDKHeader.h"
- static const CGFloat BUTTON_CONTROL_SIZE = 40;
- static const CGFloat AudioEffectViewHeight = 150;
- typedef NS_ENUM(NSInteger, CaptureMode) {
- CaptureModeStill,
- CaptureModeTap,
- CaptureModePress
- };
- typedef NS_ENUM(NSInteger, RecordState) {
- RecordStateStopped,
- RecordStateRecording,
- RecordStatePaused
- };
- #if POD_PITU
- #import "MCCameraDynamicView.h"
- #import "MaterialManager.h"
- #import "MCTip.h"
- #endif
- @interface UGCKitRecordPreviewController : NSObject
- @property (nonatomic, strong, readonly) NSArray<NSNumber *> *allVideoVolumes;
- @property (nonatomic, strong, readonly) NSArray<NSString *> *allVideoPaths;
- @property (nonatomic, strong, readonly) NSString *recordVideoPath;
- @property (nonatomic, strong, readonly) UIView *videoRecordView;
- - (instancetype)initWithContainerView:(UIView *)containerView
- recordStyle:(UGCKitRecordStyle)recordStyle
- chorusVideos:(NSArray<NSString *> *)chorusVideos
- recordVideo:(NSString *)recordVideo;
- - (void)changeChorusVideo:(NSString *)videoPath;
- - (void)startPlayChorusVideos:(CGFloat)startTime
- toTime:(CGFloat)endTime;
- - (void)stopPlayChorusVideos;
- - (void)seekChorusVideosToTime:(CGFloat)time;
- @end
- @interface UGCKitNavControllerPrivate : UINavigationController
- @property (nonatomic, assign) UIInterfaceOrientationMask supportedOrientations;
- @end
- @interface UGCKitRecordViewController()
- <TXUGCRecordListener, UIGestureRecognizerDelegate,
- MPMediaPickerControllerDelegate,TCBGMControllerListener,TXVideoJoinerListener,
- UGCKitVideoRecordMusicViewDelegate, UGCKitAudioEffectPanelDelegate, BeautyLoadPituDelegate
- #if POD_PITU
- , MCCameraDynamicDelegate
- #endif
- >
- {
- UGCKitRecordConfig *_config; // 录制配置
- UGCKitTheme *_theme; // 主题配置
- UGCKitRecordControlView *_controlView; // 界面控件覆盖层
- RecordState _recordState; // 录制状态
- NSString *_coverPath; // 保存路径, 视频为<_coverPath>.mp4结尾, 封面图为<_coverPath>.png
- BOOL _isFrontCamera;
- BOOL _vBeautyShow;
- BOOL _preloadingVideos;
- // Chorus
- TXVideoBeautyStyle _beautyStyle;
- float _beautyDepth;
- float _whitenDepth;
- float _ruddinessDepth;
- float _eye_level;
- float _face_level;
-
- BOOL _isCameraPreviewOn;
- // BOOL _videoRecording;
- CGFloat _currentRecordTime;
-
- UGCKitAudioEffectPanel *_soundMixView;
-
- BOOL _navigationBarHidden;
- BOOL _appForeground;
- // BOOL _isPaused;
-
- // 倒计时
- UILabel *_countDownLabel;
- UIView *_countDownView;
- NSTimer *_countDownTimer;
- #if POD_PITU
- MCCameraDynamicView *_tmplBar;
- NSString *_materialID;
- #else
- UIView *_tmplBar;
- #endif
- UGCKitBGMListViewController* _bgmListVC;
- NSObject* _BGMPath;
- CGFloat _BGMDuration;
- CGFloat _recordTime;
-
- int _deleteCount;
- float _zoom;
- BOOL _isBackDelete;
- BOOL _isFlash;
-
- UGCKitVideoRecordMusicView * _musicView;
- SpeedMode _speedMode;
-
- TCBeautyPanel * _vBeauty;
- UGCKitProgressHUD* _hud;
- CGFloat _bgmBeginTime;
- BOOL _bgmRecording;
-
- TXVideoJoiner * _videoJoiner;
- NSString * _joinVideoPath;
- TXVideoVoiceChangerType _voiceChangerType; // 变声参数
- TXVideoReverbType _revertType; // 混音参数
- }
- @property (strong, nonatomic) IBOutlet UIButton *btnNext;
- @property (strong, nonatomic) IBOutlet UIView *captureModeView;
- @property (strong, nonatomic) IBOutlet UIButton *btnChangeVideo;
- @property (assign, nonatomic) CaptureMode captureMode;
- @property (strong, nonatomic) UGCKitRecordPreviewController *previewController;
- @end
- @implementation UGCKitRecordViewController
- - (instancetype)initWithConfig:(UGCKitRecordConfig *)config theme:(UGCKitTheme *)theme
- {
- if (self = [super initWithNibName:nil bundle:nil]) {
- _config = config ?: [[UGCKitRecordConfig alloc] init];
- _theme = theme ?: [UGCKitTheme sharedTheme];
- _preloadingVideos = _config.recoverDraft;
- [[TXUGCRecord shareInstance] setAspectRatio:_config.ratio];
- _coverPath = [NSTemporaryDirectory() stringByAppendingString:[[NSUUID UUID] UUIDString]];
- [self _commonInit];
- }
- return self;
- }
- -(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self)
- {
- _config = [[UGCKitRecordConfig alloc] init];
- _theme = [UGCKitTheme sharedTheme];
- [self _commonInit];
- }
- return self;
- }
- - (void)_commonInit {
- _appForeground = YES;
- _isFrontCamera = YES;
- _vBeautyShow = NO;
- _beautyStyle = VIDOE_BEAUTY_STYLE_SMOOTH;
- _beautyDepth = 6.3;
- _whitenDepth = 2.7;
- _isCameraPreviewOn = NO;
- _recordState = RecordStateStopped;
- _currentRecordTime = 0;
- _speedMode = SpeedMode_Standard;
- _voiceChangerType = VIDOE_VOICECHANGER_TYPE_0; // 无变声
- _revertType = VIDOE_REVERB_TYPE_0; // 无混音效果
- [TXUGCRecord shareInstance].recordDelegate = self;
- _bgmListVC = [[UGCKitBGMListViewController alloc] initWithTheme:_theme];
- [_bgmListVC setBGMControllerListener:self];
- _joinVideoPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"outputJoin.mp4"];
- self.captureMode = CaptureModeTap;
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- }
- -(void)viewDidLoad
- {
- [super viewDidLoad];
- [self initUI];
- [self initBeautyUI];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(onAudioSessionEvent:)
- name:AVAudioSessionInterruptionNotification
- object:nil];
- }
- - (void)viewWillAppear:(BOOL)animated{
- [super viewWillAppear:animated];
-
- _navigationBarHidden = self.navigationController.navigationBar.hidden;
- self.navigationController.navigationBar.hidden = YES;
- if (_isCameraPreviewOn == NO) {
- [self startCameraPreview];
- }else{
- //停止特效的声音
- [[[TXUGCRecord shareInstance] getBeautyManager] setMotionMute:NO];
- }
- // 恢复变声与混音效果
- if (_voiceChangerType >= 0) {
- [[TXUGCRecord shareInstance] setVoiceChangerType:_voiceChangerType];
- }
- if (_revertType >= 0) {
- [[TXUGCRecord shareInstance] setReverbType:_revertType];
- }
- }
- - (void)viewWillDisappear:(BOOL)animated
- {
- [super viewWillDisappear:animated];
- self.navigationController.navigationBar.hidden = _navigationBarHidden;
- }
- - (void)viewDidDisappear:(BOOL)animated
- {
- [super viewDidDisappear:animated];
-
- [self stopCameraPreview];
- }
- - (UIStatusBarStyle)preferredStatusBarStyle
- {
- return UIStatusBarStyleLightContent;
- }
- #pragma mark - Notification Handler
- - (void)onAudioSessionEvent:(NSNotification*)notification
- {
- NSDictionary *info = notification.userInfo;
- AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
- if (type == AVAudioSessionInterruptionTypeBegan) {
- // 在10.3及以上的系统上,分享跳其它app后再回来会收到AVAudioSessionInterruptionWasSuspendedKey的通知,不处理这个事件。
- if ([info objectForKey:@"AVAudioSessionInterruptionWasSuspendedKey"]) {
- return;
- }
- _appForeground = NO;
- if (_recordState == RecordStateRecording) {
- [self pauseRecord];
- }
- }else{
- AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
- if (options == AVAudioSessionInterruptionOptionShouldResume) {
- _appForeground = YES;
- }
- }
- }
- - (void)onAppWillResignActive:(NSNotification*)notification
- {
- _appForeground = NO;
- if (_recordState == RecordStateRecording) {
- [self pauseRecord];
- }
- }
- - (void)onAppDidBecomeActive:(NSNotification*)notification
- {
- [[TXUGCRecord shareInstance] resumeAudioSession];
- _appForeground = YES;
- }
- #pragma mark - UI Setup
- -(void)initUI
- {
- self.title = @"";
- self.view.backgroundColor = _theme.backgroundColor;
-
- if (0 == _config.chorusVideos.count
- && UGCKitRecordStyleRecord != _config.recordStyle) {
- _config.recordStyle = UGCKitRecordStyleRecord;
- }
- else if (_config.chorusVideos.count < 2
- && UGCKitRecordStyleTrio == _config.recordStyle) {
- _config.chorusVideos = @[_config.chorusVideos.firstObject,
- _config.chorusVideos.firstObject];
- }
- // 视频界面
- UIView *videoContainer = [[UIView alloc] initWithFrame:self.view.bounds];
- videoContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight;
- [self.view addSubview:videoContainer];
-
- NSString *recordVideoPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"outputRecord.mp4"];
- _previewController = [[UGCKitRecordPreviewController alloc] initWithContainerView:videoContainer
- recordStyle:_config.recordStyle
- chorusVideos:_config.chorusVideos
- recordVideo:recordVideoPath];
- CGFloat top = [UIApplication sharedApplication].statusBarFrame.size.height + 25;
- CGFloat centerY = top;
-
- UIButton *(^allocButtonBlock)(UIImage *, SEL, NSString *) = ^(UIImage *bgImage, SEL action, NSString *title) {
- UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
- button.bounds = CGRectMake(0, 0, BUTTON_CONTROL_SIZE, BUTTON_CONTROL_SIZE);
- button.titleLabel.font = [UIFont systemFontOfSize:12];
- [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
- [button setTitleColor:self->_theme.titleColor forState:UIControlStateNormal];
- [button setBackgroundImage:bgImage forState:UIControlStateNormal];
- [button setTitle:title forState:UIControlStateNormal];
- return button;
- };
- // “下一步”按钮
- _btnNext = allocButtonBlock(_theme.nextIcon, @selector(onNext:), [_theme localizedString:@"UGCKit.Common.Next"]);
- _btnNext.hidden = YES;
- [_btnNext sizeToFit];
- _btnNext.center = CGPointMake(CGRectGetWidth(self.view.bounds) - 10 - CGRectGetWidth(_btnNext.frame) / 2 , centerY);
- [self.view addSubview:_btnNext];
- // "更换视频"按钮
- _btnChangeVideo = allocButtonBlock(_theme.editChooseVideoIcon, @selector(onChangeVideo:), [_theme localizedString:@"UGCKit.Common.Choose"]);
- _btnChangeVideo.bounds = CGRectMake(0, 0, 70, 30);
- _btnChangeVideo.center = _btnNext.center;
- _btnChangeVideo.hidden = YES;
- [self.view addSubview:_btnChangeVideo];
- // 主界面控件浮层
- _controlView = [[UGCKitRecordControlView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_btnNext.frame)+30,
- CGRectGetWidth(self.view.bounds),
- CGRectGetHeight(self.view.bounds) - CGRectGetMaxY(_btnNext.frame)-30)
- minDuration:_config.minDuration
- maxDuration:_config.maxDuration];
- _controlView.theme = _theme;
- _controlView.speedControlEnabled = UGCKitRecordStyleRecord == _config.recordStyle;
- #if UGC_SMART
- _controlView.musicButtonEnabled = NO;
- _controlView.speedControlEnabled = NO;
- #endif
- _controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- [_controlView setupViews];
- [self.view addSubview:_controlView];
- // 后退按钮
- UIButton *btnBack = [UGCKitSmallButton buttonWithType:UIButtonTypeCustom];
- btnBack.bounds = CGRectMake(0, 0, BUTTON_CONTROL_SIZE, BUTTON_CONTROL_SIZE);
- btnBack.center = CGPointMake(17, centerY);
- [btnBack setImage:_theme.backIcon forState:UIControlStateNormal];
- [btnBack addTarget:self action:@selector(onTapBackButton:) forControlEvents:UIControlEventTouchUpInside];
- [self.view addSubview:btnBack];
- // 比例按钮配置
- _controlView.videoRatio = _config.ratio;
-
- // 事件绑定
- [_controlView.btnMusic addTarget:self action:@selector(onBtnMusicClicked:) forControlEvents:UIControlEventTouchUpInside];
- [_controlView.btnRatioGroup addTarget:self action:@selector(onBtnRatioClicked:) forControlEvents:UIControlEventValueChanged];
- [_controlView.btnBeauty addTarget:self action:@selector(onBtnBeautyClicked:) forControlEvents:UIControlEventTouchUpInside];
- [_controlView.btnAudioEffect addTarget:self action:@selector(onBtnAudioMix:) forControlEvents:UIControlEventTouchUpInside];
- [_controlView.btnStartRecord addTarget:self action:@selector(onRecordButtonTouchDown:) forControlEvents:UIControlEventTouchDown];
- [_controlView.btnStartRecord addTarget:self action:@selector(onRecordButtonTouchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
- [_controlView.btnFlash addTarget:self action:@selector(onTapTorchButton) forControlEvents:UIControlEventTouchUpInside];
- [_controlView.btnCamera addTarget:self action:@selector(onTapCameraSwitch) forControlEvents:UIControlEventTouchUpInside];
- [_controlView.btnDelete addTarget:self action:@selector(onBtnDeleteClicked) forControlEvents:UIControlEventTouchUpInside];
- [_controlView.btnCountDown addTarget:self action:@selector(onCountDown:) forControlEvents:UIControlEventTouchUpInside];
- for (UIButton *button in _controlView.speedBtnList) {
- [button addTarget:self action:@selector(onBtnSpeedClicked:) forControlEvents:UIControlEventTouchUpInside];
- }
- [_controlView.recordButtonSwitchControl addTarget:self action:@selector(onTapCaptureMode:) forControlEvents:UIControlEventValueChanged];
- UIPinchGestureRecognizer* pinchGensture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPInchZoom:)];
- [self.view addGestureRecognizer:pinchGensture];
- // 滑动滤镜
- UIPanGestureRecognizer* panGensture = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector (onPanSlideFilter:)];
- panGensture.delegate = self;
- [self.view addGestureRecognizer:panGensture];
-
- if (UGCKitRecordStyleDuet == _config.recordStyle) { // 分屏合拍
- videoContainer.frame = CGRectMake(0, CGRectGetMaxY(_btnNext.frame) + 20,
- CGRectGetWidth(self.view.bounds),
- CGRectGetHeight(self.view.bounds) / 2);
- }
- [self refreshChrousUI];
- [self refreshRecordDuration];
- }
- - (void)refreshChrousUI
- {
- if (UGCKitRecordStyleRecord == _config.recordStyle) return;
-
- // 合唱
- _controlView.speedControlEnabled = NO;
- _controlView.photoModeEnabled = NO;
- _controlView.progressView.minimumTimeTipHidden = YES;
- _controlView.btnRatioGroup.hidden = YES;
- _controlView.btnMusic.hidden = YES;
- _controlView.btnAudioEffect.hidden = YES;
- _controlView.btnBeauty.frame = _controlView.btnMusic.frame;
- CGRect countDownFrame = _controlView.btnCountDown.frame;
- countDownFrame.origin.y = CGRectGetMinY(_controlView.btnRatioGroup.frame);
- _controlView.btnCountDown.frame = countDownFrame;
- _controlView.countDownModeEnabled = YES;
- _btnChangeVideo.hidden = NO;
-
- //用于模仿视频和录制视频的合成
- _videoJoiner = [[TXVideoJoiner alloc] initWithPreview:nil];
- _videoJoiner.joinerDelegate = self;
- }
- - (void)refreshRecordDuration
- {
- if (UGCKitRecordStyleRecord == _config.recordStyle) return;
-
- TXVideoInfo *info = nil;
- for (NSString *videoPath in _config.chorusVideos) {
- TXVideoInfo *videoInfo = [TXVideoInfoReader getVideoInfo:videoPath];
- if (!info || videoInfo.duration < info.duration) {
- info = videoInfo;
- }
- }
- _config.minDuration = info.duration;
- _config.maxDuration = info.duration;
-
- [_controlView setMinDuration:info.duration maxDuration:info.duration];
- }
- #pragma mark - UI LazyLoaders
- - (UGCKitAudioEffectPanel *)soundMixView {
- if (_soundMixView) {
- return _soundMixView;
- }
- _soundMixView = [[UGCKitAudioEffectPanel alloc] initWithTheme:_theme
- frame:CGRectMake(0, CGRectGetHeight(self.view.bounds)-AudioEffectViewHeight,
- CGRectGetWidth(self.view.bounds), AudioEffectViewHeight)];
- _soundMixView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
- _soundMixView.delegate = self;
- [self.view addSubview:_soundMixView];
- _soundMixView.hidden = YES;
- return _soundMixView;
- }
- - (UGCKitVideoRecordMusicView *)musicView {
- if (_musicView) {
- return _musicView;
- }
- _musicView = [[UGCKitVideoRecordMusicView alloc] initWithFrame:CGRectMake(0, self.view.ugckit_bottom - 330 * kScaleY, self.view.ugckit_width, 330 * kScaleY) needEffect:YES theme:_theme];
- _musicView.delegate = self;
- _musicView.hidden = YES;
- [self.view addSubview:_musicView];
- _musicView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
- return _musicView;
- }
- #pragma mark ---- Video Beauty UI ----
- -(void)initBeautyUI
- {
- NSUInteger controlHeight = [ TCBeautyPanel getHeight];
- CGFloat offset = 0;
- if (@available(iOS 11, *)) {
- offset = [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
- }
- _vBeauty = [TCBeautyPanel beautyPanelWithFrame:CGRectMake(0, self.view.frame.size.height - controlHeight - offset,
- self.view.frame.size.width, controlHeight)
- theme:_theme
- SDKObject:[TXUGCRecord shareInstance]];
- _vBeauty.hidden = YES;
- _vBeauty.pituDelegate = self;
- _vBeauty.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
- [self.view addSubview:_vBeauty];
- }
- - (void)setSelectedSpeed:(SpeedMode)tag
- {
- [_controlView setSelectedSpeed:tag];
- }
- -(void)setSpeedBtnHidden:(BOOL)hidden{
- if (UGCKitRecordStyleRecord != _config.recordStyle) hidden = YES;
- _controlView.speedControlEnabled = !hidden;
- }
- #pragma mark - Actions
- - (void)takePhoto {
- [[TXUGCRecord shareInstance] snapshot:^(UIImage *image) {
- dispatch_async(dispatch_get_main_queue(), ^{
- UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
- UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), (__bridge void*)imageView);
- imageView.contentMode = UIViewContentModeScaleAspectFit;
- imageView.frame = self.view.bounds;
- [self.view insertSubview:imageView belowSubview:self->_controlView.bottomMask];
-
- CGAffineTransform t = CGAffineTransformMakeScale(0.33, 0.33);
- [UIView animateWithDuration:0.3 animations:^{
- imageView.transform = t;
- } completion:nil];
- });
- }];
- }
- -(IBAction)onTapBackButton:(id)sender
- {
- __weak __typeof(self) wself = self;
- [self pauseRecord:^{
- [wself _goBack];
- }];
- }
- - (void)_goBack {
- NSArray *videoPaths = [[TXUGCRecord shareInstance].partsManager getVideoPathList];
- if (videoPaths.count > 0) {
- UIAlertController *controller = [UIAlertController alertControllerWithTitle:[_theme localizedString:@"UGCKit.Record.AbandonRecord"]
- message:nil
- preferredStyle:UIAlertControllerStyleAlert];
- [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.OK"]
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction * _Nonnull action) {
- [[NSUserDefaults standardUserDefaults] setObject:nil forKey:CACHE_PATH_LIST];
- if (self.completion) {
- self.completion([UGCKitResult cancelledResult]);
- }
- }]];
- [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.Cancel"] style:UIAlertActionStyleCancel handler:nil]];
- [self presentViewController:controller animated:YES completion:nil];
- }else{
- [[NSUserDefaults standardUserDefaults] setObject:nil forKey:CACHE_PATH_LIST];
- if (self.completion) {
- self.completion([UGCKitResult cancelledResult]);
- }
- }
- }
- -(IBAction)onTapTorchButton
- {
- _isFlash = !_isFlash;
- _controlView.torchOn = _isFlash;
- [[TXUGCRecord shareInstance] toggleTorch:_isFlash];
- }
- - (IBAction)onNext:(UIButton *)sender
- {
- self.captureModeView.userInteractionEnabled = YES;
- _controlView.btnCountDown.enabled = YES;
- _controlView.recordButtonSwitchControl.enabled = YES;
-
- if (_captureMode != CaptureModePress) {
- [_controlView setRecordButtonStyle:UGCKitRecordButtonStyleRecord];
- }
- _controlView.controlButtonsHidden = NO;
- if (UGCKitRecordStyleRecord != _config.recordStyle) {
- _controlView.btnMusic.hidden = YES;
- _controlView.btnRatioGroup.hidden = YES;
- _controlView.btnAudioEffect.hidden = YES;
- }
-
- [self _finishRecord];
- }
- - (void)_finishRecord {
- UIButton *nextButton = _btnNext;
- nextButton.hidden = YES;
- [self stopRecordAndComplete:^(int result){
- nextButton.hidden = NO;
- }];
-
-
-
- }
- - (IBAction)onChangeVideo:(UIButton *)sender
- {
- UGCKitMediaPickerConfig *config = [[UGCKitMediaPickerConfig alloc] init];
- config.mediaType = UGCKitMediaTypeVideo;
- config.maxItemCount = 1;
-
- UGCKitMediaPickerViewController *pickerController = [[UGCKitMediaPickerViewController alloc] initWithConfig:config theme:_theme];
- UGCKitNavControllerPrivate *navController = [[UGCKitNavControllerPrivate alloc] initWithRootViewController:pickerController];
- navController.supportedOrientations = self.supportedInterfaceOrientations;
- navController.modalPresentationStyle = UIModalPresentationFullScreen;
- WEAKIFY(self);
- pickerController.completion = ^(UGCKitResult *result) {
- if (!result.cancelled && result.code == 0) {
- [weak_self doChangeVideo:result];
- } else {
- NSLog(@"isCancelled: %c, failed: %@", result.cancelled ? 'y' : 'n', result.info[NSLocalizedDescriptionKey]);
- }
- [weak_self dismissViewControllerAnimated:YES completion:nil];
- };
- [self presentViewController:navController animated:YES completion:NULL];
- }
- - (void)doChangeVideo:(UGCKitResult *)result
- {
- if (![result.media.videoAsset isKindOfClass:[AVURLAsset class]]) return;
-
- NSString *videoPath = ((AVURLAsset *)result.media.videoAsset).URL.path;
- if (!videoPath) {
- videoPath = @"";
- }
- [self.previewController changeChorusVideo:videoPath];
-
- if (UGCKitRecordStyleDuet == _config.recordStyle) {
- _config.chorusVideos = @[videoPath];
- } else if (UGCKitRecordStyleTrio == _config.recordStyle) {
- _config.chorusVideos = @[videoPath, videoPath];
- }
- [self refreshRecordDuration];
- }
- - (IBAction)onBtnMusicClicked:(id)sender
- {
- _vBeauty.hidden = YES;
- UIView *musicView = [self musicView];
- if (_BGMPath) {
- musicView.hidden = !musicView.hidden;
- [self hideBottomView:!musicView.hidden];
- }else{
- UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:_bgmListVC];
- [nv.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:_theme.titleColor}];
- nv.navigationBar.barTintColor = _theme.backgroundColor;
- nv.modalPresentationStyle = UIModalPresentationFullScreen;
- [self presentViewController:nv animated:YES completion:nil];
- [_bgmListVC loadBGMList];
- }
- }
- - (IBAction)onBtnRatioClicked:(UGCKitSlideButton *)sender
- {
- TXVideoAspectRatio ratio = sender.buttons[sender.selectedIndex].tag;;
- [self _switchToRatio:ratio];
- }
- -(void)onBtnSpeedClicked:(UIButton *)btn
- {
- [UIView animateWithDuration:0.3 animations:^{
- self->_speedMode = btn.tag;
- [self setSelectedSpeed:self->_speedMode];
- }];
- }
- -(IBAction)onBtnDeleteClicked
- {
- if (_recordState == RecordStateRecording) {
- [self pauseRecord];
- }
- if (0 == [TXUGCRecord shareInstance].partsManager.getVideoPathList.count) {
- return;
- }
-
- if (0 == _deleteCount) {
- [_controlView.progressView prepareDeletePart];
- }else{
- [_controlView.progressView comfirmDeletePart];
- [[TXUGCRecord shareInstance].partsManager deleteLastPart];
- _isBackDelete = YES;
- }
- if (2 == ++ _deleteCount) {
- _deleteCount = 0;
- }
- }
- - (IBAction)onBtnAudioMix:(id)sender {
- [self hideBottomView:YES];
- UGCKitAudioEffectPanel *soundMixView = [self soundMixView];
- soundMixView.hidden = NO;
- _vBeauty.hidden = YES;
- _musicView.hidden = YES;
- CATransition *animation = [CATransition animation];
- animation.type = kCATransitionFade;
- [soundMixView.layer addAnimation:animation forKey:nil];
- }
- - (IBAction)onCountDown:(id)sender {
- [self hideBottomView:YES];
- [self startCountDown];
- }
- -(IBAction)onBtnBeautyClicked:(id)sender
- {
- _vBeautyShow = !_vBeautyShow;
- _musicView.hidden = YES;
- _vBeauty.hidden = !_vBeautyShow;
- [self hideBottomView:_vBeautyShow];
- }
- -(IBAction)onTapCameraSwitch
- {
- _isFrontCamera = !_isFrontCamera;
- [[TXUGCRecord shareInstance] switchCamera:_isFrontCamera];
- _controlView.isFrontCamera = _isFrontCamera;
- if (_isFrontCamera) {
- _isFlash = NO;
- _controlView.torchOn = NO;
- }
- [[TXUGCRecord shareInstance] toggleTorch:_isFlash];
- }
- - (IBAction)onTapCaptureMode:(UGCKitSlideOptionControl *)control
- {
- CaptureMode mode = (CaptureMode)control.selectedIndex;
- [UIView animateWithDuration:0.1 animations:^{
- [self->_controlView setRecordButtonStyle:(UGCKitRecordButtonStyle)mode];
- }];
- self.captureMode = mode;
- }
- - (void)_configButtonToPause {
- _controlView.controlButtonsHidden = YES;
- [_controlView setRecordButtonStyle:UGCKitRecordButtonStylePause];
- }
- #pragma mark - Count Down
- - (void)startCountDown {
- if (_countDownTimer) {
- return;
- }
-
- if (_countDownView == nil) {
- UIVisualEffectView *view = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle: UIBlurEffectStyleExtraLight]];
- view.layer.cornerRadius = 20;
- view.clipsToBounds = YES;
-
- view.translatesAutoresizingMaskIntoConstraints = NO;
- UILabel *countDownLabel = [[UILabel alloc] init];
- countDownLabel.translatesAutoresizingMaskIntoConstraints = NO;
- countDownLabel.textColor = [UIColor colorWithWhite:0.33 alpha:1];
- countDownLabel.font = [UIFont systemFontOfSize:100];
-
- [view.contentView addSubview:countDownLabel];
- [view.contentView addConstraint:[NSLayoutConstraint constraintWithItem:view.contentView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:countDownLabel attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
- [view.contentView addConstraint:[NSLayoutConstraint constraintWithItem:view.contentView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:countDownLabel attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
- [view addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:150]];
- [view addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:150]];
-
- [self.view addSubview:view];
- [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
- [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
-
-
- _countDownView = view;
- _countDownLabel = countDownLabel;
- }
- _countDownView.hidden = NO;
- _countDownLabel.text = @"3";
- _countDownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(onCountDownTimer:) userInfo:nil repeats:YES];
- _countDownView.hidden = NO;
- }
- - (void)onCountDownTimer:(NSTimer *)timer {
- if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
- return;
- }
- int count = _countDownLabel.text.intValue - 1;
- _countDownLabel.text = @(count).stringValue;
- if (count == 0) {
- [_countDownTimer invalidate];
- _countDownTimer = nil;
- _countDownView.hidden = YES;
- _controlView.recordButtonStyle = UGCKitRecordButtonStylePause;
- _controlView.recordButtonSwitchControl.selectedIndex = CaptureModeTap;
- self.captureMode = CaptureModeTap;
- [self startRecord];
- [self hideBottomView:NO];
- }
- }
- #pragma mark - Control Visibility
- #pragma mark - Properties
- -(void)syncSpeedRateToSDK{
- switch (_speedMode) {
- case SpeedMode_VerySlow:
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_SLOWEST];
- break;
- case SpeedMode_Slow:
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_SLOW];
- break;
- case SpeedMode_Standard:
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_NOMAL];
- break;
- case SpeedMode_Quick:
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_FAST];
- break;
- case SpeedMode_VeryQuick:
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_FASTEST];
- break;
- default:
- break;
- }
- }
- #pragma mark - Right Side Button Event Handler
- - (void)_switchToRatio:(TXVideoAspectRatio)ratio;
- {
- _config.ratio = ratio;
- [_controlView setVideoRatio:ratio];
- [[TXUGCRecord shareInstance] setAspectRatio:_config.ratio];
- }
- #pragma mark - Record Control
- -(void)startSDKRecord
- {
- _controlView.btnCountDown.enabled = NO;
- [self startCameraPreview];
- [self syncSpeedRateToSDK];
- int result = [[TXUGCRecord shareInstance] startRecord:[_coverPath stringByAppendingString:@".mp4"]
- coverPath:[_coverPath stringByAppendingString:@".png"]];
- [UGCKitReporter report:UGCKitReportItem_startrecord userName:nil code:result msg:result == 0 ? ASLocalizedString(@"启动录制成功"): ASLocalizedString(@"启动录制失败")];
- if(0 != result)
- {
- if(-3 == result) [self alert:[_theme localizedString:@"UGCKit.Record.HintLaunchRecordFailed"] msg:[_theme localizedString:@"UGCKit.Record.ErrorCamera"]];
- if(-4 == result) [self alert:[_theme localizedString:@"UGCKit.Record.HintLaunchRecordFailed"] msg:[_theme localizedString:@"UGCKit.Record.ErrorMIC"]];
- if(-5 == result) [self alert:[_theme localizedString:@"UGCKit.Record.HintLaunchRecordFailed"] msg:[_theme localizedString:@"UGCKit.Record.ErrorLicense"]];
- }else{
- //如果设置了BGM,播放BGM
- [self playBGM:_bgmBeginTime];
- //初始化录制状态
- _recordState = RecordStateRecording;
- _bgmRecording = YES;
- _controlView.recordButtonSwitchControl.enabled = NO;
- //录制过程中不能切换分辨率,不能切换拍照模式
- _controlView.btnRatioGroup.enabled = NO;
- [_controlView.btnRatioGroup shrink];
- self.captureModeView.userInteractionEnabled = NO;
- [self setSpeedBtnHidden:YES];
- [self _configButtonToPause];
- if (UGCKitRecordStyleRecord != _config.recordStyle) {
- [self.previewController startPlayChorusVideos:_recordTime
- toTime:_config.maxDuration];
- }
- }
- }
- - (void)_pauseAndAddMark:(void(^)(void))completion {
- NSUInteger countBefore = [TXUGCRecord shareInstance].partsManager.getVideoPathList.count;
- UGCKitRecordControlView *controlView = _controlView;
- void (^afterPause)(void)= ^{
- NSUInteger count = [TXUGCRecord shareInstance].partsManager.getVideoPathList.count;
- if (count != countBefore) {
- [controlView.progressView pause];
- }
- if (completion) {
- completion();
- }
- };
- if ([[TXUGCRecord shareInstance] pauseRecord:afterPause] < 0) {
- afterPause();
- }
- }
- - (void)pauseRecord {
- [self pauseRecord:nil];
- }
- - (void)pauseRecord:(void(^)(void))completion {
- self.captureModeView.userInteractionEnabled = YES;
- _controlView.btnCountDown.enabled = YES;
- _controlView.recordButtonSwitchControl.enabled = YES;
- __weak __typeof(self) weakSelf = self;
- UGCKitRecordControlView *controlView = _controlView;
- controlView.btnStartRecord.enabled = NO;
- [self _pauseAndAddMark:^{
- [weakSelf saveVideoClipPathToPlist];
- controlView.btnStartRecord.enabled = YES;
- if (completion) {
- completion();
- }
- }];
- [self pauseBGM];
- if (_captureMode != CaptureModePress) {
- [_controlView setRecordButtonStyle:UGCKitRecordButtonStyleRecord];
- }
- _controlView.controlButtonsHidden = NO;
- if (UGCKitRecordStyleRecord != _config.recordStyle) {
- _controlView.btnMusic.hidden = YES;
- _controlView.btnRatioGroup.hidden = YES;
- _controlView.btnAudioEffect.hidden = YES;
- }
-
- [self setSpeedBtnHidden:NO];
-
- _recordState = RecordStatePaused;
-
- [self.previewController stopPlayChorusVideos];
- }
- - (void)startRecord {
- if (_recordTime >= _config.maxDuration) {
- // 已经录制到最大时长
- return;
- }
- if (_recordState == RecordStateStopped) {
- [self startSDKRecord];
- return;
- }
- _controlView.btnCountDown.enabled = NO;
- self.captureModeView.userInteractionEnabled = NO;
- [self syncSpeedRateToSDK];
- if (_bgmRecording) {
- [self resumeBGM];
- }else{
- [self playBGM:_bgmBeginTime];
- _bgmRecording = YES;
- }
-
- [[TXUGCRecord shareInstance] resumeRecord];
- [self _configButtonToPause];
- if (_deleteCount == 1) {
- [_controlView.progressView cancelDelete];
- _deleteCount = 0;
- }
- [self setSpeedBtnHidden:YES];
- _controlView.recordButtonSwitchControl.enabled = NO;
- _recordState = RecordStateRecording;
- [self.previewController startPlayChorusVideos:_recordTime
- toTime:_config.maxDuration];
- }
- -(void)stopRecordAndComplete:(void(^)(int))completion
- {
- _btnNext.hidden = YES;
- _controlView.btnCountDown.enabled = YES;
- _controlView.recordButtonSwitchControl.enabled = YES;
- [_controlView setRecordButtonStyle:UGCKitRecordButtonStyleRecord];
- [self setSpeedBtnHidden:NO];
- [self.previewController stopPlayChorusVideos];
- //调用partsManager快速合成视频,不破坏录制状态,下次返回后可以接着录制(注意需要先暂停视频录制)
- __weak __typeof(self) weakSelf = self;
- if (_recordState == RecordStateRecording) {
- [self _pauseAndAddMark:^{
- __strong __typeof(weakSelf) self = weakSelf; if (self == nil) { return; }
- self->_recordState = RecordStatePaused;
- [self saveVideoClipPathToPlist];
- [[TXUGCRecord shareInstance].partsManager joinAllParts:self.previewController.recordVideoPath
- complete:^(int result) {
- if (completion){
- completion(result);
- }
- [weakSelf onFinishRecord:result];
- }];
- }];
- } else {
- [[TXUGCRecord shareInstance].partsManager joinAllParts:self.previewController.recordVideoPath
- complete:^(int result) {
- if (completion){
- completion(result);
- }
- [weakSelf onFinishRecord:result];
- }];
- }
- }
- #pragma mark - Camera Control
- - (void)onPInchZoom:(UIPinchGestureRecognizer*)recognizer
- {
- if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
- [[TXUGCRecord shareInstance] setZoom:MIN(MAX(1.0, _zoom * recognizer.scale),5.0)];
- }else if (recognizer.state == UIGestureRecognizerStateEnded){
- _zoom = MIN(MAX(1.0, _zoom * recognizer.scale),5.0);
- recognizer.scale = 1;
- }
- }
- #pragma mark - Record Button Actions
- - (IBAction)onRecordButtonTouchUp:(id)sender
- {
- if (self.captureMode == CaptureModePress) {
- [self pauseRecord];
- } else if (self.captureMode == CaptureModeTap) {
- if (_recordState == RecordStateRecording) {
- [self pauseRecord];
- } else {
- [self startRecord];
- }
- }
- }
- // 录制按钮按下
- - (void)onRecordButtonTouchDown:(id)sender {
- if (self.captureMode == CaptureModeStill) {
- [self takePhoto];
- } else if (self.captureMode == CaptureModePress) {
- [self startRecord];
- }
- }
- - (void)changeCaptureModeUI:(CaptureMode)captureMode
- {
- self.captureMode = captureMode;
- _controlView.recordButtonSwitchControl.selectedIndex = captureMode;
- }
- - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
- {
- UIImageView *imageView = (__bridge UIImageView *)contextInfo;
- [UIView animateWithDuration:0.3
- delay:0
- options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionBeginFromCurrentState
- animations:^{
- CGAffineTransform t = CGAffineTransformTranslate(imageView.transform, 0, self.view.ugckit_height);
- imageView.transform = CGAffineTransformScale(t, 0.5, 0.5);
- } completion:^(BOOL finished) {
- [imageView removeFromSuperview];
- }];
- }
- - (BOOL)shouldAutorotate {
- return YES;
- }
- - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
- return UIInterfaceOrientationMaskPortrait;
- }
- -(void)startCameraPreview
- {
- if (_isCameraPreviewOn == NO)
- {
- //简单设置
- // TXUGCSimpleConfig * param = [[TXUGCSimpleConfig alloc] init];
- // param.videoQuality = VIDEO_QUALITY_MEDIUM;
- // [[TXUGCRecord shareInstance] startCameraSimple:param preview:_previewController.videoRecordView];
- //自定义设置
- TXUGCCustomConfig * param = [[TXUGCCustomConfig alloc] init];
- param.videoResolution = _config.resolution;
- param.videoFPS = _config.fps;
- param.videoBitratePIN = _config.videoBitrate;
- param.GOP = _config.gop;
- param.audioSampleRate = _config.audioSampleRate;
- param.minDuration = _config.minDuration;
- param.maxDuration = _config.maxDuration + 2;
- param.frontCamera = _isFrontCamera;
- param.enableAEC = _config.AECEnabled;
- [[TXUGCRecord shareInstance] startCameraCustom:param preview:_previewController.videoRecordView];
- TXBeautyManager *beautyManager = [[TXUGCRecord shareInstance] getBeautyManager];
- [beautyManager setBeautyStyle:(TXBeautyStyle)_beautyStyle];
- [beautyManager setBeautyLevel:_beautyDepth];
- [beautyManager setWhitenessLevel:_whitenDepth];
- [beautyManager setRuddyLevel:_ruddinessDepth];
- if (UGCKitRecordStyleRecord == _config.recordStyle) {
- [[TXUGCRecord shareInstance] setVideoRenderMode:VIDEO_RENDER_MODE_ADJUST_RESOLUTION];
- } else {
- [[TXUGCRecord shareInstance] setVideoRenderMode:VIDEO_RENDER_MODE_FULL_FILL_SCREEN];
- }
- [beautyManager setEyeScaleLevel:_eye_level];
- [beautyManager setFaceSlimLevel:_face_level];
- if (_config.watermark) {
- UIImage *watermark = _config.watermark.image;
- CGRect watermarkFrame = _config.watermark.frame;
- [[TXUGCRecord shareInstance] setWaterMark:watermark normalizationFrame:watermarkFrame];
- } else {
- [[TXUGCRecord shareInstance] setWaterMark:nil normalizationFrame:CGRectZero];;
- }
- #if POD_PITU
- [self motionTmplSelected:_materialID];
- #endif
- //内存里面没有视频数据,重置美颜状态
- if ([TXUGCRecord shareInstance].partsManager.getVideoPathList.count == 0) {
- [self resetBeautySettings];
- }
-
- //加载本地视频 -> 内存
- if (_preloadingVideos) {
- NSArray *cachePathList = [[NSUserDefaults standardUserDefaults] objectForKey:CACHE_PATH_LIST];
- NSString *cacheFolder = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:UGCKIT_PARTS_DIR];
- //预加载视频 -> SDK
- TXVideoInfo *videoInfo = nil;
- for (NSInteger i = cachePathList.count - 1; i >= 0; i --) {
- NSString *videoPath = [cacheFolder stringByAppendingPathComponent:cachePathList[i]];
- [[TXUGCRecord shareInstance].partsManager insertPart:videoPath atIndex:0];
- if (i == 0) {
- videoInfo = [TXVideoInfoReader getVideoInfo:videoPath];
- }
- }
- //录制分辨比例初始化
- if (videoInfo.width == 720 && videoInfo.height == 1280) {
- [self _switchToRatio:VIDEO_ASPECT_RATIO_9_16];
- }else if(videoInfo.width == 720 && videoInfo.height == 960) {
- [self _switchToRatio:VIDEO_ASPECT_RATIO_4_3];
- }else if(videoInfo.width == 720 && videoInfo.height == 720) {
- [self _switchToRatio:VIDEO_ASPECT_RATIO_1_1];
- }
- _controlView.btnRatioGroup.enabled = cachePathList.count == 0;
- //进度条初始化
- CGFloat time = 0;
- for (NSInteger i = 0; i < cachePathList.count; i ++) {
- NSString *videoPath = [cacheFolder stringByAppendingPathComponent:cachePathList[i]];
- time = time + [TXVideoInfoReader getVideoInfo:videoPath].duration;
- [_controlView.progressView pauseAtTime:time];
- }
- _preloadingVideos = NO;
- }
- _isCameraPreviewOn = YES;
- }
- }
- - (void)resetBeautySettings {
- [_vBeauty resetAndApplyValues];
- [[TXUGCRecord shareInstance] setFilter:nil];
- [[TXUGCRecord shareInstance] setGreenScreenFile:nil];
- }
- -(void)stopCameraPreview
- {
- if (_isCameraPreviewOn == YES)
- {
- [[TXUGCRecord shareInstance] stopCameraPreview];
- _isCameraPreviewOn = NO;
- }
- }
- - (void)saveVideoClipPathToPlist
- {
- if (UGCKitRecordStyleRecord != _config.recordStyle) {
- // 合唱暂不支持草稿
- return;
- }
- NSMutableArray *cachePathList = [NSMutableArray array];
- for (NSString *videoPath in [TXUGCRecord shareInstance].partsManager.getVideoPathList) {
- [cachePathList addObject:[[videoPath pathComponents] lastObject]];
- }
- [[NSUserDefaults standardUserDefaults] setObject:cachePathList forKey:CACHE_PATH_LIST];
- [[NSUserDefaults standardUserDefaults] synchronize];
- }
- -(void)onFinishRecord:(int)result
- {
- _btnNext.hidden = NO;
- if(0 == result){
- if (UGCKitRecordStyleRecord == _config.recordStyle) {
- [self stopCameraPreview];
- if (self.completion) {
- NSAssert(self.previewController.recordVideoPath != nil, @"unexpected");
- UGCKitResult *result = [[UGCKitResult alloc] init];;
- result.media = [UGCKitMedia mediaWithVideoPath:self.previewController.recordVideoPath];
- result.coverImage = [[UIImage alloc] initWithContentsOfFile:[_coverPath stringByAppendingString:@".png"]];
- if (self.completion) {
- self.completion(result);
- }
- }
- } else {
- _btnNext.hidden = YES;
- [self joinVideos];
- }
- [UGCKitReporter report:UGCKitReportItem_videorecord userName:nil code:0 msg:ASLocalizedString(@"视频录制成功")];
- }else{
- NSString * message = [NSString stringWithFormat:@"%@(%d)",
- [_theme localizedString:@"UGCKit.Record.TryAgain"],
- result];
- [self alert:[_theme localizedString:@"UGCKit.Media.HintVideoSynthesizeFailed"]
- msg:message];
- [UGCKitReporter report:UGCKitReportItem_videorecord userName:nil code:-1 msg:ASLocalizedString(@"视频录制失败")];
- }
- }
- - (void)joinVideos
- {
- NSString * recordVideoPath = self.previewController.recordVideoPath;
- if (0 == recordVideoPath.length
- || 0 == _config.chorusVideos.count
- || ![[NSFileManager defaultManager] fileExistsAtPath:recordVideoPath]
- || ![[NSFileManager defaultManager] fileExistsAtPath:_config.chorusVideos.firstObject]
- || (UGCKitRecordStyleTrio == _config.recordStyle
- && (_config.chorusVideos.count < 2 || ![[NSFileManager defaultManager] fileExistsAtPath:_config.chorusVideos[1]]))) {
- [self alert:[_theme localizedString:@"UGCKit.Media.HintVideoSynthesizeFailed"]
- msg:[_theme localizedString:@"UGCKit.Record.TryAgain"]];
- return;
- }
-
- CGFloat canvasWidth = 720 * 2, canvasHeight = 1280;
- CGFloat halfWidth = canvasWidth / 2;
- NSArray *displayRects = @[[NSValue valueWithCGRect:CGRectMake(0, 0, halfWidth, canvasHeight)],
- [NSValue valueWithCGRect:CGRectMake(halfWidth, 0, halfWidth, canvasHeight)]];
- if (UGCKitRecordStyleTrio == _config.recordStyle) {
- canvasWidth = 720;
- CGFloat oneThirdHeight = canvasHeight / 3;
- displayRects = @[[NSValue valueWithCGRect:CGRectMake(0, 0, canvasWidth, oneThirdHeight)],
- [NSValue valueWithCGRect:CGRectMake(0, oneThirdHeight, canvasWidth, oneThirdHeight)],
- [NSValue valueWithCGRect:CGRectMake(0, canvasHeight - oneThirdHeight, canvasWidth, oneThirdHeight)]];
- }
-
- if (0 == [_videoJoiner setVideoPathList:self.previewController.allVideoPaths]) {
- [_videoJoiner setSplitScreenList:displayRects canvasWidth:canvasWidth canvasHeight:canvasHeight];
- [_videoJoiner setVideoVolumes:self.previewController.allVideoVolumes];
- [_videoJoiner splitJoinVideo:VIDEO_COMPRESSED_720P videoOutputPath:_joinVideoPath];
- if (nil == _hud) {
- _hud = [UGCKitProgressHUD showHUDAddedTo:self.view animated:YES];
- } else {
- [self.view addSubview:_hud];
- [_hud showAnimated:YES];
- }
- _hud.mode = UGCKitProgressHUDModeText;
- _hud.label.text = [_theme localizedString:@"UGCKit.Media.VideoSynthesizing"];
- } else {
- [self alert:[_theme localizedString:@"UGCKit.Media.HintVideoSynthesizeFailed"]
- msg:[_theme localizedString:@"UGCKit.Record.VideoChorusNotSupported"]];
- }
- }
- /// 选拍照模式
- - (void)setCaptureMode:(CaptureMode)captureMode
- {
- _captureMode = captureMode;
-
- BOOL isStillMode = captureMode == CaptureModeStill;
- _controlView.speedControlEnabled = !isStillMode;
- _controlView.progressView.hidden = isStillMode;
- _controlView.recordTimeLabel.hidden = isStillMode;
- _controlView.btnDelete.hidden = isStillMode;
- }
- #pragma mark Control Panel Switching
- - (void) touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- if (_vBeautyShow)
- {
- UITouch *touch = [[event allTouches] anyObject];
- CGPoint _touchPoint = [touch locationInView:self.view];
- if (NO == CGRectContainsPoint(_vBeauty.frame, _touchPoint))
- {
- [self onBtnBeautyClicked:nil];
- }
- }
- if (_musicView && !_musicView.hidden) {
- CGPoint _touchPoint = [[[event allTouches] anyObject] locationInView:self.view];
- if (NO == CGRectContainsPoint(_musicView.frame, _touchPoint)){
- _musicView.hidden = !_musicView.hidden;
- [self hideBottomView:!_musicView.hidden];
- }
- }
- if (_soundMixView && !_soundMixView.hidden) {
- _soundMixView.hidden = YES;
- _controlView.bottomMask.hidden = NO;
- [self hideBottomView:NO];
- CATransition *animation = [CATransition animation];
- animation.duration = 0.1;
- animation.type = kCATransitionFade;
- [_soundMixView.superview.layer addAnimation:animation forKey:nil];
- }
- }
- - (void)hideBottomView:(BOOL)bHide
- {
- _controlView.hidden = bHide;
- }
- #pragma mark - TXUGCRecordListener
- -(void) onRecordProgress:(NSInteger)milliSecond;
- {
- _recordTime = milliSecond / 1000.0;
- BOOL shouldPause = _recordTime >= _config.maxDuration;
- [self updateRecordProgressLabel: _recordTime];
-
- BOOL isEmpty = milliSecond == 0;
- //录制过程中不能切换BGM, 不能改变声音效果,不能更换合拍视频
- if (UGCKitRecordStyleRecord == _config.recordStyle) {
- _btnChangeVideo.hidden = YES;
- } else {
- _btnChangeVideo.hidden = !isEmpty;
- }
- _controlView.btnRatioGroup.enabled = isEmpty;
- _controlView.btnMusic.enabled = isEmpty;
- _btnNext.hidden = milliSecond / 1000.0 < _config.minDuration;
- _controlView.btnAudioEffect.enabled = _controlView.btnMusic.enabled;
- //回删之后被模仿视频进度回退
- if (_isBackDelete && UGCKitRecordStyleRecord != _config.recordStyle) {
- [self.previewController seekChorusVideosToTime:_recordTime];
- _isBackDelete = NO;
- }
- if (shouldPause) {
- [self pauseRecord];
- if (_config.autoComplete) {
- [self _finishRecord];
- }
- }
- }
- -(void) onRecordComplete:(TXUGCRecordResult*)result;
- {
- [_controlView setRecordButtonStyle:UGCKitRecordButtonStyleRecord];
- if (_appForeground)
- {
- if (_currentRecordTime >= _config.minDuration)
- {
- if (result.retCode != UGC_RECORD_RESULT_FAILED) {
- [self onFinishRecord:(int)result.retCode];
- }else{
- [self toastTip:[_theme localizedString:@"UGCKit.Record.ErrorREC"]];
- }
- } else {
- [self toastTip:[_theme localizedString:@"UGCKit.Record.ErrorTime"]];
- }
- }
- }
- - (void)updateRecordProgressLabel:(CGFloat)second {
- _currentRecordTime = second;
- [_controlView.progressView update:_currentRecordTime / _config.maxDuration];
- long min = (int)_currentRecordTime / 60;
- long sec = (int)_currentRecordTime % 60;
- [_controlView.recordTimeLabel setText:[NSString stringWithFormat:@"%02ld:%02ld", min, sec]];
- }
- #pragma mark TXVideoJoinerListener
- -(void) onJoinProgress:(float)progress
- {
- _hud.label.text = [NSString stringWithFormat:@"%@%d%%",[_theme localizedString:@"UGCKit.Media.VideoSynthesizing"], (int)(progress * 100)];
- }
- -(void) onJoinComplete:(TXJoinerResult *)result
- {
- _btnNext.hidden = NO;
- [_hud hideAnimated:YES];
- if (_appForeground && result.retCode == RECORD_RESULT_OK) {
- [self stopCameraPreview];
- if (self.completion) {
- UGCKitResult *result = [[UGCKitResult alloc] init];
- result.media = [UGCKitMedia mediaWithVideoPath:_joinVideoPath];
- self.completion(result);
- }
- }else{
- [self alert:[_theme localizedString:@"UGCKit.Media.HintVideoSynthesizeFailed"] msg:result.descMsg];
- }
- [UGCKitReporter report:UGCKitReportItem_videojoiner userName:nil code:result.retCode msg:result.descMsg];
- }
- #if POD_PITU
- - (void)motionTmplSelected:(NSString *)materialID {
- if (materialID == nil) {
- [MCTip hideText];
- }
- _materialID = materialID;
- if ([MaterialManager isOnlinePackage:materialID]) {
- [[TXUGCRecord shareInstance] selectMotionTmpl:materialID inDir:[MaterialManager packageDownloadDir]];
- } else {
- NSString *localPackageDir = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Resource"];
- [[TXUGCRecord shareInstance] selectMotionTmpl:materialID inDir:localPackageDir];
- }
- }
- #endif
- #pragma mark - BeautyLoadPituDelegate
- - (void)onLoadPituStart
- {
- dispatch_async(dispatch_get_main_queue(), ^{
- UGCKitProgressHUD *hud = [UGCKitProgressHUD showHUDAddedTo:self.view animated:YES];
- hud.mode = UGCKitProgressHUDModeText;
- hud.label.text = [self->_theme localizedString:@"UGCKit.Record.ResourceLoadBegin"];
- self->_hud = hud;
- });
- }
- - (void)onLoadPituProgress:(CGFloat)progress
- {
- dispatch_async(dispatch_get_main_queue(), ^{
- self->_hud.label.text = [NSString stringWithFormat:[self->_theme localizedString:@"UGCKit.Record.ResourceLoading"],(int)(progress * 100)];
- });
- }
- - (void)onLoadPituFinished
- {
- dispatch_async(dispatch_get_main_queue(), ^{
- self->_hud.label.text = [self->_theme localizedString:@"UGCKit.Record.ResourceLoadSucceeded"];
- [self->_hud hideAnimated:YES afterDelay:1];
- });
- }
- - (void)onLoadPituFailed
- {
- dispatch_async(dispatch_get_main_queue(), ^{
- self->_hud.label.text = [self->_theme localizedString:@"UGCKit.Record.ResourceLoadFailed"];
- [self->_hud hideAnimated:YES afterDelay:1];
- });
- }
- #pragma mark TCBGMControllerListener
- -(void) onBGMControllerPlay:(NSObject*) path{
- [self dismissViewControllerAnimated:YES completion:nil];
- if(path == nil) return;
- [self onSetBGM:path];
- //试听音乐这里要把RecordSpeed 设置为VIDEO_RECORD_SPEED_NOMAL,否则音乐可能会出现加速或则慢速播现象
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_NOMAL];
- [self playBGM:0];
- dispatch_async(dispatch_get_main_queue(), ^(){
- UGCKitVideoRecordMusicView *musicView = self->_musicView;
- [musicView resetCutView];
- if(musicView.hidden){
- musicView.hidden = !musicView.hidden;
- [self hideBottomView:!musicView.hidden];
- }
- });
- }
- #pragma mark - UGCKitAudioEffectPanelDelegate
- - (void)audioEffectPanel:(UGCKitAudioEffectPanel *)panel didSelectReverbType:(TXVideoReverbType)type
- {
- _revertType = type;
- [[TXUGCRecord shareInstance] setReverbType:type];
- }
- - (void)audioEffectPanel:(UGCKitAudioEffectPanel *)panel didSelectVoiceChangerType:(TXVideoVoiceChangerType)type
- {
- _voiceChangerType = type;
- [[TXUGCRecord shareInstance] setVoiceChangerType:type];
- }
- -(void)onBtnMusicSelected
- {
- UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:_bgmListVC];
- [nv.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
- // nv.navigationBar.barTintColor = RGB(25, 29, 38);
- nv.modalPresentationStyle = UIModalPresentationFullScreen;
- [self presentViewController:nv animated:YES completion:nil];
- [_bgmListVC loadBGMList];
- }
- -(void)onBtnMusicStoped
- {
- _BGMPath = nil;
- _bgmRecording = NO;
- [[TXUGCRecord shareInstance] stopBGM];
- if (!_musicView.hidden) {
- _musicView.hidden = !_musicView.hidden;
- [self hideBottomView:!_musicView.hidden];
- }
- }
- -(void)onBGMValueChange:(CGFloat)value
- {
- [[TXUGCRecord shareInstance] setBGMVolume:value];
- }
- -(void)onVoiceValueChange:(CGFloat)value
- {
- [[TXUGCRecord shareInstance] setMicVolume:value];
- }
- -(void)onBGMRangeChange:(CGFloat)startPercent endPercent:(CGFloat)endPercent
- {
- //切换bgm 范围的时候,bgm录制状态置NO
- _bgmRecording = NO;
- //试听音乐这里要把RecordSpeed 设置为VIDEO_RECORD_SPEED_NOMAL,否则音乐可能会出现加速或则慢速播现象
- [[TXUGCRecord shareInstance] setRecordSpeed:VIDEO_RECORD_SPEED_NOMAL];
- [self playBGM:_BGMDuration * startPercent toTime:_BGMDuration * endPercent];
- }
- #pragma mark - BGM Operations
- -(void)onSetBGM:(NSObject *)path
- {
- _BGMPath = path;
- if([_BGMPath isKindOfClass:[NSString class]]){
- _BGMDuration = [[TXUGCRecord shareInstance] setBGM:(NSString *)_BGMPath];
- }else{
- _BGMDuration = [[TXUGCRecord shareInstance] setBGMAsset:(AVAsset *)_BGMPath];
- }
-
- _bgmRecording = NO;
- dispatch_async(dispatch_get_main_queue(), ^{
- [UGCKitProgressHUD hideHUDForView:self.view animated:YES];
- });
- }
- -(void)playBGM:(CGFloat)beginTime{
- if (_BGMPath != nil) {
- [[TXUGCRecord shareInstance] playBGMFromTime:beginTime toTime:_BGMDuration withBeginNotify:^(NSInteger errCode) {
-
- } withProgressNotify:^(NSInteger progressMS, NSInteger durationMS) {
-
- } andCompleteNotify:^(NSInteger errCode) {
-
- }];
- _bgmBeginTime = beginTime;
- }
- }
- -(void)playBGM:(CGFloat)beginTime toTime:(CGFloat)endTime
- {
- if (_BGMPath != nil) {
- [[TXUGCRecord shareInstance] playBGMFromTime:beginTime toTime:endTime withBeginNotify:^(NSInteger errCode) {
-
- } withProgressNotify:^(NSInteger progressMS, NSInteger durationMS) {
-
- } andCompleteNotify:^(NSInteger errCode) {
-
- }];
- _bgmBeginTime = beginTime;
- }
- }
- -(void)pauseBGM{
- if (_BGMPath != nil) {
- [[TXUGCRecord shareInstance] pauseBGM];
- }
- }
- - (void)resumeBGM
- {
- if (_BGMPath != nil) {
- [[TXUGCRecord shareInstance] resumeBGM];
- }
- }
- #pragma mark - Misc Methods
- - (void) toastTip:(NSString*)toastInfo
- {
- UGCKitProgressHUD *hud = [UGCKitProgressHUD showHUDAddedTo:self.view animated:YES];
- hud.mode = UGCKitProgressHUDModeText;
- hud.label.text = toastInfo;
- dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
- dispatch_after(popTime, dispatch_get_main_queue(), ^{
- if ([hud.label.text isEqualToString:toastInfo]) {
- [hud hideAnimated:YES];
- }
- });
- }
- -(void)alert:(NSString *)title msg:(NSString *)msg
- {
- UIAlertController *controller = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
- [controller addAction:[UIAlertAction actionWithTitle:[_theme localizedString:@"UGCKit.Common.OK"] style:UIAlertActionStyleCancel handler:nil]];
- [self presentViewController:controller animated:YES completion:nil];
- }
- #pragma mark - gesture handler
- - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
- CGPoint location = [gestureRecognizer locationInView:self.view];
- CGRect frame = [self.view convertRect:_controlView.bottomMask.frame fromView:_controlView];
- return !CGRectContainsPoint(frame, location);
- }
- - (void)onPanSlideFilter:(UIPanGestureRecognizer*)recognizer
- {
- CGPoint translation = [recognizer translationInView:self.view.superview];
- [recognizer velocityInView:self.view];
- CGPoint speed = [recognizer velocityInView:self.view];
-
- // NSLog(@"pan center:(%.2f)", translation.x);
- // NSLog(@"pan speed:(%.2f)", speed.x);
-
- float ratio = translation.x / self.view.frame.size.width;
- float leftRatio = ratio;
- NSInteger index = [_vBeauty currentFilterIndex];
- UIImage* curFilterImage = [_vBeauty filterImageByMenuOptionIndex:index];
- UIImage* filterImage1 = nil;
- UIImage* filterImage2 = nil;
- CGFloat filter1Level = 0.f;
- CGFloat filter2Level = 0.f;
- if (leftRatio > 0) {
- filterImage1 = [_vBeauty filterImageByMenuOptionIndex:index - 1];
- filter1Level = [_vBeauty filterStrengthAtIndex:index - 1] / 10;
- filterImage2 = curFilterImage;
- filter2Level = [_vBeauty filterStrengthAtIndex:index] / 10;
- }
- else {
- filterImage1 = curFilterImage;
- filter1Level = [_vBeauty filterStrengthAtIndex:index] / 10;
- filterImage2 = [_vBeauty filterImageByMenuOptionIndex:index + 1];
- filter2Level = [_vBeauty filterStrengthAtIndex:index + 1] / 10;
- leftRatio = 1 + leftRatio;
- }
-
- if (recognizer.state == UIGestureRecognizerStateChanged) {
- [[TXUGCRecord shareInstance] setFilter:filterImage1
- leftIntensity:filter1Level
- rightFilter:filterImage2
- rightIntensity:filter2Level
- leftRatio:leftRatio];
- }
- else if (recognizer.state == UIGestureRecognizerStateEnded) {
- BOOL isDependRadio = fabs(speed.x) < 500; //x方向的速度
- [self animateFromFilter1:filterImage1
- filter2:filterImage2
- filter1Strength:filter1Level
- filter2Strength:filter2Level
- leftRadio:leftRatio
- speed:speed.x
- completion:^{
- NSInteger filterIndex = index;
- if (!isDependRadio) {
- if (speed.x < 0) {
- filterIndex = index + 1;
- } else {
- filterIndex = index - 1;
- }
- } else {
- if (ratio > 0.5) { //过半或者速度>500就切换
- filterIndex = index - 1;
- } else if (ratio < -0.5) {
- filterIndex = index + 1;
- }
- }
- self->_vBeauty.currentFilterIndex = filterIndex;
- UILabel* filterTipLabel = [UILabel new];
- filterTipLabel.text = [self->_vBeauty currentFilterName];
- filterTipLabel.font = [UIFont systemFontOfSize:30];
- filterTipLabel.textColor = UIColor.whiteColor;
- filterTipLabel.alpha = 0.1;
- [filterTipLabel sizeToFit];
- CGSize viewSize = self.view.frame.size;
- CGFloat centerX = UGCKitRecordStyleDuet != self->_config.recordStyle ? viewSize.width / 2 : viewSize.width / 4;
- CGFloat centerY = UGCKitRecordStyleTrio != self->_config.recordStyle ? viewSize.height / 3 : viewSize.height / 2;
- filterTipLabel.center = CGPointMake(centerX, centerY);
- [self.view addSubview:filterTipLabel];
- [UIView animateWithDuration:0.25 animations:^{
- filterTipLabel.alpha = 1;
- } completion:^(BOOL finished) {
- [UIView animateWithDuration:0.25 delay:0.25 options:UIViewAnimationOptionCurveLinear animations:^{
- filterTipLabel.alpha = 0.1;
- } completion:^(BOOL finished) {
- [filterTipLabel removeFromSuperview];
- }];
- }];
- }];
-
-
- }
- }
- - (void)animateFromFilter1:(UIImage*)filter1Image
- filter2:(UIImage*)filter2Image
- filter1Strength:(CGFloat)filter1Strength
- filter2Strength:(CGFloat)filter2Strength
- leftRadio:(CGFloat)leftRadio
- speed:(CGFloat)speed
- completion:(void(^)(void))completion
- {
- if (leftRadio <= 0 || leftRadio >= 1) {
- completion();
- return;
- }
-
- static float delta = 1.f / 12;
-
- BOOL isDependRadio = fabs(speed) < 500;
- if (isDependRadio) {
- if (leftRadio < 0.5) {
- leftRadio -= delta;
- }
- else {
- leftRadio += delta;
- }
- }
- else {
- if (speed > 0) {
- leftRadio += delta;
- }
- else
- leftRadio -= delta;
- }
-
- [[TXUGCRecord shareInstance] setFilter:filter1Image leftIntensity:filter1Strength rightFilter:filter2Image rightIntensity:filter2Strength leftRatio:leftRadio];
-
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f / 30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self animateFromFilter1:filter1Image filter2:filter2Image filter1Strength:filter1Strength filter2Strength:filter2Strength leftRadio:leftRadio speed:speed completion:completion];
- });
- }
- - (void)uinit{
- [[TXUGCRecord shareInstance] stopRecord];
- [[TXUGCRecord shareInstance] stopCameraPreview];
- [[TXUGCRecord shareInstance].partsManager deleteAllParts];
- _recordState = RecordStateStopped;
- // [TCUtil removeCacheFile:_recordVideoPath];
- // [TCUtil removeCacheFile:_joinVideoPath];
- }
- - (void)dealloc
- {
- [self uinit];
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- @end
- @implementation UGCKitRecordConfig
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- _ratio = VIDEO_ASPECT_RATIO_9_16;
- _resolution = VIDEO_RESOLUTION_720_1280;
- _videoBitrate = 9600;
- _minDuration = 2;
- _maxDuration = 16.0;
- _audioSampleRate = AUDIO_SAMPLERATE_48000;
- _fps = 30;
- _gop = 3;
- _AECEnabled = YES;
- _autoComplete = YES;
- }
- return self;
- }
- @end
- @implementation UGCKitRecordPreviewController
- {
- NSArray<NSString *> *_allVideoPaths;
-
- NSString *_recordVideoPath;
-
- UIView *_containerView;
-
- UIView *_videoRecordView;
-
- UGCKitRecordStyle _recordStyle;
-
- NSArray<TXVideoEditer *> *_videoPlayers;
- }
- - (instancetype)initWithContainerView:(UIView *)containerView
- recordStyle:(UGCKitRecordStyle)recordStyle
- chorusVideos:(NSArray<NSString *> *)chorusVideos
- recordVideo:(NSString *)recordVideo
- {
- if (!containerView) {
- return nil;
- }
-
- if (self = [super init]) {
- _containerView = containerView;
- _recordStyle = recordStyle;
-
- _recordVideoPath = recordVideo ? recordVideo : @"";
-
- _videoRecordView = [[UIView alloc] initWithFrame:containerView.bounds];
- _videoRecordView.autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight;
- [containerView addSubview:_videoRecordView];
-
- [self initChildViews:chorusVideos];
-
- [containerView bringSubviewToFront:_videoRecordView];
- }
- return self;
- }
- - (void)initChildViews:(NSArray<NSString *> *)chorusVideos
- {
- if (UGCKitRecordStyleRecord == _recordStyle) {
- return;
- }
-
- NSMutableArray<TXVideoEditer *> *videoPlayers = [NSMutableArray arrayWithCapacity:chorusVideos.count];
- void (^allocVideoPlayer)(UIView *, CGRect, NSString *, UIViewAutoresizing) = ^(UIView *containerView,
- CGRect frame, NSString *videoPath,
- UIViewAutoresizing autoresizingMask) {
- UIView *playerView = [[UIView alloc] initWithFrame:frame];
- playerView.autoresizingMask = autoresizingMask;
- [containerView addSubview:playerView];
-
- TXPreviewParam *param = [[TXPreviewParam alloc] init];
- param.renderMode = PREVIEW_RENDER_MODE_FILL_SCREEN;
- param.videoView = playerView;
-
- TXVideoEditer *videoPlayer = [[TXVideoEditer alloc] initWithPreview:param];
- [videoPlayer setVideoPath:videoPath];
- [videoPlayers addObject:videoPlayer];
- };
-
- NSMutableArray<NSString *> *allVideoPaths = [NSMutableArray arrayWithCapacity:chorusVideos.count + 1];
- [allVideoPaths addObject:_recordVideoPath];
-
- if (UGCKitRecordStyleDuet == _recordStyle) { /// 分屏合拍模式
- CGRect viewRect = CGRectMake(0, 0,
- CGRectGetWidth(_containerView.frame) / 2,
- CGRectGetHeight(_containerView.frame));
- _videoRecordView.translatesAutoresizingMaskIntoConstraints = NO;
- _videoRecordView.frame = viewRect;
- _videoRecordView.autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight
- | UIViewAutoresizingFlexibleRightMargin;
-
- UIViewAutoresizing autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight
- | UIViewAutoresizingFlexibleLeftMargin;
- viewRect.origin.x = CGRectGetMaxX(viewRect);
- NSString *videoPath = chorusVideos.firstObject;
- allocVideoPlayer(_containerView, viewRect, videoPath, autoresizingMask);
- [allVideoPaths addObject:(videoPath ? videoPath : @"")];
- } else if (UGCKitRecordStyleTrio == _recordStyle) { /// 三屏合拍模式
- CGRect viewRect = CGRectMake(0,
- CGRectGetHeight(_containerView.frame) / 3,
- CGRectGetWidth(_containerView.frame),
- CGRectGetHeight(_containerView.frame) / 3);
- _videoRecordView.translatesAutoresizingMaskIntoConstraints = NO;
- _videoRecordView.frame = viewRect;
- _videoRecordView.autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight
- | UIViewAutoresizingFlexibleTopMargin
- | UIViewAutoresizingFlexibleBottomMargin;
-
- for (NSUInteger idx = 0; idx < 2; idx++) {
- NSString *videoPath = idx < chorusVideos.count ? chorusVideos[idx] : chorusVideos.firstObject;
- if (0 == idx) {
- CGRect playerRect = CGRectMake(0, CGRectGetMaxY(viewRect), viewRect.size.width, viewRect.size.height);
- UIViewAutoresizing autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight
- | UIViewAutoresizingFlexibleBottomMargin;
- allocVideoPlayer(_containerView, playerRect, videoPath, autoresizingMask);
- [allVideoPaths insertObject:(videoPath ? videoPath : @"") atIndex:0];
-
- } else {
- CGRect playerRect = CGRectMake(0, 0, viewRect.size.width, viewRect.size.height);
- UIViewAutoresizing autoresizingMask = UIViewAutoresizingFlexibleWidth
- | UIViewAutoresizingFlexibleHeight
- | UIViewAutoresizingFlexibleTopMargin;
- allocVideoPlayer(_containerView, playerRect, videoPath, autoresizingMask);
- [videoPlayers.lastObject setVideoVolume:0];
- [allVideoPaths addObject:(videoPath ? videoPath : @"")];
- }
- }
- }
- _videoPlayers = videoPlayers;
- _allVideoPaths = allVideoPaths;
- }
- - (instancetype)init
- {
- return nil;
- }
- - (NSArray<NSNumber *> *)allVideoVolumes
- {
- if (UGCKitRecordStyleRecord == _recordStyle) {
- return @[@1];
- } else if (UGCKitRecordStyleDuet == _recordStyle) {
- return @[@0, @1];
- } else {
- return @[@1, @0, @0];
- }
- }
- - (void)changeChorusVideo:(NSString *)videoPath
- {
- if (UGCKitRecordStyleRecord == _recordStyle || 0 == videoPath.length) {
- return;
- }
-
- for (TXVideoEditer *videoPlayer in _videoPlayers) {
- [videoPlayer stopPlay];
- [videoPlayer setVideoPath:videoPath];
- [videoPlayer previewAtTime:0];
- }
-
- if (UGCKitRecordStyleDuet == _recordStyle) {
- _allVideoPaths = @[_recordVideoPath, videoPath];
- } else if (UGCKitRecordStyleTrio == _recordStyle) {
- _allVideoPaths = @[videoPath, _recordVideoPath, videoPath];
- }
- }
- #pragma mark - start/stop play chorus videos
- - (void)startPlayChorusVideos:(CGFloat)startTime toTime:(CGFloat)endTime
- {
- for (TXVideoEditer *videoPlayer in _videoPlayers) {
- [videoPlayer startPlayFromTime:startTime toTime:endTime];
- }
- }
- - (void)stopPlayChorusVideos
- {
- for (TXVideoEditer *videoPlayer in _videoPlayers) {
- [videoPlayer stopPlay];
- }
- }
- - (void)seekChorusVideosToTime:(CGFloat)time
- {
- for (TXVideoEditer *videoPlayer in _videoPlayers) {
- [videoPlayer previewAtTime:time];
- }
- }
- @end
- @implementation UGCKitNavControllerPrivate
- - (UIInterfaceOrientationMask)supportedInterfaceOrientations
- {
- return self.supportedOrientations;
- }
- - (UIStatusBarStyle)preferredStatusBarStyle
- {
- return UIStatusBarStyleLightContent;
- }
- @end
|