浏览代码

加入,腾讯txt合成语音播放sdk。 up80%

openlockPPP 2 年之前
父节点
当前提交
a839ebfe34
共有 25 个文件被更改,包括 1078 次插入9 次删除
  1. 32 4
      jiaPei.xcodeproj/project.pbxproj
  2. 二进制
      jiaPei.xcworkspace/xcuserdata/mimasigeling.xcuserdatad/UserInterfaceState.xcuserstate
  3. 23 0
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/Contents.json
  4. 二进制
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/读题pause.png
  5. 二进制
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/读题pause@2x.png
  6. 二进制
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/读题pause@3x.png
  7. 23 0
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/Contents.json
  8. 二进制
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/读题pay.png
  9. 二进制
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/读题pay@2x.png
  10. 二进制
      jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/读题pay@3x.png
  11. 1 1
      jiaPei/Modules/OtherModules/ExerciseModule/View/ExercisePage/RQExerciseQuestionCell.m
  12. 39 2
      jiaPei/Modules/OtherModules/ExerciseModule/ViewModel/ExercisePage/itemViewModel/RQExerciseQuestionItemViewModel.m
  13. 1 0
      jiaPei/OLD/Util/SingletonManger/ADViewManager/NYADViewManager.m
  14. 29 0
      jiaPei/OLD/Util/SingletonManger/VoiceManager/NYVoiceManager.h
  15. 449 0
      jiaPei/OLD/Util/SingletonManger/VoiceManager/NYVoiceManager.m
  16. 4 1
      jiaPei/OLD/Util/WXPay/payRequsestHandler.h
  17. 3 1
      jiaPei/PrefixHeader.pch
  18. 25 0
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCPlayerError.h
  19. 74 0
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudMediaPlayer.h
  20. 35 0
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudMediaPlayer2.h
  21. 48 0
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudOfflineAuthInfo.h
  22. 222 0
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudTTSEngine.h
  23. 70 0
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/TtsError.h
  24. 二进制
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Info.plist
  25. 二进制
      jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/QCloudTTS

+ 32 - 4
jiaPei.xcodeproj/project.pbxproj

@@ -101,6 +101,8 @@
 		90798B0B2A52722300E68461 /* NYComplaintListViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 90798B092A52722300E68461 /* NYComplaintListViewCell.xib */; };
 		90798B0F2A52AE2600E68461 /* ComplaintDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 90798B0E2A52AE2600E68461 /* ComplaintDataModel.m */; };
 		90798B122A53E87800E68461 /* NYComplaintListViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 90798B112A53E87800E68461 /* NYComplaintListViewModel.m */; };
+		90B0F6862A70E9E300B448DC /* QCloudTTS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90B0F6852A70E9E300B448DC /* QCloudTTS.framework */; };
+		90B0F68A2A711C5E00B448DC /* NYVoiceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 90B0F6892A711C5E00B448DC /* NYVoiceManager.m */; };
 		90BA2E822A3177B50029A54A /* NYTheoryTimeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 90BA2E802A3177B50029A54A /* NYTheoryTimeVC.m */; };
 		90BA2E872A3177DE0029A54A /* NYGetjobTimeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 90BA2E852A3177DE0029A54A /* NYGetjobTimeVC.m */; };
 		90BA2E8B2A317BEB0029A54A /* NYBasetjTimeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 90BA2E8A2A317BEB0029A54A /* NYBasetjTimeVC.m */; };
@@ -1825,6 +1827,9 @@
 		90798B0E2A52AE2600E68461 /* ComplaintDataModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ComplaintDataModel.m; sourceTree = "<group>"; };
 		90798B102A53E87800E68461 /* NYComplaintListViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NYComplaintListViewModel.h; sourceTree = "<group>"; };
 		90798B112A53E87800E68461 /* NYComplaintListViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NYComplaintListViewModel.m; sourceTree = "<group>"; };
+		90B0F6852A70E9E300B448DC /* QCloudTTS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = QCloudTTS.framework; sourceTree = "<group>"; };
+		90B0F6882A711C5E00B448DC /* NYVoiceManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NYVoiceManager.h; sourceTree = "<group>"; };
+		90B0F6892A711C5E00B448DC /* NYVoiceManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NYVoiceManager.m; sourceTree = "<group>"; };
 		90BA2E7F2A3177B50029A54A /* NYTheoryTimeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NYTheoryTimeVC.h; sourceTree = "<group>"; };
 		90BA2E802A3177B50029A54A /* NYTheoryTimeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NYTheoryTimeVC.m; sourceTree = "<group>"; };
 		90BA2E842A3177DE0029A54A /* NYGetjobTimeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NYGetjobTimeVC.h; sourceTree = "<group>"; };
@@ -4242,6 +4247,7 @@
 				1866FBF01DFFE39D00EE5415 /* CoreMedia.framework in Frameworks */,
 				1866FBEE1DFFE38F00EE5415 /* CoreVideo.framework in Frameworks */,
 				D0FA4D9328C71994009736D1 /* Security.framework in Frameworks */,
+				90B0F6862A70E9E300B448DC /* QCloudTTS.framework in Frameworks */,
 				1866FBE81DFFE27000EE5415 /* libiconv.2.tbd in Frameworks */,
 				D0B3FC3F2869CD4C003C52BA /* CoreBluetooth.framework in Frameworks */,
 				1866FBE61DFFE25D00EE5415 /* libc++.1.tbd in Frameworks */,
@@ -4587,6 +4593,23 @@
 			path = Model;
 			sourceTree = "<group>";
 		};
+		90B0F6842A70E9E300B448DC /* QCloudTTSSDK */ = {
+			isa = PBXGroup;
+			children = (
+				90B0F6852A70E9E300B448DC /* QCloudTTS.framework */,
+			);
+			path = QCloudTTSSDK;
+			sourceTree = "<group>";
+		};
+		90B0F6872A711C1700B448DC /* VoiceManager */ = {
+			isa = PBXGroup;
+			children = (
+				90B0F6882A711C5E00B448DC /* NYVoiceManager.h */,
+				90B0F6892A711C5E00B448DC /* NYVoiceManager.m */,
+			);
+			path = VoiceManager;
+			sourceTree = "<group>";
+		};
 		90BA2E7B2A3175F80029A54A /* NewTheory */ = {
 			isa = PBXGroup;
 			children = (
@@ -9022,6 +9045,7 @@
 		D0B4118A2199674D00BD61DA /* SingletonManger */ = {
 			isa = PBXGroup;
 			children = (
+				90B0F6872A711C1700B448DC /* VoiceManager */,
 				D0A29D66263AB34E0004E6DC /* ADViewManager */,
 				D092510225A6408500820F82 /* ChechBodyManager */,
 				D0B06DBC2232063900FA684D /* LocationManager */,
@@ -9526,6 +9550,7 @@
 				D0870D032701A6B9004EC94E /* YYKit */,
 				D06534882681C853000A5D23 /* Wechat */,
 				D09E5BC425E39A890099E87C /* BaiDuFaceSDK */,
+				90B0F6842A70E9E300B448DC /* QCloudTTSSDK */,
 				D001AF1225A842DD00921EF2 /* FMDBMigrationManager */,
 				D0E9AC0C2524840500DD6EEC /* XYUUID */,
 				D02947F6243F07E300B46AB1 /* RatingBar */,
@@ -11198,6 +11223,7 @@
 				D06BBFBA276722A800D7A2EE /* RQHomeSubPageNormalCell.m in Sources */,
 				D0870E412701B5A0004EC94E /* RQHTTPService+RQGetCode.m in Sources */,
 				D074575329272C680050BE10 /* QMAudioAnimation.m in Sources */,
+				90B0F68A2A711C5E00B448DC /* NYVoiceManager.m in Sources */,
 				D0870D612701A6B9004EC94E /* NSInvocation+BlocksKit.m in Sources */,
 				D074575729272C680050BE10 /* QMItemCollectionCell.m in Sources */,
 				18ACEEF41C3E5FCA00C5DE05 /* InputView.m in Sources */,
@@ -11676,7 +11702,7 @@
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_RESOURCE_RULES_PATH[sdk=*]" = "";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 2022023071301;
+				CURRENT_PROJECT_VERSION = 2032023072601;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEVELOPMENT_TEAM = K7T6CU5SW5;
 				ENABLE_BITCODE = NO;
@@ -11690,6 +11716,7 @@
 					"$(PROJECT_DIR)/RX-FaceSDK/ios",
 					"$(PROJECT_DIR)/jiaPei/Vendor/BaiDuFaceSDK/BDFaceSDK",
 					"$(PROJECT_DIR)/jiaPei/Vendor/ADCDN_SDK",
+					"$(PROJECT_DIR)/jiaPei/Vendor/QCloudTTSSDK",
 				);
 				GCC_PREFIX_HEADER = "$(SRCROOT)/jiaPei/PrefixHeader.pch";
 				HEADER_SEARCH_PATHS = (
@@ -11712,7 +11739,7 @@
 					"$(PROJECT_DIR)/jiaPei/Vendor/BaiDuFaceSDK/BDFaceSDK/lib",
 					"$(PROJECT_DIR)/jiaPei/Vendor/QiNiu_IMSDK/Vendors/Voice",
 				);
-				MARKETING_VERSION = 2.0.2;
+				MARKETING_VERSION = 2.0.3;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_CFLAGS = (
 					"$(inherited)",
@@ -11757,7 +11784,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 2022023071301;
+				CURRENT_PROJECT_VERSION = 2032023072601;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = K7T6CU5SW5;
 				ENABLE_BITCODE = NO;
@@ -11771,6 +11798,7 @@
 					"$(PROJECT_DIR)/RX-FaceSDK/ios",
 					"$(PROJECT_DIR)/jiaPei/Vendor/BaiDuFaceSDK/BDFaceSDK",
 					"$(PROJECT_DIR)/jiaPei/Vendor/ADCDN_SDK",
+					"$(PROJECT_DIR)/jiaPei/Vendor/QCloudTTSSDK",
 				);
 				GCC_PREFIX_HEADER = "$(SRCROOT)/jiaPei/PrefixHeader.pch";
 				HEADER_SEARCH_PATHS = (
@@ -11793,7 +11821,7 @@
 					"$(PROJECT_DIR)/jiaPei/Vendor/BaiDuFaceSDK/BDFaceSDK/lib",
 					"$(PROJECT_DIR)/jiaPei/Vendor/QiNiu_IMSDK/Vendors/Voice",
 				);
-				MARKETING_VERSION = 2.0.2;
+				MARKETING_VERSION = 2.0.3;
 				ONLY_ACTIVE_ARCH = NO;
 				OTHER_CFLAGS = (
 					"$(inherited)",

二进制
jiaPei.xcworkspace/xcuserdata/mimasigeling.xcuserdatad/UserInterfaceState.xcuserstate


+ 23 - 0
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "读题pause.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "读题pause@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "读题pause@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

二进制
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/读题pause.png


二进制
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/读题pause@2x.png


二进制
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pause.imageset/读题pause@3x.png


+ 23 - 0
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "读题pay.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "读题pay@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "读题pay@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

二进制
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/读题pay.png


二进制
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/读题pay@2x.png


二进制
jiaPei/Images.xcassets/Modules/OtherModule/ExerciseModule/读题pay.imageset/读题pay@3x.png


+ 1 - 1
jiaPei/Modules/OtherModules/ExerciseModule/View/ExercisePage/RQExerciseQuestionCell.m

@@ -38,7 +38,7 @@
 - (void)bindViewModel:(RQExerciseQuestionItemViewModel *)viewModel {
     @weakify(self)
     _viewModel = viewModel;
-
+    self.questionLabel.userInteractionEnabled = YES;
     RAC(self.questionLabel, attributedText) = [[RACObserve(viewModel, qusetionString) takeUntil:self.rac_prepareForReuseSignal] deliverOnMainThread];
     RAC(self.labelHeight, constant) = [[RACObserve(viewModel, labelHeight) takeUntil:self.rac_prepareForReuseSignal] deliverOnMainThread];
 

+ 39 - 2
jiaPei/Modules/OtherModules/ExerciseModule/ViewModel/ExercisePage/itemViewModel/RQExerciseQuestionItemViewModel.m

@@ -6,6 +6,7 @@
 //
 
 #import "RQExerciseQuestionItemViewModel.h"
+#import "payRequsestHandler.h"
 
 @interface RQExerciseQuestionItemViewModel ()
 @property (nonatomic, readwrite, strong) RQExerciseModel *exerciseModel;
@@ -19,6 +20,8 @@
 @property (nonatomic, readwrite, strong) NSString *videoString;
 @property (nonatomic, readwrite, strong) NSMutableAttributedString *spaceAttachment;
 
+//@property (nonatomic, readwrite, strong) QMUIButton *readBtn;
+
 @end
 
 @implementation RQExerciseQuestionItemViewModel
@@ -27,11 +30,11 @@
         @weakify(self)
         self.exerciseModel = exerciseModel;
         
-        
         dispatch_async(dispatch_get_main_queue(), ^{
             @strongify(self)
             self.qusetionString = [self dealQuestionStrWithRQExerciseModel:exerciseModel];
             self.labelHeight = [self getMessageHeightWithAttributedStr:self.qusetionString andLabel:self.yyLabel];
+            
         });
         
         
@@ -229,7 +232,25 @@
 //        [_self showMessage:[NSString stringWithFormat:@"Tap: %@",[text.string substringWithRange:range]]];
 //    }];
     [testText appendAttributedString: attrString];
-
+    
+    //读题
+    QMUIButton *readBtn = [QMUIButton buttonWithType:UIButtonTypeCustom];
+    CGFloat ebtnH = 20.f;
+    CGFloat ebtnW = 58.f;
+    CGSize ebtnSize = CGSizeMake(ebtnW, ebtnH);
+    readBtn.size = btnSize;
+    [readBtn setImage:RQImageNamed(@"读题pay") forState:UIControlStateNormal];
+    [readBtn setImage:RQImageNamed(@"读题pause") forState:UIControlStateSelected];
+    [readBtn addTarget:self action:@selector(buttonActionPayVoicedo:) forControlEvents:UIControlEventTouchUpInside];
+    NSMutableAttributedString *readAttachment = [NSMutableAttributedString yy_attachmentStringWithContent:readBtn
+                                                               contentMode:UIViewContentModeCenter
+                                                            attachmentSize:ebtnSize
+                                                               alignToFont:[UIFont systemFontOfSize:RQ_Exercise_Module.exerciseFontSize]
+                                                                 alignment:YYTextVerticalAlignmentCenter];
+//    self.readBtn = readBtn;
+    [testText appendAttributedString:self.spaceAttachment];
+    [testText appendAttributedString:readAttachment];
+    
     [text appendAttributedString:testText];
 //    [text appendAttributedString:[self padding]];
     text.yy_lineSpacing = 8;
@@ -281,4 +302,20 @@
 - (NSString *)itemClassName {
     return @"RQExerciseQuestionCell";
 }
+
+#pragma mark -事件
+- (void)buttonActionPayVoicedo:(UIButton *)btn
+{
+    btn.selected = !btn.isSelected;
+    QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+     //如果使用STS临时证书鉴权时需要设置Token
+    [tts setOnlineAuthParam:QDApp_Id SecretId:QDSecret_ID SecretKey:QDSecret_Key Token:nil];
+    if(btn.selected){//播放
+        NSString *Question = self.exerciseModel.ydtQuestionModel.Question;
+        [NY_VOICE_MANAGER startPayVoiceActionText:Question];
+    }else {//暂停
+        [NY_VOICE_MANAGER pausePayVoiceAction];
+    }
+}
+
 @end

+ 1 - 0
jiaPei/OLD/Util/SingletonManger/ADViewManager/NYADViewManager.m

@@ -98,6 +98,7 @@ static dispatch_once_t onceToken;
 #pragma mark - PrivateMethods
 
 - (void)initCXHAdSDK {
+    [CXHAdSDK setRequestDomain:@"http://ad.baihemob.com"];
     [CXHAdSDK setLogLevel:CXHSDKLogLevelDebug];
     NSString *CXHAppid = @"458110";
     [CXHAdSDK initWithAppId:CXHAppid completionBlock:^(NSError * _Nullable error) {

+ 29 - 0
jiaPei/OLD/Util/SingletonManger/VoiceManager/NYVoiceManager.h

@@ -0,0 +1,29 @@
+//
+//  NYVoiceManager.h
+//  jiaPei
+//
+//  Created by Ning.ge on 2023/7/26.
+//  Copyright © 2023 JCZ. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+#define NY_VOICE_MANAGER [NYVoiceManager sharedManager]
+
+@interface NYVoiceManager : NSObject
+
++ (NYVoiceManager *)sharedManager;
+- (void)ny_configureTTSVoiceDK;
+
+//开播合成播放
+- (void)startPayVoiceActionText:(NSString *)text;
+//暂停合成播放
+- (void)pausePayVoiceAction;
+//停止合成播放
+- (void)stopPayVoiceAction;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 449 - 0
jiaPei/OLD/Util/SingletonManger/VoiceManager/NYVoiceManager.m

@@ -0,0 +1,449 @@
+//
+//  NYVoiceManager.m
+//  jiaPei
+//
+//  Created by Ning.ge on 2023/7/26.
+//  Copyright © 2023 JCZ. All rights reserved.
+//
+
+#import "NYVoiceManager.h"
+#import "payRequsestHandler.h"
+
+static NYVoiceManager *vomanger = nil;
+static dispatch_once_t onceToken;
+
+@interface NYVoiceManager ()<QCloudTTSEngineDelegate,QCloudPlayerDelegate>
+{
+    NSMutableArray*  _textArr;
+}
+//SDK 内置播放器
+@property(strong) QCloudMediaPlayer *player;
+// demo 层播放器,如SDK播放器不能满足需求 可以自定义播放器 如下只是一个例子
+//@property(strong) MediaPlayerDemo *player;
+
+
+@property (nonatomic,assign)float onlineSpeed;
+@property (nonatomic,assign)int onlineVoiceType;
+@property (nonatomic,assign)int onlineLanguage;
+@property (nonatomic,assign)float onlineVolume;
+
+@property (nonatomic,assign)float offlineSpeed;
+@property (nonatomic,copy)NSString *offlineVoiceType;
+@property (nonatomic,assign)int offlineLanguage;
+@property (nonatomic,assign)float offlineVolume;
+
+@property (nonatomic,assign)int responseTimeout;
+@property (nonatomic,assign)int requestTimeout;
+@property (nonatomic,assign)int checkTimeout;
+
+@property (nonatomic, copy) NSString*  resource_dir;
+
+@property (nonatomic,assign)int cout; //统计合成句子数,当作utteranceId用于标记句子用
+
+@end
+
+
+@implementation NYVoiceManager
+
+
+#pragma mark - SystemMethod
++ (NYVoiceManager *)sharedManager {
+    dispatch_once(&onceToken, ^{
+        vomanger = [[self alloc] init];
+    });
+    return vomanger;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        [self initBaseData];
+    }
+    return self;
+}
+
+- (void)dealloc {
+}
+
+
+#pragma mark - PublicMethods
+// 配置
+- (void)ny_configureTTSVoiceDK {
+    QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+    [tts cancel];
+    [_player StopPlay];
+    [self setOnlineParam:tts];//在线
+}
+-(void)setOnlineParam:(QCloudTTSEngine*)ttsEngine {
+    
+    //设置合成声音速度
+    [ttsEngine setOnlineVoiceSpeed:_onlineSpeed];
+    //设置合成声音类型
+    [ttsEngine setOnlineVoiceType:_onlineVoiceType];
+    //设置合成语种
+    [ttsEngine setOnlineVoiceLanguage:_onlineLanguage];
+    //设置合成声音大小默认值为0
+    [ttsEngine setOnlineVoiceVolume:_onlineVolume];
+    //设置响应超时时间
+    [ttsEngine setTimeoutIntervalForResource:_responseTimeout];
+    //设置请求超时时间
+    [ttsEngine setTimeoutIntervalForRequest:_requestTimeout];
+    //设置检测网络间隔时间
+    [ttsEngine setCheckNetworkIntervalTime:_checkTimeout];
+    
+}
+
+- (void)setOfflineParam:(QCloudTTSEngine*)ttsEngine{
+    
+    [ttsEngine setOfflineVoiceType:_offlineVoiceType];
+    [ttsEngine setOfflineVoiceSpeed:_offlineSpeed];
+    [ttsEngine setOfflineVoiceVolume:_offlineVolume];
+    
+}
+
+//开播合成播放
+- (void)startPayVoiceActionText:(NSString *)text{
+    QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+    [self setOnlineParam:tts];
+    //设置ProjectId 不设置默认使用0,说明:项目功能用于按项目管理云资源,可以对云资源进行分项目管理,详情见 https://console.cloud.tencent.com/project
+    //[tts setOnlineProjectId:0];
+    [self stopTTSBtnAction:nil];
+    
+    _textArr = [self breakIntoSentencesFromString:text];
+    for (int i = 0; i < 10 - [_player getAudioQueueSize]; i++) {
+        if (_textArr.count > 0) {
+            [tts synthesize:_textArr[0] UtteranceId:[NSString stringWithFormat:@"%d",_cout++]];
+            [_textArr removeObjectAtIndex:0];
+        }
+    }
+}
+
+//暂停合成播放
+- (void)pausePayVoiceAction {
+    [self resumeTTSBtnAction:nil];
+}
+
+//停止合成播放
+- (void)stopPayVoiceAction {
+    [self stopTTSBtnAction:nil];
+}
+
+- (IBAction)stopTTSBtnAction:(id)sender {
+    
+    [_player StopPlay];
+    [_textArr removeAllObjects];
+    QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+    [tts cancel];
+}
+- (IBAction)pauseTTSBtnAction:(id)sender {
+    
+    [_player PausePlay];
+    
+}
+- (IBAction)resumeTTSBtnAction:(id)sender {
+    
+    [_player ResumePlay];
+    
+}
+#pragma mark - PrivateMethods
+
+- (void)initBaseData {
+    _cout = 0;
+    _textArr = [NSMutableArray array];
+    QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+    //如果使用STS临时证书鉴权时需要设置Token
+    [tts setOnlineAuthParam:QDApp_Id SecretId:QDSecret_ID SecretKey:QDSecret_Key Token:nil];
+    
+    
+    [tts engineInit:0 Delegate:self];
+    [tts setEnableDebugLog:YES];
+    
+    //SDK 内置播放器
+    _player = [[QCloudMediaPlayer alloc]init];
+    
+    // demo 层播放器,如SDK播放器不能满足需求 可以自定义播放器 如下只是一个例子 源码在MediaPlayerDemo.m文件 可自行修改
+    //_player = [[MediaPlayerDemo alloc]init];
+    
+    _player.playerDelegate = self;
+    //离线参数
+    
+    //在线参数
+    _onlineSpeed = 0;
+    _onlineVoiceType = 1001;
+    //主语言类型:1-中文(默认)2-英文
+    _onlineLanguage = 1;
+    _onlineVolume = 0;
+    
+    //连接超时默认15000ms(15s) 范围[500,30000] 单位ms , Mix模式下建议调小此值,以获得更好的体验
+    _responseTimeout = 15*1000;
+    //读取超时超时默认30000ms(30s) 范围[2200,60000] 单位ms, Mix模式下建议调小此值,以获得更好的体验
+    _requestTimeout = 30 * 1000;
+    
+    
+    //离线参数,如果您下载的是在线版SDK,以下参数不需要设置,请忽略
+    _offlineSpeed = 1.0;//离线语速[0.5,2.0]
+    //voiceType 离线音色名称,名称配置位于音色资源目录tts_resource\voices\config.json 中,可自行增删音色
+    _offlineVoiceType = @"pb";
+    _offlineVolume = 1.0;//离线音量 > 0
+    
+    
+    /*_checkTimeout     大于等于0 单位s, 等于0时持续检测,直到成功
+    Mix模式下,已经连接网络,但出现网络错误后的检测间隔时间,用于从离线模式自动切换回在线模式,默认值5分钟
+    注意:每次检测时将使用所入参的一句文本请求服务器,如果后端合成成功将会额外消耗该句字数的合成额度
+    */
+    _checkTimeout = 300;
+    
+}
+
+#pragma mark -- QCloudTTSEngineDelegate
+//合成结果返回
+//---------QCloudTTSEngineDelegate---------
+/// 合成回调
+/// @param data 语音数据
+/// @param utteranceId 语句id
+/// @param text 文本
+/// @param type 引擎类型 0:在线 1:离线
+///
+-(void) onSynthesizeData:(NSData *_Nullable)data UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text EngineType:(NSInteger)type RequestId:(NSString*)requestId{
+    
+    NSLog(@"text====%@,utteranceId ==%@,type==%ld,requestId=%@",text,utteranceId,(long)type,requestId);
+    [_player enqueueWithData:data Text:text UtteranceId:utteranceId];
+    
+//    //通过保存音频的URL播放
+//    //NSString *str = [self filePathWithName:@"tmp.mp3"];
+//    //NSURL * url = [NSURL URLWithString:str];
+//    //[_player enqueueWithFile:url Text:text UtteranceId:utteranceId];
+//
+//
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n text=%@\n utteranceId=%@ requestId=%@",_messageTextView.text,text,utteranceId,requestId];
+//    [self scrollToBottom];
+//
+//    NSLog(@"onSynthesizeData %@",@(data.length));
+    
+}
+
+/// 错误回调
+/// @param error 错误信息
+/// @param utteranceId utteranceId
+/// @param text text
+-(void) onError:(TtsError *_Nullable)error UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text{
+    
+    
+//    if (error.serviceError != nil && _ttsMode == TTS_MODE_MIX) {
+//        //实际业务上判断一下,如果是混合模式下返回在线合成的后端错误码,应当忽略可不做处理
+//        //SDK内会继续调用离线合成继续工作,如果没有日志需求,这里直接return忽略即可
+//        //return;
+//    }else{
+//        QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+//        [tts cancel];
+//    }
+//
+//    NSString* msg = [NSString stringWithFormat:@"%@\n error=%@\n error.code=%@\n error.message=%@\n response = %@\n utteranceId=%@",_messageTextView.text,error.error,@(error.err_code),error.msg,error.serviceError.respose, utteranceId];
+//    _messageTextView.text = msg;
+//    [self scrollToBottom];
+//    NSLog(@"onError %@",msg);
+}
+
+
+//离线或者混合模式下,调用初始化后必须收到此回调,并且OfflineAuthInfo.err_code为0时,才可以调用合成接口,如果err_code不为0,请检查参数或者网络,重新init
+- (void)onOfflineAuthInfo:(QCloudOfflineAuthInfo * _Nonnull)OfflineAuthInfo {
+    
+//    NSString *msg = [NSString stringWithFormat:@"OfflineAuthInfo:err_code=%@,err_msg=%@\n,deviceId=%@\n,expireTime=%@\n,respose=%@\n,authVoiceList=%@",@(OfflineAuthInfo.err_code),OfflineAuthInfo.err_msg,OfflineAuthInfo.deviceId,OfflineAuthInfo.expireTime,OfflineAuthInfo.respose,OfflineAuthInfo.voiceAuthList];
+//
+//    NSLog(@"%@",msg);
+//    _messageTextView.text = msg;
+//    [self scrollToBottom];
+    
+}
+
+
+//---------QCloudPlayerDelegate---------
+//播放开始
+-(void) onTTSPlayStart{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayStart",_messageTextView.text];
+//    [self scrollToBottom];
+    NSLog(@"onTTSPlayStart");
+}
+
+//队列所有音频播放完成,音频等待中
+-(void) onTTSPlayWait{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayWait",_messageTextView.text];
+//    [self scrollToBottom];
+    NSLog(@"onTTSPlayWait");
+}
+
+//恢复播放
+-(void) onTTSPlayResume{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayResume",_messageTextView.text];
+//    [self scrollToBottom];
+    NSLog(@"onTTSPlayResume");
+}
+
+//暂停播放
+-(void) onTTSPlayPause{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayPause",_messageTextView.text];
+//    [self scrollToBottom];
+    NSLog(@"onTTSPlayPause");
+}
+//播放中止
+-(void)onTTSPlayStop{
+    
+    _cout = 0;
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayStop",_messageTextView.text];
+//    [self scrollToBottom];
+    NSLog(@"onTTSPlayStop");
+    
+}
+
+
+//播放器异常
+-(void)onTTSPlayError:(QCPlayerError* _Nullable)playError{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n playError.code==%@\n playError.massage==%@",_messageTextView.text,@(playError.mCode),playError.message];
+//    [self scrollToBottom];
+    NSLog(@"playError.code==%@,playError.massage==%@",@(playError.mCode),playError.message);
+    
+}
+//即将播放播放下一句,即将播放音频对应的句子,以及这句话utteranceId
+/// 即将播放播放下一句,即将播放音频对应的句子,以及这句话utteranceId
+/// @param text 当前播放句子的文本
+/// @param utteranceId 当前播放音频对应的ID
+-(void) onTTSPlayNextWithText:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n text==%@\n utteranceId==%@",_messageTextView.text,text,utteranceId];
+//    NSLog(@"text==%@,utteranceId==%@",text,utteranceId);
+//    [self scrollToBottom];
+//    QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
+//    if ([_player getAudioQueueSize] < 10) {
+//
+//        if (_textArr.count > 0) {
+//
+//            NSLog(@"AudioQueueSize=%@",@([_player getAudioQueueSize]));
+//            [tts synthesize:_textArr[0] UtteranceId:[NSString stringWithFormat:@"%d",_cout++]];
+//            [_textArr removeObjectAtIndex:0];
+//        }
+//    }
+}
+/// 当前播放的字符,当前播放的字符在所在的句子中的下标.
+/// @param currentWord 当前读到的单个字,是一个估算值不一定准确
+/// @param currentIdex 当前播放句子中读到文字的下标
+-(void)onTTSPlayProgressWithCurrentWord:(NSString*_Nullable)currentWord CurrentIndex:(NSInteger)currentIdex{
+    
+//    _messageTextView.text = [NSString stringWithFormat:@"%@\n CurrentWord==%@\n currentIdex==%@",_messageTextView.text,currentWord,@(currentIdex)];
+//    NSLog(@"CurrentWord==%@,currentIdex==%@",currentWord,@(currentIdex));
+//    [self scrollToBottom];
+    
+}
+
+/*===============================使用自定义分割逻辑,以下为句子分割示例=====================*/
+#define Sentence_Count_Max 50   //单次最大请求字数,建议首句不要设置太长
+/*
+ API最大请求字数详见官网文档https://cloud.tencent.com/document/product/1073/37995
+ 
+ */
+
+- (NSMutableArray *)breakIntoSentencesFromString:(NSString *)string
+{
+    NSMutableArray *stringsArr = [NSMutableArray array];
+    
+    NSString *splitString = @",;,;";
+    //先按句子分割
+    [string enumerateSubstringsInRange:NSMakeRange(0, string.length) options:NSStringEnumerationBySentences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
+        //后台接收字符不能太长
+        const char *commitChar = [substring UTF8String];
+        if (strlen(commitChar) > Sentence_Count_Max * 3) { //UTF-8中文的字符长度一般是3个字节,英文的长度为1
+            //再按分号逗号分割
+            NSArray *textArr = [self separatedString:substring split:splitString];
+            for (NSString *object in textArr) {
+                //再按字数分割
+                const char *objectChar = [object UTF8String];
+                if (strlen(objectChar) > Sentence_Count_Max * 3) {
+                    NSString *remainStr = object;
+                    while (remainStr.length > Sentence_Count_Max) {
+                        NSString *sentence = [remainStr substringToIndex:Sentence_Count_Max];
+                        if (![self isAllSplitString:sentence split:splitString]
+                            &&![self isPunct:sentence]) {
+                            [stringsArr addObject:sentence];
+                        }
+                        remainStr = [remainStr substringFromIndex:Sentence_Count_Max];
+                    }
+                    if (![self isAllSplitString:remainStr split:splitString]
+                        &&![self isPunct:remainStr]) {
+                        [stringsArr addObject:remainStr];
+                    }
+                }
+                else {
+                    if (![self isAllSplitString:object split:splitString]
+                        &&![self isPunct:object]) {
+                        [stringsArr addObject:object];
+                    }
+                }
+            }
+        }else{
+            if (![self isAllSplitString:substring split:splitString]
+                &&![self isPunct:substring]) {
+                [stringsArr addObject:substring];
+            }
+        }
+    }];
+    
+    return stringsArr;
+}
+
+
+- (NSArray *)separatedString:(NSString *)text split:(NSString *)split {
+    NSMutableArray *mArray = [NSMutableArray array];
+    NSInteger loc = 0;
+    for (NSInteger i = 0; i < [text length]; i++) {
+        if ([split rangeOfString:[text substringWithRange:NSMakeRange(i, 1)]].location != NSNotFound) {
+            NSString *subString = [text substringWithRange:NSMakeRange(loc, i-loc+1)];
+            [mArray addObject:subString];
+            loc = i + 1;
+        }
+        if (i + 1 == [text length] && [split rangeOfString:[text substringWithRange:NSMakeRange(i, 1)]].location == NSNotFound) { //判断最后一个字符是否包含分隔符,如果不包含把最后一句添加到数组
+            NSString *subString = [text substringWithRange:NSMakeRange(loc, i-loc+1)];
+            [mArray addObject:subString];
+        }
+    }
+    return [mArray copy];
+}
+- (BOOL)isAllSplitString:(NSString *)text split:(NSString *)split
+{
+    split = @",;,;。";
+    if ([text length] && [split length]) {
+        BOOL all = YES;
+        for (NSInteger i = 0; i < [text length]; i++) {
+            if ([split rangeOfString:[text substringWithRange:NSMakeRange(i, 1)]].location == NSNotFound) {
+                all = NO;
+                break;
+            }
+        }
+        return all;
+    }
+    else {
+        return NO;
+    }
+}
+
+
+-(BOOL)isPunct:(NSString *)string //校验是否全为符号
+{
+    NSError *error = nil;
+    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[\\p{P}~^<>]" options:NSRegularExpressionCaseInsensitive error:&error];
+
+    NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:@""];
+    
+    NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+    NSString *trimmedStr = [modifiedString stringByTrimmingCharactersInSet:set];
+    if (!trimmedStr.length) {
+        return YES;
+    }
+    return NO;
+}
+
+
+@end

+ 4 - 1
jiaPei/OLD/Util/WXPay/payRequsestHandler.h

@@ -53,6 +53,9 @@
 //支付结果回调页面(后台会给你)
 #define NOTIFY_URL      @"这里填写后台给你的微信支付的后台接口网址"
 
+#define QDApp_Id     1305573081
+#define QDSecret_ID     @"AKIDJoy2xuMlHAB0nXAf3Phy34yuiSIdr8LU"     //语音
+#define QDSecret_Key    @"97tU0Tnz3xiKk9qT6pL0jijZL3kGbkhV"         //语音key
 
 
 @interface payRequsestHandler : NSObject{
@@ -80,4 +83,4 @@
 //签名实例测试
 - ( NSMutableDictionary *)sendPay_demo;
 
-@end
+@end

+ 3 - 1
jiaPei/PrefixHeader.pch

@@ -25,7 +25,8 @@
 #import <Foundation/Foundation.h>
 #import <UIKit/UIKit.h>
 #import <QMUIKit/QMUIKit.h>
-
+#import <QCloudTTS/QCloudTTSEngine.h>
+#import <QCloudTTS/QCloudMediaPlayer.h>
 
 
 #pragma mark - Vendors
@@ -92,6 +93,7 @@
 #import "CheckBodyManager.h"
 #import "RQADViewManager.h"
 #import "NYADViewManager.h"
+#import "NYVoiceManager.h"
 #import "UIFormatter.h"
 #import "RQConstant.h"
 #import "UserInfo.h"

+ 25 - 0
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCPlayerError.h

@@ -0,0 +1,25 @@
+//
+//  QPlayerError.h
+//  cloud-tts-sdk-ios
+//
+//  Created by renqiu on 2022/1/11.
+//
+
+#import <Foundation/Foundation.h>
+
+typedef NS_ENUM (NSInteger,QCPlayerErrorCode){
+    
+       QPLAYER_ERROR_CODE_EXCEPTION = -201,
+       QPLAYER_ERROR_CODE_PLAY_QUEUE_IS_FULL = -202,
+       QPLAYER_ERROR_CODE_AUDIO_READ_FAILEDL = -203,
+       QPLAYER_ERROR_CODE_UNKNOW = -204,
+    
+};
+@interface QCPlayerError : NSObject
+@property (nonatomic, assign) NSInteger mCode;
+@property (nonatomic,copy)NSString *message;
+@property (nonatomic,strong)NSError *errorMessage;
++(instancetype)getQCPlayerErrorWithMcode:(NSInteger)mCode ErrorMessage:(NSError*)errorMessage;
+@end
+
+

+ 74 - 0
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudMediaPlayer.h

@@ -0,0 +1,74 @@
+//
+//  QCloudMediaPlayer.h
+//  cloud-tts-sdk-ios
+//
+//  Created by renqiu on 2022/1/11.
+//
+
+#import <Foundation/Foundation.h>
+#import <QCloudTTS/QCPlayerError.h>
+
+@protocol QCloudPlayerDelegate <NSObject>
+//播放开始
+-(void) onTTSPlayStart;
+
+//队列所有音频播放完成,音频等待中
+-(void) onTTSPlayWait;
+
+//恢复播放
+-(void) onTTSPlayResume;
+
+//暂停播放
+-(void) onTTSPlayPause;
+
+//播放中止
+-(void)onTTSPlayStop;
+
+//即将播放播放下一句,即将播放音频对应的句子,以及这句话utteranceId
+/// 即将播放播放下一句,即将播放音频对应的句子,以及这句话utteranceId
+/// @param text 当前播放句子的文本
+/// @param utteranceId 当前播放音频对应的ID
+-(void) onTTSPlayNextWithText:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId;
+
+
+
+//播放器异常
+-(void)onTTSPlayError:(QCPlayerError* _Nullable)playError;
+
+/// 当前播放的字符,当前播放的字符在所在的句子中的下标.
+/// @param currentWord 当前读到的单个字,是一个估算值不一定准确
+/// @param currentIdex 当前播放句子中读到文字的下标
+-(void)onTTSPlayProgressWithCurrentWord:(NSString*_Nullable)currentWord CurrentIndex:(NSInteger)currentIdex;
+
+
+@end
+/// <#Description#>
+@interface QCloudMediaPlayer : NSObject
+@property (assign,nonnull)id <QCloudPlayerDelegate>playerDelegate;
+//
+/// 数据入队列
+/// @param data 加入队列的音频
+/// @param text 音频对应的文本
+/// @param utteranceId 音频对应的ID
+-(void)enqueueWithData:(NSData* _Nonnull )data Text:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId;
+/// 数据入队列
+/// @param file 加入队列的音频文件
+/// @param text 音频文件对应的文本
+/// @param utteranceId 音频文件对应的ID
+-(void)enqueueWithFile:(NSURL* _Nullable)file Text:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId;
+//
+/// 停止播放
+-(QCPlayerError* _Nullable)StopPlay;
+/// 暂停播放
+-(QCPlayerError* _Nullable)PausePlay;
+/// 恢复播放
+-(QCPlayerError* _Nullable)ResumePlay;
+-(NSInteger)getAudioQueueSize;
+
+@end
+
+
+@interface QCloudTTSProxy : NSProxy
+- (instancetype _Nullable )initWithObjc:(id _Nullable)object;
+@end
+

+ 35 - 0
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudMediaPlayer2.h

@@ -0,0 +1,35 @@
+//
+//  QCloudMediaPlayer.h
+//  cloud-tts-sdk-ios
+//
+//  Created by renqiu on 2022/1/11.
+//
+
+#import <Foundation/Foundation.h>
+#import <QCloudTTS/QCPlayerError.h>
+#import <QCloudTTS/QCloudMediaPlayer.h>
+
+/// <#Description#>
+@interface QCloudMediaPlayer2 : NSObject
+@property (weak)id <QCloudPlayerDelegate> _Nullable playerDelegate;
+//
+/// 数据入队列
+/// @param data 加入队列的音频
+/// @param text 音频对应的文本
+/// @param utteranceId 音频对应的ID
+-(void)enqueueWithData:(NSData* _Nonnull )data Text:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId;
+/// 数据入队列
+/// @param file 加入队列的音频文件
+/// @param text 音频文件对应的文本
+/// @param utteranceId 音频文件对应的ID
+-(void)enqueueWithFile:(NSURL* _Nullable)file Text:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId;
+//
+/// 停止播放
+-(QCPlayerError* _Nullable)StopPlay;
+/// 暂停播放
+-(QCPlayerError* _Nullable)PausePlay;
+/// 恢复播放
+-(QCPlayerError* _Nullable)ResumePlay;
+-(NSInteger)getAudioQueueSize;
+
+@end

+ 48 - 0
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudOfflineAuthInfo.h

@@ -0,0 +1,48 @@
+//
+//  QCloudOfflineAuthInfo.h
+//  QCloudTTS
+//
+//  Created by dgw on 2022/6/15.
+//
+
+#import <Foundation/Foundation.h>
+/*如果您下载的是在线版TTS SDK ,请忽略此接口文件*/
+NS_ASSUME_NONNULL_BEGIN
+
+// 离线授权错误吗
+typedef NS_ENUM(NSInteger, AuthErrorCode) {
+    OFFLINE_AUTH_SUCCESS = 0,//"Auth Success"
+    
+    OFFLINE_AUTH_NETWORK_CONNECT_FAILED = -10,//"Network connect failed."
+    OFFLINE_AUTH_NETWORK_SERVER_AUTH_FAILED = -11,//"Server Authorization Error !See Response Message."
+
+    OFFLINE_AUTH_PARAMETERS_ERROR = -12,//"Parameter cannot be empty."
+    OFFLINE_AUTH_PACKAGENAME_ERROR = -13,//"Authorization package name error."
+    OFFLINE_AUTH_DEVICE_ID_ERROR = -14,//"Authorization device ID error."
+    OFFLINE_AUTH_GET_DEVICE_ID_FAILED = -15,//"The device is abnormal and the device ID cannot be obtained."
+    OFFLINE_AUTH_PLATFORM_ERROR = -16,//"The platform is not authorized."
+    OFFLINE_AUTH_BIZCODE_ERROR = -17,//"License business does not match."
+    OFFLINE_AUTH_EXPIRED = -18,//"Authorization has expired.")
+    OFFLINE_AUTH_JSON_PARSE_FAILED = -19,//"JSON Parsing Error."
+    OFFLINE_AUTH_DECODE_ERROR = -20,//"Could not decode license, please check input parameters."
+    OFFLINE_AUTH_UNKNOWN_ERROR = -21,//"Unknown authorization error."
+
+};
+// 离线授权信息类
+@interface QCloudOfflineAuthInfo : NSObject
+
+@property (nonatomic, copy, nullable) NSString*  respose; //使用在线拉取授权时,服务器返回到json数据
+
+@property (nonatomic, assign) AuthErrorCode err_code; //错误码
+@property (nonatomic, copy, nullable) NSString*  err_msg; //错误信息
+
+@property (nonatomic, copy, nullable) NSString*  deviceId; //设备id
+@property (nonatomic, copy, nullable) NSString*  expireTime; //到期时间
+@property (nonatomic, copy, nullable) NSString*  voiceAuthList; //已授权的音色名列表,用分号隔开
+
++(instancetype _Nonnull )getQCloudOfflineAuthInfo:(AuthErrorCode)err_code Respose:(NSString*_Nullable)respose;
+
++(NSString* _Nonnull )getErrorMsg:(AuthErrorCode)code;
+@end
+
+NS_ASSUME_NONNULL_END

+ 222 - 0
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/QCloudTTSEngine.h

@@ -0,0 +1,222 @@
+//
+//  QCloudTTSEngine.h
+//  cloud-tts-sdk-ios
+//
+//  Created by dgw on 2022/1/10.
+//
+
+#import <Foundation/Foundation.h>
+#import <QCloudTTS/TtsError.h>
+#import <QCloudTTS/QCloudOfflineAuthInfo.h>
+
+
+typedef NS_ENUM(NSUInteger, TtsMode) {
+    TTS_MODE_ONLINE = 0, //在线模式
+    TTS_MODE_OFFLINE = 1, //离线模式
+    TTS_MODE_MIX = 2   //离在线混合模式
+};
+
+
+
+/// 回调接口
+@protocol QCloudTTSEngineDelegate <NSObject>
+
+@optional
+/// 合成结果回调
+/// @param data 音频数据
+/// @param utteranceId  utteranceId
+/// @param text  text
+/// @param type 该句话是以何种引擎生成的:0:在线 1:离线
+/// @deprecated
+-(void) onSynthesizeData:(NSData *_Nullable)data UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text EngineType:(NSInteger)type;
+
+/// 合成结果回调
+/// @param data 音频数据
+/// @param utteranceId  utteranceId
+/// @param text  text
+/// @param type 该句话是以何种引擎生成的:0:在线 1:离线
+/// @param requestId 请求ID,仅engineType为0时不为nil,用于排查问题
+-(void) onSynthesizeData:(NSData *_Nullable)data UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text EngineType:(NSInteger)type RequestId:(NSString* _Nullable)requestId;
+
+/// 合成结果回调
+/// @param data 音频数据
+/// @param utteranceId  utteranceId
+/// @param text  text
+/// @param type 该句话是以何种引擎生成的:0:在线 1:离线
+/// @param respJson 请求结果
+-(void) onSynthesizeData:(NSData *_Nullable)data UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text EngineType:(NSInteger)type RequestId:(NSString* _Nullable)requestId RespJson:(NSString* _Nullable)respJson;
+
+@required
+/// 错误回调
+/// @param error 错误信息
+/// @param utteranceId utteranceId
+/// @param text text
+-(void) onError:(TtsError *_Nullable)error UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text;
+
+
+/// 返回离线合成模块授权信息,使用混合或者离线模式时,收到此方法成功回调后才可以调用合成接口
+/// 如果您下载的是在线版TTS SDK ,或者只使用在线合成模式,请忽略此方法
+/// @param OfflineAuthInfo 授权信息,当OfflineAuthInfo.err_msg为0时授权成功,详见QCloudOfflineAuthInfo.h
+-(void) onOfflineAuthInfo:(QCloudOfflineAuthInfo* _Nonnull )OfflineAuthInfo;
+
+@end
+
+
+
+/// 语音合成引擎接口
+@interface QCloudTTSEngine : NSObject
+
+
+/// 获得QCloudTTSEngine实例
++(id _Nullable )getShareInstance;
+
+/// 销毁QCloudTTSEngine实例
++(void) instanceRelease;
+
+
+/// 初始化引擎
+/// @param mode 引擎模式,在线、离线、混合,如切换引擎,需要先执行instanceRelease
+/// @param delegate 用于接收结果的代理
+-(void) engineInit:(TtsMode)mode Delegate:(id<QCloudTTSEngineDelegate> _Nonnull) delegate;
+
+
+/// 取消合成,清空内部合成队列
+-(TtsError *_Nullable) cancel;
+
+/// 合成接口,支持持续调用添加文本
+/// @param text 需要合成的文本
+/// @param utteranceId  用于标记文本的id,合成完成后随音频文件或者错误接口返回,可为空
+-(TtsError *_Nullable) synthesize:(NSString *_Nonnull)text UtteranceId:(NSString *_Nullable)utteranceId;
+
+
+
+
+
+/// 配置在线引擎鉴权参数
+/// @param appId   appId
+/// @param secretId  secretId
+/// @param secretKey  secretKey
+/// @param token  token,可为空,如果使用sts临时证书鉴权,secretId和secretKey均入参临时的,同时需要入参对应的token,
+/// sts临时证书具体详见https://cloud.tencent.com/document/product/598/33416 (开发调试时建议先用普通方式鉴权,token填nil)
+-(void) setOnlineAuthParam:(NSInteger)appId SecretId:(NSString* _Nonnull)secretId SecretKey:(NSString* _Nonnull)secretKey Token:(NSString* _Nullable)token;
+
+
+
+///online语音相关设置
+
+/// 设置在线语速,对setOnlineParam的封装
+/// @param voiceSpeed 默认0,代表正常速度
+-(void)setOnlineVoiceSpeed:(float)voiceSpeed;
+
+/// 设置在线音色ID,对setOnlineParam的封装
+/// @param voiceType 默认1001,音色id可查看官网文档https://cloud.tencent.com/document/product/1073/37995
+-(void)setOnlineVoiceType:(int)voiceType;
+
+/// 设置在线引擎音量,对setOnlineParam的封装
+/// @param voiceVolume   默认0,代表正常音量,没有静音选项
+-(void)setOnlineVoiceVolume:(float)voiceVolume;
+
+/// 设置主语言类型,对setOnlineParam的封装
+/// @param primaryLanguage  1:中文 2:英文 默认1
+-(void)setOnlineVoiceLanguage:(int)primaryLanguage;
+
+///在线编码格式,如无业务特殊需求不建议更改(默认"mp3",目前支持"mp3","wav","pcm",若更改为pcm不支持直接播放,对setOnlineParam的封装
+-(void)setOnlineCodec:(NSString* _Nonnull) code;
+
+/// 项目ID
+/// @param projectId  默认0, 对setOnlineParam的封装
+-(void)setOnlineProjectId:(int)projectId;
+
+/// 是否开启时间戳功能,默认为false,对setOnlineParam的封装
+- (void)setOnlineEnableSubtitle:(Boolean)val;
+
+/// 断句敏感阈值,默认值为:0,对setOnlineParam的封装
+- (void)setOnlineSegmentRate:(int)val;
+
+/// 控制合成音频的情感,仅支持多情感音色使用,对setOnlineParam的封装
+- (void)setOnlineEmotionCategory:(NSString* _Nullable)val;
+
+/// 控制合成音频情感程度,对setOnlineParam的封装
+- (void)setOnlineEmotionIntensity:(int)val;
+
+/// 设置自定义参数,可使用该方法控制请求时的参数
+/// @param value为nil时将删除参数,否则会在请求中添加参数
+- (void)setOnlineParam:(NSString* _Nonnull)key value:(NSObject* _Nullable)value;
+
+/// 设置区域
+/// @param region 默认为ap-shanghai,无特殊需求请勿更改
+- (void)setOnlineRegion:(NSString *)region;
+
+//设置是否输出日志
+-(void)setEnableDebugLog:(BOOL)enableDebugLog;
+
+
+
+
+/// timeoutIntervalForRequest ,0.5s - 30s 默认15000ms(15s)
+/// @param timeout [2200,60000] 单位ms
+- (void)setTimeoutIntervalForRequest:(int)timeout;
+
+
+/// timeoutIntervalForResource  2.2s - 60s  默认30000ms(30s)
+/// @param timeout   [500,30000] 单位ms
+-(void)setTimeoutIntervalForResource:(int) timeout;
+
+
+/// Mix模式下,出现网络错误后的检测间隔时间, 默认值5分钟
+///注意:每次检测时将使用所入参的一句文本请求服务器,如果后端合成成功将会额外消耗该句字数的合成额度
+/// @param checkNetworkIntervalTime 大于等于0 单位s, 等于0时持续检测,直到成功
+-(void)setCheckNetworkIntervalTime:(int) checkNetworkIntervalTime;
+
+
+//以下为离线语音相关参数配置
+
+//resourceDir 离线资源路径
+-(void)setOfflineResourceDir:(NSString * _Nonnull) resourceDir;
+
+//voiceSpeed [0.5,2.0]
+-(void)setOfflineVoiceSpeed:(float) voiceSpeed;
+
+//voiceType 离线音色名称,名称配置位于音色资源目录\voices\config.json 中,可自行指定更多的音色,demo中仅提供"pb"、"femalen"两种
+-(void)setOfflineVoiceType:(NSString *_Nonnull)  voiceType;
+
+//voiceVolume >0
+-(void)setOfflineVoiceVolume:(float) voiceVolume;
+
+/// 配置离线TTS授权参数: 在线下载密钥(第一次激活设备需要联网)
+/// @param licPk 密钥对应的licPk,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+/// @param licKey 密钥对应的licKey,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+/// @param secretId  腾讯云secretId (可能与在线模式不是同一个账号,需要输入购买离线SDK对应的账号的secretId)
+/// @param secretKey 腾讯云 secretKey(可能与在线模式不是同一个账号,需要输入购买离线SDK对应的账号的secretKey)
+/// @param token token,可为空,如果使用sts临时证书鉴权,secretId和secretKey均入参临时的,同时需要入参对应的token,
+-(void)setOfflineAuthParamDoOnline:(NSString* _Nonnull)licPk
+                                    LicKey:(NSString* _Nonnull)licKey
+                                    SecretId:(NSString* _Nonnull)secretId
+                                    SecretKey:(NSString* _Nonnull)secretKey
+                                    Token:(NSString* _Nullable)token;
+
+/// 配置离线TTS授权参数: 在线下载密钥(第一次激活设备需要联网)
+/// @param licPk 密钥对应的licPk,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+/// @param licKey 密钥对应的licKey,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+/// @param secretId  腾讯云secretId (可能与在线模式不是同一个账号,需要输入购买离线SDK对应的账号的secretId)
+/// @param secretKey 腾讯云 secretKey(可能与在线模式不是同一个账号,需要输入购买离线SDK对应的账号的secretKey)
+/// @param token token,可为空,如果使用sts临时证书鉴权,secretId和secretKey均入参临时的,同时需要入参对应的token,
+/// @param refreshAuth  是否强制联网刷新授权(NO:仅第一次联网激活下载授权文件; YES:联网刷新授权文件,无网络下将激活失败)
+-(void)setOfflineAuthParamDoOnline:(NSString* _Nonnull)licPk
+                                    LicKey:(NSString* _Nonnull)licKey
+                                    SecretId:(NSString* _Nonnull)secretId
+                                    SecretKey:(NSString* _Nonnull)secretKey
+                                    Token:(NSString* _Nullable)token
+                                    RefreshAuth:(BOOL)refreshAuth;
+
+
+/// 配置离线TTS授权参数: 直接传入密钥(第一次激活也不需要联网)
+/// @param lic 授权密钥 ,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+/// @param licPk 该密钥对应的licPk,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+/// @param licSign 该密钥对应的licSign,请在腾讯云官网页面获取,或者由腾讯云商务线下下发
+-(void)setOfflineAuthParamDoOffline:(NSString* _Nonnull)lic
+                              LicPk:(NSString* _Nonnull)licPk
+                            LicSign:(NSString* _Nonnull)licSign;
+@end
+
+

+ 70 - 0
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Headers/TtsError.h

@@ -0,0 +1,70 @@
+//
+//  TtsError.h
+//  cloud-tts-sdk-ios
+//
+//  Created by dgw on 2022/1/10.
+//
+
+#ifndef TtsError_h
+#define TtsError_h
+
+#import <Foundation/Foundation.h>
+
+typedef NS_ENUM(NSInteger, TtsErrorCode) {
+    
+    TTS_ERROR_CODE_UNINITIALIZED = -100, //Engine uninitialized
+    TTS_ERROR_CODE_GENERATE_SIGN_FAIL = -101, //generate sign failed
+    TTS_ERROR_CODE_NETWORK_CONNECT_FAILED = 102, //network connect failed
+    TTS_ERROR_CODE_DECODE_FAIL = -103, //JSON Response Parsing Error
+    TTS_ERROR_CODE_SERVER_RESPONSE_ERROR = -104, //Server response error
+    TTS_ERROR_CODE_CANCEL_FAILURE = -106, //Cancel failure,please try again later
+    
+    TTS_ERROR_CODE_OFFLINE_FAILURE = -107,//Offline synthesize failed, please check your text and VoiceType
+    TTS_ERROR_CODE_OFFLINE_INIT_FAILURE = -108,//Offline engine initialization failed, please check resource files
+    TTS_ERROR_CODE_OFFLINE_AUTH_FAILURE = -109,//Offline engine auth failure
+    TTS_ERROR_CODE_OFFLINE_TEXT_TOO_LONG = -110, //Offline synthesize failed,text too long,MAX <= 1024 byte
+    TTS_ERROR_CODE_OFFLINE_VOICE_AUTH_FAILURE = -111, //This voice not authorized, please change it
+    
+    TTS_ERROR_CODE_OFFLINE_NOSUPPORT = -900 //This SDK only supports online mode
+};
+    
+
+
+
+
+
+/// 后端返回的错误信息
+@interface TtsServiceError : NSObject
+
+@property (nonatomic, copy) NSString*  _Nullable err_code;
+@property (nonatomic, copy) NSString*  _Nullable msg;
+@property (nonatomic, copy) NSString*  _Nullable respose;
+
++(instancetype _Nonnull)getTtsServiceError:(NSString *_Nullable)err_code ErrorMsg:(NSString*  _Nullable)msg Respose:(NSString*  _Nullable)respose;
+
+@end
+
+
+/// 错误信息类
+@interface TtsError : NSObject
+
+@property (nonatomic, assign) TtsErrorCode err_code; //错误码
+
+@property (nonatomic, copy, nullable) NSString*  msg; //错误信息
+
+@property (nonatomic, copy, nullable) NSError *  error; //系统抛出的错误信息(不一定有,可能为空)
+
+@property (nonatomic, strong ,nullable) TtsServiceError *  serviceError;//服务器返回的错误信息(不一定有,可能为空)
+
++(instancetype _Nonnull)getTtsError:(TtsErrorCode)err_code
+                        TtsServiceError:(TtsServiceError* _Nullable)serviceError
+                        NSErrorMsg:(NSError *_Nullable)error;
+@end
+
+
+
+
+
+
+
+#endif /* TtsError_h */

二进制
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/Info.plist


二进制
jiaPei/Vendor/QCloudTTSSDK/QCloudTTS.framework/QCloudTTS