|
@@ -0,0 +1,1078 @@
|
|
|
+//
|
|
|
+// KSMediaMergeView.m
|
|
|
+// KulexiuSchoolStudent
|
|
|
+//
|
|
|
+// Created by 王智 on 2023/8/29.
|
|
|
+//
|
|
|
+
|
|
|
+#import "KSMediaMergeView.h"
|
|
|
+#import "KSMergeAudioControlView.h"
|
|
|
+#import "KSAudioAnimationView.h"
|
|
|
+#import "KSMediaEditor.h"
|
|
|
+#import "KSPlayerView.h"
|
|
|
+#import "KSPlayerSliderView.h"
|
|
|
+#import "kSNewPlayer.h"
|
|
|
+#import "KSVideoPlayerView.h"
|
|
|
+#import "TZImageManager.h"
|
|
|
+#import "KSUploadManager.h"
|
|
|
+#import "KSAudioPlayAnimationView.h"
|
|
|
+#import "KSNewAlertView.h"
|
|
|
+#import "MusicPublistAlert.h"
|
|
|
+#import "KSMediaManager.h"
|
|
|
+
|
|
|
+@interface KSMediaMergeView ()<kSNewPlayerManagerDelegate,KSVideoPlayerViewDelegate>
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSAudioAnimationView *animationView;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSMergeAudioControlView *contrlView;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSURL *videoUrl;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSURL *bgAudioUrl;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSURL *recordUrl;
|
|
|
+
|
|
|
+@property (nonatomic, assign) NSInteger offsetTime;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSPlayerView *playerView;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSPlayerSliderView *playControlView;
|
|
|
+
|
|
|
+@property (nonatomic, strong) kSNewPlayer *bgPlayer;
|
|
|
+
|
|
|
+@property (nonatomic, strong) kSNewPlayer *recordPlayer;
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isPause;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSString *filePath;
|
|
|
+
|
|
|
+
|
|
|
+@property (nonatomic, assign) NSInteger originalOffset;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSVideoPlayerView *videoView;
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isVideoPlay;
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isHideControlView;
|
|
|
+
|
|
|
+@property (nonatomic, strong) UIButton *showButton;
|
|
|
+
|
|
|
+@property (nonatomic, strong) PHAsset *videoAsset;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSString *presentName;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSAudioPlayAnimationView *playAnimationView;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSTimer *timer;
|
|
|
+
|
|
|
+// 远端资源
|
|
|
+@property (nonatomic, strong) NSString *remoteVideoUrl;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSString *remoteBgAudioUrl;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSString *remoteRecrodUrl;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSString *jsonConfig;
|
|
|
+
|
|
|
+
|
|
|
+@property (nonatomic, assign) NSInteger originalVolume;
|
|
|
+
|
|
|
+@property (nonatomic, assign) NSInteger accompanyVolume;
|
|
|
+
|
|
|
+@property (nonatomic, strong) dispatch_group_t requestGroup;
|
|
|
+
|
|
|
+@property (nonatomic, copy) DraftEditCallback draftCallback;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSDictionary *preJsonDic;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSNewAlertView *alertView;
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL hasSave;
|
|
|
+
|
|
|
+@property (nonatomic, copy) MergeCallback mergeCallback;
|
|
|
+
|
|
|
+@property (nonatomic, strong) MusicPublistAlert *publishAlert;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSMediaManager *mediaManager;
|
|
|
+
|
|
|
+@property (nonatomic, strong) UIImage *settingImage; // 图片
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL hasModify;
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation KSMediaMergeView
|
|
|
+
|
|
|
+- (instancetype)init {
|
|
|
+ self = [super init];
|
|
|
+ if (self) {
|
|
|
+ self.hasModify = NO;
|
|
|
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:@"appEnterBackground" object:nil];
|
|
|
+ }
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)appEnterBackground {
|
|
|
+ [self stopPlay];
|
|
|
+}
|
|
|
+
|
|
|
+- (instancetype)initWithFrame:(CGRect)frame {
|
|
|
+ self = [super initWithFrame:frame];
|
|
|
+ if (self) {
|
|
|
+ }
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)configWithVideoUrl:(NSURL *)videoUrl bgAudioUrl:(NSURL *)bgAudioUrl remoteBgUrl:(NSString *)remoteBgUrl recordUrl:(NSURL *)recordUrl offsetTime:(NSInteger)offsetTime mergeCallback:(MergeCallback)callback {
|
|
|
+ if (callback) {
|
|
|
+ self.mergeCallback = callback;
|
|
|
+ }
|
|
|
+ if (videoUrl) {
|
|
|
+ self.isVideoPlay = YES;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ self.isVideoPlay = NO;
|
|
|
+ }
|
|
|
+ self.remoteBgAudioUrl = remoteBgUrl;
|
|
|
+ self.videoUrl = videoUrl;
|
|
|
+ self.bgAudioUrl = bgAudioUrl;
|
|
|
+ self.recordUrl = recordUrl;
|
|
|
+ if (offsetTime > 300) {
|
|
|
+ offsetTime = 300;
|
|
|
+ }
|
|
|
+ self.originalOffset = 0;
|
|
|
+ [self.contrlView configWithOffsetTime:0];
|
|
|
+ self.contrlView.hideBackView = NO;
|
|
|
+ [self configPlayer];
|
|
|
+ [self configUI];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)configRemoteVideoUrl:(NSString *)remoteVideoUrl bgAudioUrl:(NSString *)remoteBgAudioUrl recordUrl:(NSString *)remoteRecrodUrl jsonConfig:(NSString *)jsonConfig callback:(DraftEditCallback)callback {
|
|
|
+ if (callback) {
|
|
|
+ self.draftCallback = callback;
|
|
|
+ }
|
|
|
+ if (![NSString isEmptyString:remoteVideoUrl]) {
|
|
|
+ self.isVideoPlay = YES;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ self.isVideoPlay = NO;
|
|
|
+ }
|
|
|
+ self.remoteVideoUrl = remoteVideoUrl;
|
|
|
+ self.remoteBgAudioUrl = remoteBgAudioUrl;
|
|
|
+ self.remoteRecrodUrl = remoteRecrodUrl;
|
|
|
+
|
|
|
+ self.preJsonDic = [jsonConfig mj_JSONObject];
|
|
|
+ self.originalOffset = [self.preJsonDic ks_integerValueForKey:@"offset"];
|
|
|
+ self.offsetTime = self.originalOffset;
|
|
|
+ [self.contrlView configWithOffsetTime:self.originalOffset];
|
|
|
+ self.contrlView.hideBackView = YES;
|
|
|
+ [self downloadFileSource];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)downloadFileSource {
|
|
|
+ [LOADING_MANAGER showCustomLoading:@"资源下载中..."];
|
|
|
+
|
|
|
+ [self downloadVideo];
|
|
|
+ [self downloadAccompany];
|
|
|
+ [self downloadAudio];
|
|
|
+ dispatch_group_notify(self.requestGroup, dispatch_get_main_queue(), ^{
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ [self configPlayer];
|
|
|
+ [self configUI];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)downloadVideo {
|
|
|
+ if (![NSString isEmptyString:self.remoteVideoUrl]) {
|
|
|
+ dispatch_group_enter(self.requestGroup);
|
|
|
+ [KSNetworkingManager downloadFileRequestWithFileUrl:self.remoteVideoUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
|
|
|
+
|
|
|
+ } success:^(NSURL * _Nonnull fileUrl) {
|
|
|
+ dispatch_group_leave(self.requestGroup);
|
|
|
+ self.videoUrl = fileUrl;
|
|
|
+ } faliure:^(NSError * _Nonnull error) {
|
|
|
+ dispatch_group_leave(self.requestGroup);
|
|
|
+
|
|
|
+ }];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)downloadAudio {
|
|
|
+ if (![NSString isEmptyString:self.remoteRecrodUrl]) {
|
|
|
+ dispatch_group_enter(self.requestGroup);
|
|
|
+
|
|
|
+ [KSNetworkingManager downloadFileRequestWithFileUrl:self.remoteRecrodUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
|
|
|
+
|
|
|
+ } success:^(NSURL * _Nonnull fileUrl) {
|
|
|
+ dispatch_group_leave(self.requestGroup);
|
|
|
+ self.recordUrl = fileUrl;
|
|
|
+ } faliure:^(NSError * _Nonnull error) {
|
|
|
+ dispatch_group_leave(self.requestGroup);
|
|
|
+ }];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)downloadAccompany {
|
|
|
+ if (![NSString isEmptyString:self.remoteBgAudioUrl]) {
|
|
|
+ dispatch_group_enter(self.requestGroup);
|
|
|
+ [KSNetworkingManager downloadFileRequestWithFileUrl:self.remoteBgAudioUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
|
|
|
+
|
|
|
+ } success:^(NSURL * _Nonnull fileUrl) {
|
|
|
+ dispatch_group_leave(self.requestGroup);
|
|
|
+ self.bgAudioUrl = fileUrl;
|
|
|
+ } faliure:^(NSError * _Nonnull error) {
|
|
|
+ dispatch_group_leave(self.requestGroup);
|
|
|
+
|
|
|
+ }];
|
|
|
+ }
|
|
|
+}
|
|
|
+- (void)configPlayer {
|
|
|
+
|
|
|
+ if (self.bgAudioUrl) {
|
|
|
+ [self.bgPlayer preparePlayNativeSongWithPath:self.bgAudioUrl];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (self.recordUrl) {
|
|
|
+ [self.recordPlayer preparePlayNativeSongWithPath:self.recordUrl];
|
|
|
+ }
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self.videoView preparePlayNativeVideoWithPath:self.videoUrl];
|
|
|
+ self.videoView.isMute = YES;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 音量同步
|
|
|
+ NSInteger accompanyVolume = 100;
|
|
|
+ if ([[self.preJsonDic allKeys] containsObject:@"accompanyVolume"]) {
|
|
|
+ accompanyVolume = [self.preJsonDic ks_integerValueForKey:@"accompanyVolume"];
|
|
|
+ }
|
|
|
+ self.accompanyVolume = accompanyVolume;
|
|
|
+ self.bgPlayer.volume = accompanyVolume / 100.0;
|
|
|
+
|
|
|
+ NSInteger originalVolume = 100;
|
|
|
+ if ([[self.preJsonDic allKeys] containsObject:@"originalVolume"]) {
|
|
|
+ originalVolume = [self.preJsonDic ks_integerValueForKey:@"originalVolume"];
|
|
|
+ }
|
|
|
+ self.originalVolume = originalVolume;
|
|
|
+ self.recordPlayer.volume = originalVolume / 100.0;
|
|
|
+
|
|
|
+ [self.contrlView configRecordVolume:originalVolume bgVolume:accompanyVolume];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)configUI {
|
|
|
+ self.backgroundColor = [UIColor whiteColor];
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self addSubview:self.videoView];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self addSubview:self.playerView];
|
|
|
+ }
|
|
|
+
|
|
|
+ [self addSubview:self.showButton];
|
|
|
+ self.showButton.hidden = YES;
|
|
|
+ self.showButton.userInteractionEnabled = NO;
|
|
|
+
|
|
|
+ [self addSubview:self.contrlView];
|
|
|
+ [self.contrlView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.right.top.bottom.mas_equalTo(self);
|
|
|
+ make.width.mas_equalTo(289);
|
|
|
+ }];
|
|
|
+
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self.videoView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.top.bottom.mas_equalTo(self);
|
|
|
+ make.right.mas_equalTo(self.contrlView.mas_left).offset(20);
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else { // 音频
|
|
|
+ // 添加投影
|
|
|
+ UIImageView *shadowImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"merge_music_bg"]];
|
|
|
+ [self.playerView addSubview:shadowImage];
|
|
|
+
|
|
|
+
|
|
|
+ [self.playerView addSubview:self.playAnimationView];
|
|
|
+ [self.playAnimationView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.centerX.mas_equalTo(self.playerView.mas_centerX);
|
|
|
+ make.centerY.mas_equalTo(self.playerView.mas_centerY);
|
|
|
+ make.width.mas_equalTo(424);
|
|
|
+ make.height.mas_equalTo(80);
|
|
|
+ }];
|
|
|
+
|
|
|
+ [self.playerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.top.bottom.mas_equalTo(self);
|
|
|
+ make.right.mas_equalTo(self.contrlView.mas_left).offset(20);
|
|
|
+ }];
|
|
|
+
|
|
|
+ [self.playerView addSubview:self.animationView];
|
|
|
+ [self.animationView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.centerX.mas_equalTo(self.playerView.mas_centerX);
|
|
|
+ make.centerY.mas_equalTo(self.playerView.mas_centerY);
|
|
|
+ make.width.height.mas_equalTo(200);
|
|
|
+ }];
|
|
|
+ [shadowImage mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.width.mas_equalTo(284);
|
|
|
+ make.height.mas_equalTo(151);
|
|
|
+ make.centerX.mas_equalTo(self.playerView.mas_centerX);
|
|
|
+ make.top.mas_equalTo(self.animationView.mas_top).offset(86);
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+ [self addSubview:self.playControlView];
|
|
|
+ [self.playControlView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.mas_equalTo(self.mas_left);
|
|
|
+ make.right.mas_equalTo(self.contrlView.mas_left).offset(-20);
|
|
|
+ make.height.mas_equalTo(44);
|
|
|
+ make.bottom.mas_equalTo(self.mas_bottom).offset(-30);
|
|
|
+ }];
|
|
|
+
|
|
|
+ [self.playControlView configViewDisplayColor:self.isVideoPlay];
|
|
|
+ NSString *imgName = self.isVideoPlay ? @"back_button_white" : @"back_black";
|
|
|
+ UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
+ [backButton setImage:[UIImage imageNamed:imgName] forState:UIControlStateNormal];
|
|
|
+ [backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
|
|
|
+ [self addSubview:backButton];
|
|
|
+ [backButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.width.height.mas_equalTo(44);
|
|
|
+ make.left.mas_equalTo(self.mas_left).offset(10);
|
|
|
+ make.top.mas_equalTo(self.mas_top).offset(10);
|
|
|
+ }];
|
|
|
+ float totalTime = [self.recordPlayer getTotalDuration];
|
|
|
+ [self.playControlView configWithDuration:totalTime];
|
|
|
+
|
|
|
+ UILabel *songLabel = [[UILabel alloc] init];
|
|
|
+ songLabel.font = [UIFont systemFontOfSize:16.0f weight:UIFontWeightSemibold];
|
|
|
+ songLabel.text = [NSString returnNoNullStringWithString:self.songName];
|
|
|
+ songLabel.textColor = self.isVideoPlay ? HexRGB(0xffffff) : HexRGB(0x131415);
|
|
|
+ [self addSubview:songLabel];
|
|
|
+ [songLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.mas_equalTo(backButton.mas_right);
|
|
|
+ make.centerY.mas_equalTo(backButton.mas_centerY);
|
|
|
+ make.height.mas_equalTo(22);
|
|
|
+ make.right.mas_greaterThanOrEqualTo(self.contrlView.mas_left).offset(20);
|
|
|
+ }];
|
|
|
+ [self startPlay];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)backAction {
|
|
|
+ if (self.hasModify) {
|
|
|
+ MJWeakSelf;
|
|
|
+ [self.alertView configTitle:@"提示" descMessage:@"是否将本次录制的作品保存为草稿?" leftButtonTitle:@"取消" rightButtonTitle:@"确认" leftButtonAction:^{
|
|
|
+ [weakSelf removeViewTips:NO];
|
|
|
+ } rightButtonAction:^{
|
|
|
+ [weakSelf saveCurrentDraft:YES];
|
|
|
+ }];
|
|
|
+ [self.alertView showAlert];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (self.mergeCallback) {
|
|
|
+ [self removeViewTips:NO];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self removeView];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark ----- lazying
|
|
|
+- (KSAudioAnimationView *)animationView {
|
|
|
+ if (!_animationView) {
|
|
|
+ _animationView = [KSAudioAnimationView shareInstance];
|
|
|
+ }
|
|
|
+ return _animationView;
|
|
|
+}
|
|
|
+
|
|
|
+- (KSPlayerView *)playerView {
|
|
|
+ if (!_playerView) {
|
|
|
+ _playerView = [[KSPlayerView alloc] init];
|
|
|
+ }
|
|
|
+ return _playerView;
|
|
|
+}
|
|
|
+
|
|
|
+- (KSPlayerSliderView *)playControlView {
|
|
|
+ if (!_playControlView) {
|
|
|
+ _playControlView = [KSPlayerSliderView shareInstance];
|
|
|
+ MJWeakSelf;
|
|
|
+ [_playControlView sliderControlAction:^(PLAYERTYPE type, NSInteger rate) {
|
|
|
+ [weakSelf playSliderAction:type rate:rate];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ return _playControlView;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)startPlay {
|
|
|
+ self.playControlView.isPlay = YES;
|
|
|
+ self.animationView.isPlay = YES;
|
|
|
+ NSInteger recordPlayerPosition = self.playControlView.playScheduleTime*1000;
|
|
|
+ NSLog(@"--recordPlayer start---");
|
|
|
+ [self.recordPlayer seekToTimePlay:recordPlayerPosition];
|
|
|
+ NSInteger realOffsetTime = self.offsetTime;
|
|
|
+ NSInteger offsetTime = recordPlayerPosition + realOffsetTime;
|
|
|
+ if (offsetTime > 0) {
|
|
|
+ [self.bgPlayer seekToTimePlay:labs(offsetTime)];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(labs(offsetTime) * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
|
|
|
+ NSLog(@"--bgPlayer start---");
|
|
|
+
|
|
|
+ [self.bgPlayer startPlay];
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self.videoView seekToTimePlay:recordPlayerPosition];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self.playAnimationView startAnimation];
|
|
|
+ [self startTimer];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)stopPlay {
|
|
|
+ self.animationView.isPlay = NO;
|
|
|
+ self.playControlView.isPlay = NO;
|
|
|
+ [self.bgPlayer puasePlay];
|
|
|
+ [self.recordPlayer puasePlay];
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self.videoView puasePlay];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self.playAnimationView stopAnimation];
|
|
|
+ [self stopTimer];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playSliderAction:(PLAYERTYPE)type rate:(NSInteger)rate {
|
|
|
+ switch (type) {
|
|
|
+ case PLAYERTYPE_PLAY:
|
|
|
+ {
|
|
|
+ [self startPlay];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PLAYERTYPE_PAUSE:
|
|
|
+ {
|
|
|
+ [self stopPlay];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PLAYERTYPE_RATE:
|
|
|
+ {
|
|
|
+ [self.recordPlayer seekOffsetTime:rate*1000];
|
|
|
+ NSInteger realOffsetTime = self.offsetTime;
|
|
|
+
|
|
|
+ NSInteger offsetTime = rate*1000 + realOffsetTime;
|
|
|
+ if (offsetTime > 0) {
|
|
|
+ [self.bgPlayer seekOffsetTime:labs(offsetTime)];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self.bgPlayer puasePlay];
|
|
|
+ if (self.recordPlayer.isPlaying) {
|
|
|
+
|
|
|
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(labs(offsetTime) * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
|
|
|
+ [self.bgPlayer startPlay];
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self.bgPlayer seekToStart];
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self.videoView seekOffsetTime:rate*1000];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)startTimer {
|
|
|
+ [self.timer setFireDate:[NSDate distantPast]];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)stopTimer {
|
|
|
+ [self.timer setFireDate:[NSDate distantFuture]];
|
|
|
+}
|
|
|
+
|
|
|
+- (KSMergeAudioControlView *)contrlView {
|
|
|
+ if (!_contrlView) {
|
|
|
+ _contrlView = [KSMergeAudioControlView shareIntance];
|
|
|
+ MJWeakSelf;
|
|
|
+ [_contrlView controlActionCallback:^(MERGEACTION type, NSInteger recordVolume, NSInteger bgVolume, NSInteger offsetTime) {
|
|
|
+ [weakSelf megerAction:type recordVolume:recordVolume bgVolume:bgVolume offsetTime:offsetTime];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ return _contrlView;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)megerAction:(MERGEACTION)action recordVolume:(NSInteger)recordVolume bgVolume:(NSInteger)bgVolume offsetTime:(NSInteger)offsetTime {
|
|
|
+ switch (action) {
|
|
|
+ case MERGEACTION_CANCLE:
|
|
|
+ {
|
|
|
+ [self backAction];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MERGEACTION_MODIFY:
|
|
|
+ {
|
|
|
+ self.hasModify = YES;
|
|
|
+ self.accompanyVolume = bgVolume;
|
|
|
+ self.originalVolume = recordVolume;
|
|
|
+
|
|
|
+ self.bgPlayer.volume = bgVolume / 100.0;
|
|
|
+ self.recordPlayer.volume = recordVolume / 100.0;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MERGEACTION_DELAY: // offset
|
|
|
+ {
|
|
|
+ self.hasModify = YES;
|
|
|
+ if (self.bgPlayer.isPlaying) {
|
|
|
+ CMTime time = [self.recordPlayer getCurrentPlayTime];
|
|
|
+ NSInteger newDelayTime = CMTimeGetSeconds(time) * 1000 + offsetTime;
|
|
|
+ [self.bgPlayer seekOffsetTime:newDelayTime];
|
|
|
+ }
|
|
|
+
|
|
|
+ self.offsetTime = offsetTime;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MERGEACTION_SAVE: // 保存
|
|
|
+ {
|
|
|
+ [self saveCurrentDraft:NO];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MERGEACTION_UPLOAD: // 上传
|
|
|
+ {
|
|
|
+ [self showPublishAlert];
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MERGEACTION_HIDEVIEW:
|
|
|
+ {
|
|
|
+ [self hideControlView];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)showPublishAlert {
|
|
|
+ self.publishAlert = [MusicPublistAlert shareInstance];
|
|
|
+ self.publishAlert.musicName.text = [NSString returnNoNullStringWithString:self.songName];
|
|
|
+ [self.publishAlert.musicImage sd_setImageWithURL:[NSURL URLWithString:[self.coverImage getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"pub_music_placeholder"]];
|
|
|
+ self.publishAlert.userName.text = [NSString returnNoNullStringWithString:UserDefault(NicknameKey)];
|
|
|
+ MJWeakSelf;
|
|
|
+ [self.publishAlert chooseAction:^(PUBLISH_ACTION type) {
|
|
|
+ [weakSelf publishAction:type];
|
|
|
+ }];
|
|
|
+ [self.publishAlert showAlert];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)publishAction:(PUBLISH_ACTION)type {
|
|
|
+ switch (type) {
|
|
|
+ case PUBLISH_ACTION_PUBLISH:
|
|
|
+ {
|
|
|
+ self.desc = [NSString isEmptyString:self.publishAlert.textView.text] ? @"我发布了一首演奏作品,快来听听吧~" :self.publishAlert.textView.text;
|
|
|
+ if (self.settingImage) { // 上传图片
|
|
|
+ [self updateWithCoverImage:self.settingImage];
|
|
|
+ }
|
|
|
+ else { // 直接上传
|
|
|
+ [self publishMusic];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PUBLISH_ACTION_CHOOSEIMG:
|
|
|
+ {
|
|
|
+ // 调用相册
|
|
|
+ self.mediaManager = [[KSMediaManager alloc] init];
|
|
|
+ self.mediaManager.mediaType = MEDIATYPE_PHOTO;
|
|
|
+ self.mediaManager.maxPhotoNumber = 1;
|
|
|
+ self.mediaManager.baseCtrl = [self findViewController];
|
|
|
+
|
|
|
+ self.mediaManager.needCropImage = NO;
|
|
|
+ MJWeakSelf;
|
|
|
+ [self.mediaManager noAlertCallback:^(NSString * _Nullable videoUrl, NSMutableArray * _Nullable imageArray, NSMutableArray * _Nullable imageAsset) {
|
|
|
+ [weakSelf refreshViewCoverImg:imageArray];
|
|
|
+ }];
|
|
|
+ [self.mediaManager pushImagePickerController];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)updateWithCoverImage:(UIImage *)image {
|
|
|
+ NSData *imgData = [UIImage turnsImaegDataByImage:image];
|
|
|
+ NSString *fileName = @"musicCoverImg";
|
|
|
+ [UPLOAD_MANAGER configBucketName:@"daya"];
|
|
|
+ [[KSUploadManager shareInstance] uploadImage:imgData fileName:fileName successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
|
|
|
+ NSString *avatarUrl = [fileUrlArray lastObject];
|
|
|
+ self.coverImage = avatarUrl;
|
|
|
+ [self publishMusic];
|
|
|
+ } faliure:^(NSError * _Nullable error, NSString *descMessaeg) {
|
|
|
+ if ([NSString isEmptyString:descMessaeg]) {
|
|
|
+ [LOADING_MANAGER MBShowAUTOHidingInWindow:descMessaeg];
|
|
|
+ }
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)refreshViewCoverImg:(NSMutableArray *)imageArray {
|
|
|
+ UIImage *img = [imageArray lastObject];
|
|
|
+ self.settingImage = img;
|
|
|
+ [self.publishAlert.musicImage setImage:self.settingImage];
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)publishMusic {
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [LOADING_MANAGER showCustomLoading:@"视频合成中..."];
|
|
|
+ [KSMediaEditor mixVideoWithRecordAudio:self.recordUrl recordVolume:self.recordPlayer.volume bgAudio:self.bgAudioUrl bgAudioVolume:self.bgPlayer.volume offsetTime:self.offsetTime videoUrlStr:self.videoUrl completion:^(NSString * _Nonnull outPath, BOOL isSuccess, NSString * _Nonnull desc) {
|
|
|
+ // 保存文件到指定文件夹
|
|
|
+ if (isSuccess) {
|
|
|
+ self.filePath = outPath;
|
|
|
+ MJWeakSelf;
|
|
|
+ [self saveVideoToAsset:outPath isFormal:YES callback:^(NSString *videoUrl) {
|
|
|
+ [weakSelf saveMusic:YES isFormal:YES fileUrl:videoUrl];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [LOADING_MANAGER showCustomLoading:@"音频合成中..."];
|
|
|
+ NSInteger realOffsetTime = self.offsetTime;
|
|
|
+ [KSMediaEditor mixRecordAudio:self.recordUrl recordVolume:self.recordPlayer.volume bgAudio:self.bgAudioUrl bgAudioVolume:self.bgPlayer.volume offsetTime:realOffsetTime completion:^(NSString * _Nonnull outPath, BOOL isSuccess, NSString * _Nonnull desc) {
|
|
|
+ // 保存文件到指定文件夹
|
|
|
+ if (isSuccess) {
|
|
|
+ self.filePath = outPath;
|
|
|
+ MJWeakSelf;
|
|
|
+ [self sendAudioWithPath:outPath isFormal:YES success:^(NSString *audioUrl) {
|
|
|
+ [weakSelf saveMusic:NO isFormal:YES fileUrl:audioUrl];
|
|
|
+ } failure:^(NSString *desc) {
|
|
|
+ [LOADING_MANAGER MBShowAUTOHidingInWindow:@"文件上传失败"];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+- (void)saveCurrentDraft:(BOOL)needBack {
|
|
|
+ self.hasModify = NO;
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ if (self.remoteVideoUrl) {
|
|
|
+ // 保存草稿
|
|
|
+ [self saveMusic:YES isFormal:NO fileUrl:self.remoteVideoUrl needBack:needBack];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ MJWeakSelf;
|
|
|
+ [self saveVideoURLToAsset:self.videoUrl isFormal:NO callback:^(NSString *videoUrl) {
|
|
|
+ // 保存草稿
|
|
|
+ [weakSelf saveMusic:YES isFormal:NO fileUrl:videoUrl needBack:needBack];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (self.remoteRecrodUrl) {
|
|
|
+ [self saveMusic:NO isFormal:NO fileUrl:self.remoteRecrodUrl needBack:needBack];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ MJWeakSelf;
|
|
|
+ [self sendAudioWithURLPath:self.recordUrl isFormal:NO success:^(NSString *audioUrl) {
|
|
|
+
|
|
|
+ [weakSelf saveMusic:NO isFormal:NO fileUrl:audioUrl needBack:needBack];
|
|
|
+ } failure:^(NSString *desc) {
|
|
|
+ [LOADING_MANAGER MBShowAUTOHidingInWindow:@"文件上传失败"];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)removeViewTips:(BOOL)needTips {
|
|
|
+ [self freePlayer];
|
|
|
+ [self removeFromSuperview];
|
|
|
+ if (self.draftCallback) {
|
|
|
+ self.draftCallback();
|
|
|
+ }
|
|
|
+ if (needTips && self.mergeCallback) {
|
|
|
+ self.mergeCallback();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)removeView {
|
|
|
+ [self removeViewTips:YES];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)freePlayer {
|
|
|
+ if (_bgPlayer) {
|
|
|
+ [self.bgPlayer freePlayer];
|
|
|
+ }
|
|
|
+ if (_recordPlayer) {
|
|
|
+ [self.recordPlayer freePlayer];
|
|
|
+ }
|
|
|
+ if (_videoView) {
|
|
|
+ [self.videoView freePlayer];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (kSNewPlayer *)bgPlayer {
|
|
|
+ if (!_bgPlayer) {
|
|
|
+ _bgPlayer = [[kSNewPlayer alloc] init];
|
|
|
+ _bgPlayer.delegate = self;
|
|
|
+ }
|
|
|
+ return _bgPlayer;
|
|
|
+}
|
|
|
+
|
|
|
+- (kSNewPlayer *)recordPlayer {
|
|
|
+ if (!_recordPlayer) {
|
|
|
+ _recordPlayer = [[kSNewPlayer alloc] init];
|
|
|
+ _recordPlayer.delegate = self;
|
|
|
+ }
|
|
|
+ return _recordPlayer;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark ----- player delegate
|
|
|
+- (void)getSongCurrentTime:(NSInteger)currentTime andTotalTime:(NSInteger)totalTime andProgress:(CGFloat)progress currentInterval:(NSTimeInterval)currentInterval playTime:(NSTimeInterval)playTime inPlayer:(kSNewPlayer *_Nonnull)player {
|
|
|
+ if (player == self.recordPlayer) {
|
|
|
+// NSLog(@"--- ---- ----- %f", playTime);
|
|
|
+ self.playControlView.playScheduleTime = (NSInteger)(playTime / 1000);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ NSLog(@"--- ---- bgPlayer ----- %f", playTime);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playFinished:(kSNewPlayer *)player {
|
|
|
+ if (player == self.recordPlayer) {
|
|
|
+ [self.recordPlayer puasePlay];
|
|
|
+ [self.recordPlayer seekToStart];
|
|
|
+
|
|
|
+ [self.bgPlayer puasePlay];
|
|
|
+ [self.bgPlayer seekToStart];
|
|
|
+ self.isPause = NO;
|
|
|
+ self.animationView.isPlay = NO;
|
|
|
+ self.playControlView.isPlay = NO;
|
|
|
+ [self.playAnimationView stopAnimation];
|
|
|
+ [self stopTimer];
|
|
|
+ if (self.isVideoPlay) {
|
|
|
+ [self.videoView puasePlay];
|
|
|
+ [self.videoView seekToStart];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (KSVideoPlayerView *)videoView {
|
|
|
+ if (!_videoView) {
|
|
|
+ _videoView = [[KSVideoPlayerView alloc] init];
|
|
|
+ _videoView.delegate = self;
|
|
|
+ }
|
|
|
+ return _videoView;
|
|
|
+}
|
|
|
+
|
|
|
+- (UIButton *)showButton {
|
|
|
+ if (!_showButton) {
|
|
|
+ _showButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
+ _showButton.frame = CGRectMake(KLandscapeWidth-30, (KLandscapeHeight-30)/2.0, 30, 30);
|
|
|
+ [_showButton setImage:[UIImage imageNamed:@"mergeControl_show"] forState:UIControlStateNormal];
|
|
|
+ [_showButton addTarget:self action:@selector(showControlView) forControlEvents:UIControlEventTouchUpInside];
|
|
|
+ }
|
|
|
+ return _showButton;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)hideControlView {
|
|
|
+ [UIView animateWithDuration:0.5f animations:^{
|
|
|
+ [self.contrlView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.top.bottom.mas_equalTo(self);
|
|
|
+ make.width.mas_equalTo(289);
|
|
|
+ make.right.mas_equalTo(self.mas_right).offset(289);
|
|
|
+ }];
|
|
|
+ } completion:^(BOOL finished) {
|
|
|
+ self.showButton.hidden = NO;
|
|
|
+ self.showButton.userInteractionEnabled = YES;
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)showControlView {
|
|
|
+ [UIView animateWithDuration:0.5f animations:^{
|
|
|
+ [self.contrlView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.right.top.bottom.mas_equalTo(self);
|
|
|
+ make.width.mas_equalTo(289);
|
|
|
+ }];
|
|
|
+ } completion:^(BOOL finished) {
|
|
|
+ self.showButton.hidden = YES;
|
|
|
+ self.showButton.userInteractionEnabled = NO;
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)saveVideoURLToAsset:(NSURL *)videoUrl isFormal:(BOOL)isFormal callback:(void(^)(NSString *videoUrl))callback {
|
|
|
+
|
|
|
+ [[TZImageManager manager] saveVideoWithUrl:videoUrl completion:^(PHAsset *asset, NSError *error) {
|
|
|
+ if (!error) {
|
|
|
+ self.videoAsset = asset;
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+
|
|
|
+ if (callback) {
|
|
|
+ [self uploadRecordVideoisFormal:isFormal Success:^(NSString *uploadVideoUrl) {
|
|
|
+ callback(uploadVideoUrl);
|
|
|
+
|
|
|
+ } failure:^(NSString *desc) {
|
|
|
+ [LOADING_MANAGER MBShowAUTOHidingInWindow:@"上传视频失败"];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ [LOADING_MANAGER MBShowAUTOHidingInWindow:@"保存视频错误"];
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)saveVideoToAsset:(NSString *)saveVideoUrl isFormal:(BOOL)isFormal callback:(void(^)(NSString *videoUrl))callback {
|
|
|
+ NSURL *fileUrl = [NSURL fileURLWithPath:saveVideoUrl];
|
|
|
+ [self saveVideoURLToAsset:fileUrl isFormal:isFormal callback:^(NSString *videoUrl) {
|
|
|
+ callback(videoUrl);
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)saveMusic:(BOOL)isVideo isFormal:(BOOL)isFormal fileUrl:(NSString *)fileUrl {
|
|
|
+
|
|
|
+ [self saveMusic:isVideo isFormal:isFormal fileUrl:fileUrl needBack:NO];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)saveMusic:(BOOL)isVideo isFormal:(BOOL)isFormal fileUrl:(NSString *)fileUrl needBack:(BOOL)needBack {
|
|
|
+ NSString *type = isFormal ? @"FORMAL" : @"DRAFT";
|
|
|
+ NSMutableDictionary *parm = [NSMutableDictionary dictionary];
|
|
|
+ [parm setValue:@(self.offsetTime) forKey:@"offset"];
|
|
|
+ [parm setValue:@(self.originalVolume) forKey:@"originalVolume"];
|
|
|
+ [parm setValue:@(self.accompanyVolume) forKey:@"accompanyVolume"];
|
|
|
+ self.jsonConfig = [parm mj_JSONString];
|
|
|
+ [LOADING_MANAGER showCustomLoading:@"加载中..."];
|
|
|
+ [KSNetworkingManager saveMusicMessage:KS_POST jsonConfig:self.jsonConfig img:self.coverImage videoUrl:fileUrl accompanyUrl:self.remoteBgAudioUrl desc:self.desc type:type musicPracticeRecordId:self.recordId success:^(NSDictionary * _Nonnull dic) {
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ if ([dic ks_integerValueForKey:@"code"] == 200) {
|
|
|
+ if (isFormal) {
|
|
|
+ [LOADING_MANAGER KSShowMsg:@"发布成功" promptCompletion:^{
|
|
|
+ [self removeView];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [LOADING_MANAGER KSShowMsg:@"保存成功" promptCompletion:^{
|
|
|
+ self.hasModify = NO;
|
|
|
+ if (needBack) {
|
|
|
+ [self removeViewTips:NO];
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
|
|
|
+ }
|
|
|
+ } faliure:^(NSError * _Nonnull error) {
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+// 上传视频
|
|
|
+- (void)uploadRecordVideoisFormal:(BOOL)isFormal Success:(void(^)(NSString *uploadVideoUrl))success failure:(void(^)(NSString *desc))faliure {
|
|
|
+ if (self.videoAsset) {
|
|
|
+ if (self.videoAsset) {
|
|
|
+
|
|
|
+ [[TZImageManager manager] getVideoOutputPathWithAsset:self.videoAsset presetName:self.presentName success:^(NSString *outputPath) {
|
|
|
+
|
|
|
+ NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath);
|
|
|
+ NSData *outputData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:outputPath]]; //压缩后的视频
|
|
|
+ NSLog(@"导出后的视频:%@",[NSString stringWithFormat:@"%.2fM",(CGFloat)outputData.length/(1024*1024)]);
|
|
|
+ // 上传
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ [self sendVideoActionWith:outputPath isFormal:isFormal success:success failure:faliure];
|
|
|
+ });
|
|
|
+
|
|
|
+ } failure:^(NSString *errorMessage, NSError *error) {
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ faliure(@"视频导出失败");
|
|
|
+ });
|
|
|
+ NSLog(@"视频导出失败:%@,error:%@",errorMessage, error);
|
|
|
+
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ faliure(@"未找到视频资源");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ faliure(@"未找到视频资源");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)sendVideoActionWith:(NSString *)fileUrl isFormal:(BOOL)isFormal success:(void (^)(NSString * _Nonnull))success failure:(void (^)(NSString * _Nonnull))faliure {
|
|
|
+ NSString *tips = isFormal ? @"正在上传作品" : @"正在上传草稿";
|
|
|
+ [LOADING_MANAGER showCustomLoading:tips];
|
|
|
+ NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:fileUrl]];
|
|
|
+ NSString *suffix = [NSString stringWithFormat:@".%@",[fileUrl pathExtension]];
|
|
|
+ [UPLOAD_MANAGER configBucketName:@"daya"];
|
|
|
+ [[KSUploadManager shareInstance] videoUpload:fileData fileName:@"video" fileSuffix:suffix progress:^(int64_t bytesWritten, int64_t totalBytes) {
|
|
|
+ // 显示进度
|
|
|
+ int progress = (int)(bytesWritten / totalBytes * 100);
|
|
|
+ __block NSString *tipsMessage = [NSString stringWithFormat:@"%@\n%d%%",tips,progress];
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ [LOADING_MANAGER.loadingView setDisplayText:tipsMessage];
|
|
|
+ });
|
|
|
+ } successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ NSString *fileUrl = [fileUrlArray lastObject];
|
|
|
+ success(fileUrl);
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ } faliure:^(NSError * _Nullable error, NSString * _Nullable descMessaeg) {
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ faliure(descMessaeg);
|
|
|
+ });
|
|
|
+
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)sendAudioWithURLPath:(NSURL *)fileUrl isFormal:(BOOL)isFormal success:(void(^)(NSString *audioUrl))success failure:(void(^)(NSString *desc))faliure {
|
|
|
+ NSString *tips = isFormal ? @"正在上传作品" : @"正在上传草稿";
|
|
|
+
|
|
|
+ [LOADING_MANAGER showCustomLoading:tips];
|
|
|
+ NSData *fileData = [NSData dataWithContentsOfURL:fileUrl];
|
|
|
+ NSString *suffix = [NSString stringWithFormat:@".%@",[fileUrl pathExtension]];
|
|
|
+ [UPLOAD_MANAGER configBucketName:@"daya"];
|
|
|
+ [UPLOAD_MANAGER uploadFile:fileData fileName:@"evaluateAudio" fileSuffix:suffix progress:^(int64_t bytesWritten, int64_t totalBytes) {
|
|
|
+ // 显示进度
|
|
|
+ int progress = (int)(bytesWritten / totalBytes * 100);
|
|
|
+ __block NSString *tipsMessage = [NSString stringWithFormat:@"%@\n%d%%",tips,progress];
|
|
|
+ dispatch_main_async_safe(^{
|
|
|
+ [LOADING_MANAGER.loadingView setDisplayText:tipsMessage];
|
|
|
+ });
|
|
|
+ } successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ NSString *fileUrl = [fileUrlArray lastObject];
|
|
|
+ success(fileUrl);
|
|
|
+ } faliure:^(NSError * _Nullable error, NSString * _Nullable descMessaeg) {
|
|
|
+ [LOADING_MANAGER removeCustomLoading];
|
|
|
+ faliure(descMessaeg);
|
|
|
+ }];
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+- (void)sendAudioWithPath:(NSString *)filePath isFormal:(BOOL)isFormal success:(void(^)(NSString *audioUrl))success failure:(void(^)(NSString *desc))faliure {
|
|
|
+ NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
|
|
|
+ [self sendAudioWithURLPath:fileUrl isFormal:isFormal success:success failure:faliure];
|
|
|
+}
|
|
|
+
|
|
|
+- (NSString *)presentName {
|
|
|
+ NSString *presentName = AVAssetExportPresetMediumQuality;
|
|
|
+ if ([[NSString deviceVersion] containsString:@"iPhone 12"]) {
|
|
|
+
|
|
|
+ presentName = AVAssetExportPreset640x480;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ presentName = AVAssetExportPresetMediumQuality;
|
|
|
+ }
|
|
|
+ return presentName;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)removeVideoWithPath:(NSString *)videoUrl {
|
|
|
+ NSFileManager *fileMamager = [NSFileManager defaultManager];
|
|
|
+ if ([fileMamager fileExistsAtPath:videoUrl]) {
|
|
|
+ [fileMamager removeItemAtPath:videoUrl error:nil];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (KSAudioPlayAnimationView *)playAnimationView {
|
|
|
+ if (!_playAnimationView) {
|
|
|
+ _playAnimationView = [[KSAudioPlayAnimationView alloc] init];
|
|
|
+ _playAnimationView.frame = CGRectMake(0, 0, 424, 80);
|
|
|
+ }
|
|
|
+ return _playAnimationView;
|
|
|
+}
|
|
|
+
|
|
|
+- (NSTimer *)timer{
|
|
|
+
|
|
|
+ if (!_timer) {
|
|
|
+ MJWeakSelf;
|
|
|
+ _timer = [NSTimer scheduledTimerWithTimeInterval:0.5f repeats:YES block:^(NSTimer * _Nonnull timer) {
|
|
|
+ [weakSelf timerAction];
|
|
|
+ }];
|
|
|
+ [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
|
|
|
+ [_timer setFireDate:[NSDate distantFuture]];
|
|
|
+ }
|
|
|
+ return _timer;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)timerAction {
|
|
|
+ float value = drand48();
|
|
|
+ [self.playAnimationView setSoundsValue:value];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark -- 重置定时器
|
|
|
+- (void)resetTimer{
|
|
|
+ [self.timer setFireDate:[NSDate distantPast]];
|
|
|
+ [_timer invalidate];
|
|
|
+ _timer = nil;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)removeAll{
|
|
|
+
|
|
|
+ if (_timer) {
|
|
|
+ [_timer invalidate];
|
|
|
+ _timer = nil;
|
|
|
+ }
|
|
|
+}
|
|
|
+- (void)dealloc {
|
|
|
+ [self removeAll];
|
|
|
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark ----- lazy
|
|
|
+- (dispatch_group_t)requestGroup {
|
|
|
+ if (!_requestGroup) {
|
|
|
+ _requestGroup = dispatch_group_create();
|
|
|
+ }
|
|
|
+ return _requestGroup;
|
|
|
+}
|
|
|
+
|
|
|
+- (KSNewAlertView *)alertView {
|
|
|
+ if (!_alertView) {
|
|
|
+ _alertView = [KSNewAlertView shareInstance];
|
|
|
+
|
|
|
+ }
|
|
|
+ return _alertView;
|
|
|
+}
|
|
|
+
|
|
|
+- (UIViewController *)findViewController {
|
|
|
+ for (UIView *view = self; view; view = view.superview) {
|
|
|
+ UIResponder *nextResponder = [view nextResponder];
|
|
|
+ if ([nextResponder isKindOfClass:[UIViewController class]]) {
|
|
|
+ return (UIViewController *)nextResponder;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+// Only override drawRect: if you perform custom drawing.
|
|
|
+// An empty implementation adversely affects performance during animation.
|
|
|
+- (void)drawRect:(CGRect)rect {
|
|
|
+ // Drawing code
|
|
|
+}
|
|
|
+*/
|
|
|
+
|
|
|
+@end
|