184FFC492C218FC4006F664D /* PlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184FFC482C218FC4006F664D /* PlayerManager.swift */; };
184FFC4D2C2199E5006F664D /* SendToolBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184FFC4C2C2199E5006F664D /* SendToolBar.swift */; };
184FFC512C21A4EB006F664D /* TtsLongViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184FFC502C21A4EB006F664D /* TtsLongViewController.swift */; };
+ 18ABF57A2C3F884600C60E9B /* 2.pcm in Resources */ = {isa = PBXBuildFile; fileRef = 18ABF5792C3F884600C60E9B /* 2.pcm */; };
18B74A212C201CD600FABBA9 /* TtsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B74A202C201CD600FABBA9 /* TtsViewController.swift */; };
18B74A242C201CE900FABBA9 /* SttViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B74A232C201CE900FABBA9 /* SttViewController.swift */; };
18B74A262C201EBD00FABBA9 /* ChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B74A252C201EBD00FABBA9 /* ChatViewController.swift */; };
184FFC482C218FC4006F664D /* PlayerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerManager.swift; sourceTree = "<group>"; };
184FFC4C2C2199E5006F664D /* SendToolBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendToolBar.swift; sourceTree = "<group>"; };
184FFC502C21A4EB006F664D /* TtsLongViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TtsLongViewController.swift; sourceTree = "<group>"; };
+ 18ABF5792C3F884600C60E9B /* 2.pcm */ = {isa = PBXFileReference; lastKnownFileType = file; path = 2.pcm; sourceTree = "<group>"; };
18B74A202C201CD600FABBA9 /* TtsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TtsViewController.swift; sourceTree = "<group>"; };
18B74A232C201CE900FABBA9 /* SttViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SttViewController.swift; sourceTree = "<group>"; };
18B74A252C201EBD00FABBA9 /* ChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewController.swift; sourceTree = "<group>"; };
18FF930A2C39263A0006452C /* cat.png */,
18C42B582C24166D000D8860 /* input.msbc */,
181188592C1BE80B00C23FAB /* 1.pcm */,
+ 18ABF5792C3F884600C60E9B /* 2.pcm */,
18C8561E2C3B81B800EAE874 /* tts.mp3 */,
);
path = Resource;
18204BE02C193F9D00F94E69 /* LaunchScreen.storyboard in Resources */,
18C856202C3B81B900EAE874 /* tts.mp3 in Resources */,
18204BDD2C193F9D00F94E69 /* Assets.xcassets in Resources */,
+ 18ABF57A2C3F884600C60E9B /* 2.pcm in Resources */,
18204BDB2C193F9A00F94E69 /* Main.storyboard in Resources */,
18C42B592C24166D000D8860 /* input.msbc in Resources */,
);
func sendRecordToolBar(_ toolBar: SendRecordToolBar, _ text: String) {
textView.text += "[send] " + text + "\n"
-
let range = NSMakeRange(textView.text.count - 1, 1)
textView.scrollRangeToVisible(range)
- let content = text
+
view.makeToastActivity(.center)
- MixSdk.shared.chatGpt.send(content: content, useModel: "gpt-3.5-turbo") {[weak self] response, error in
+ MixSdk.shared.chatGpt.send(content: text, useModel: "gpt-3.5-turbo") {[weak self] response, error in
guard let self = self else {return}
self.view.hideToastActivity()
if let model = response,let choices = model.choices.first {
self.view.backgroundColor = .white
let recordBtn = UIButton(type: .custom)
- recordBtn.setTitle("start record", for: .normal)
- recordBtn.setTitle("stop record", for: .selected)
+ recordBtn.setTitle("按住说话", for: .normal)
+ recordBtn.setTitle("松开结束", for: .highlighted)
recordBtn.setTitleColor(.white, for: .normal)
recordBtn.backgroundColor = .blue
- recordBtn.addTarget(self, action: #selector(recordAction(button:)), for: .touchUpInside)
+ let longTap = UILongPressGestureRecognizer(target: self, action: #selector(recordLongPressAction(press:)))
+ recordBtn.addGestureRecognizer(longTap)
view.addSubview(recordBtn)
recordBtn.snp.makeConstraints { make in
make.width.centerX.equalToSuperview()
MixSdk.shared.stt.eventCallBack = {[weak self] event in
guard let self = self else {return}
if event.event == "TranscriptionStarted" {
- //2
- self.startTask()
+ print("开始已任务,可以开始录音")
+ //2、开启录音
+ recordMamager.start()
}
else if event.event == "TranscriptionCompleted"{
- //6
- self.endTask()
+ //6、结束任务
+ print("结束已任务")
}
else if event.event == "SentenceEnd",let text = event.result?.result{
- //4
+ //4、识别到完整的句子
self.textView.text += text + "\n"
let range = NSMakeRange(textView.text.count - 1, 1)
self.textView.scrollRangeToVisible(range)
recordMamager.recordDataCallBack = {[weak self] data in
guard let self = self else {return}
if MixSdk.shared.chat.connectState == .connected {
+ //3、发送录音数据
MixSdk.shared.stt.sendVoice(pcmData: data)
}
else{
- //"断开连接"
+ //断开连接,不发送数据
}
}
}
}
extension SttViewController{
- @objc func recordAction(button:UIButton){
- button.isSelected = !button.isSelected
- if button.isSelected {
- //1
- MixSdk.shared.stt.startTranscription()
- }
- else{
- //5
- recordMamager.stop()
- MixSdk.shared.stt.stopTranscription()
- }
- }
- //3
- @objc func startTask(){
- print("开始录音")
- recordMamager.start()
- }
- //7
- @objc func endTask(){
- print("结束录音")
+ @objc func recordLongPressAction(press longTap:UILongPressGestureRecognizer){
+ if longTap.state == .began {
+ view.makeToastActivity(.center)
+ //1、发送开始任务请求
+ MixSdk.shared.stt.startTranscription()
+ }else if longTap.state == .ended {
+ //5、发送结束任务请求
+ recordMamager.stop()
+ MixSdk.shared.stt.stopTranscription()
+ view.hideToastActivity()
+ }
}
}
import MixSdk
import SnapKit
import Toast_Swift
-class TtsFileViewController: UIViewController{
+class SttFileViewController: UIViewController{
var isRecord = false;
let textView = UITextView()
}
-extension TtsFileViewController{
+extension SttFileViewController{
@objc func selectFileAction() {
view.makeToastActivity(.center)
guard let path = Bundle.main.path(forResource: "1", ofType: "pcm") else {return}
self.view.makeToast("unAuthorized!")
return;
}
- let vc = TtsFileViewController()
+ let vc = SttFileViewController()
self.navigationController?.pushViewController(vc, animated: true)
}
@objc func sttAction() {
return result
}
+
+ /// sbc转pcm
+ /// - Parameters:
+ /// - sbcPath: sbc文件路径
+ /// - pcmPath: pcm文件路径
+ /// - Returns: 转换结果
+ public static func sbcToPcm(sbcPath:String,pcmPath:String)->Bool {
+ guard let sbcData = MSTool.readFile(from: sbcPath) else{
+ return false
+ }
+ let pcmData = sbcTopcm(sbcData)
+ return MSTool.saveToFile(data: pcmData, path: pcmPath)
+ }
+
/// sbc转mp3
/// - Parameters:
/// - pcmPath: sbc文件路径
}
- public static func sbcToMp3(sbcData:Data,mp3Path:String)->Bool {
+ static func sbcToMp3(sbcData:Data,mp3Path:String)->Bool {
let pcmData = self.sbcTopcm(sbcData)
let pcmPath = NSTemporaryDirectory() + "temp.pcm"
@interface AudioTransform : NSObject
-//+ (BOOL)transformToMp3FromPath:(NSString *)originalPath
-// toMp3Path:(NSString *)mp3Path;
-
+ (BOOL)convertPcm:(NSString *)pcmPath toMp3:(NSString *)mp3Path;
@end
@implementation AudioTransform
-+ (BOOL)transformToMp3FromPath:(NSString *)originalPath
- toMp3Path:(NSString *)mp3Path{
- @try {
- int read, write;
-
- FILE *pcm = fopen([originalPath cStringUsingEncoding:1], "rb"); //source
- fseek(pcm, 4*1024, SEEK_CUR); //skip file header
- FILE *mp3 = fopen([mp3Path cStringUsingEncoding:1], "wb"); //output
-
- const int PCM_SIZE = 8192;
- const int MP3_SIZE = 8192;
- short int pcm_buffer[PCM_SIZE*2];
- unsigned char mp3_buffer[MP3_SIZE];
-
- lame_t lame = lame_init();
- lame_set_in_samplerate(lame, 16000);
- lame_set_num_channels(lame, 1); //声道,不设置默认为双声道
- lame_set_VBR(lame, vbr_default);
- lame_init_params(lame);
-
- do {
- read = (int)fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
- if (read == 0)
- write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
- else
- write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
-
- fwrite(mp3_buffer, write, 1, mp3);
-
- } while (read != 0);
-
- lame_close(lame);
- fclose(mp3);
- fclose(pcm);
- }
- @catch (NSException *exception) {
- NSLog(@"%@",[exception description]);
- return false;
- }
- @finally {
- return true;
- }
-
-}
-
/***
* pcm 文件转mp3文件
*/
fclose(fmp3);
fclose(fpcm);
} @catch (NSException *exception) {
- NSLog(@"catch exception, %@", exception);
+// NSLog(@"catch exception, %@", exception);
return false;
} @finally {
return true;
private func getPath()->String{
-// let path = NSHomeDirectory() + "/Documents/IOTBluetooth/" + "\(Date().format(.middle)).log"
let foldPath = NSHomeDirectory() + "/Documents/MixSdk/"
let fileManager = FileManager.default
if !fileManager.fileExists(atPath: foldPath) {