func startTimer() {
deinitTimer()
- self.timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: false, block: { [unowned self] _ in
+ self.timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false, block: { [unowned self] _ in
deinitTimer()
self.completion?(.response.code(.timeout))
self.remove()
import StarburstSdk
public class DCBleManager{
-
public static let shared = DCBleManager()
private var connectPeripheral: CBPeripheral?
private var writeCha: CBCharacteristic?
if data.count > 4 && data[0] == 0xBA {
if let sender = BleSender.answer(data) {
sender.completion?(.response.code(.success).value(data))
- sender.deinitTimer()
- sender.remove()
+ if data[1] == 0x10,data[2] == 0x01{
+ //音乐列表分包,解析的时候处理
+ }
+ else{
+ sender.deinitTimer()
+ sender.remove()
+ }
return
}
else if data[1] == 0x0D{
if data[1] == 0x10,data[2] == 0x06{
DCDevice.shared.receiveNotice(data)
}
- else if data[1] == 0x0F{
- switch data[2] {
+ else if data[1] == 0x0F,data[2] == 0x0B{
+ let type = data[3]
+ switch type{
case 0x01:
DCLogger.debug("打开AI对话")
case 0x02:
default:
break
}
-
-
+ DCDevice.shared.eventCallback?(type)
+ DCDevice.shared.sendAiEventResponse(type)
}
}
static func contentData(_ data:Data)->Data{
public class DCBleRecord {
public static let shared = DCBleRecord()
/// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
- public var fromLanguage:String = ""
+ public var fromLanguage:String = "zh-CN"
/// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
- public var toLanguage:String = ""
+ public var toLanguage:String = "en-US"
/// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
public var isTranslate = false
/// 是否进⾏Tts,默认false
var translateList : [(String,Int)] = []
var translateText = ""
+ init() {
+ setupRecord()
+ }
+
func setupRecord(){
let config = StarburstAsrConfig()
config.isTranslate = isTranslate
/// 默认pcm。⽀持pcm / ogg_opus / mp3
public var ttsAudioFormat:String = "mp3"
/// 语⾔编码,默认为普通话(zh-CN)
- public var language:String = ""
+ public var language:String = "zh-CN"
+
+ init() {
+ setupChat()
+ }
}
extension DCChat{
public func getVcSpeekerList(finished:@escaping ([DCRole]?,Bool)->Void){
}
}
- public func initChat(){
+ func setupChat(){
let config = StarburstVoiceChatConfig()
config.tts = tts
config.ttsAudioFormat = ttsAudioFormat
responseCallback?(text,self.dialogId)
}
- } responseVoice: { [weak self] (dialogId,data, finish) in
+ } responseVoice: { [weak self] (dialogId,data, finish,sampleRate) in
guard let self = self else { return }
self.dialogId = dialogId
dataCallback?(dialogId,data,finish)
}
public func startChat(){
- initChat()
+ setupChat()
+ DCDevice.shared.startChat()
}
public func stopChat(){
StarburstSdk.shared().stopVoiceChat(self.dialogId)
public class DCDevice{
public static let shared = DCDevice()
+ /// ai事件回调
+ /// 0x01(打开AI对话)
+// 0x02(关闭AI对话)
+// 0x03(打开耳机录音)
+// 0x04(关闭耳机录音)
+ public var eventCallback:((UInt8)->Void)?
func receiveNotice(_ data:Data){
if data[1] == 0x10,data[2] == 0x06{
public func getBatery(finished:@escaping ((Int,Int)?)->Void){
var head: UInt8 = 0xBA
var cmd: UInt8 = 0x09
- var data:UInt8 = 00
+ var data:UInt8 = 0x00
var total = Data()
total.append(&head, count: 1)
total.append(&cmd, count: 1)
public func getSoftVersion(finished:@escaping (String?)->Void){
var head: UInt8 = 0xBA
var cmd: UInt8 = 0x0A
- var data:UInt8 = 00
+ var data:UInt8 = 0x00
var total = Data()
total.append(&head, count: 1)
total.append(&cmd, count: 1)
public func getHardVersion(finished:@escaping (String?)->Void){
var head: UInt8 = 0xBA
var cmd: UInt8 = 0x0A
- var data:UInt8 = 01
+ var data:UInt8 = 0x01
var total = Data()
total.append(&head, count: 1)
total.append(&cmd, count: 1)
}
}
+
extension DCDevice{
- public func getMusicList(size:UInt8,index:UInt16,finished:@escaping ([DCMusic]?,Bool)->Void){
- var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x01
- var pageSize = size
- var total = Data()
- total.append(&head, count: 1)
- total.append(&cmd, count: 1)
- total.append(&data, count: 1)
- total.append(&pageSize, count: 1)
- total.appendInt16(index)
- total.addCrc()
-
- let sender = BleSender()
- sender.data = total
- sender.completion = { result in
- DCLogger.debug("\(result.description)")
- if result.isSuccess{
-// let data = DCBleManager.contentData(result.data)
- let data = result.data.subdata(in: 3..<result.data.count - 3)
- let str = String(data: data, encoding: .utf8)
- DCLogger.debug(str ?? "")
- guard let list = JSON.decode([DCMusic].self, from: data) else { return }
-// var list = [DCMusic]()
- finished(list,true)
- }
- else{
- finished(nil,false)
- }
- }
- DCBleManager.shared.send(sender)
- }
-
-// 0x00:顺序循环
-// 0x01:随机
-// 0x02:单曲
- public func setMusicPlayMode(mode:UInt8,finished:@escaping (Bool)->Void){
- var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x02
- var mode:UInt8 = mode
- var total = Data()
- total.append(&head, count: 1)
- total.append(&cmd, count: 1)
- total.append(&data, count: 1)
- total.append(&mode, count: 1)
- total.addCrc()
-
- let sender = BleSender()
- sender.data = total
- sender.completion = { result in
- DCLogger.debug("\(result.description)")
- if result.isSuccess{
- let value = result.data[2].int
- DCLogger.debug(value)
- finished(value == 0)
- }
- else{
- finished(false)
- }
- }
- DCBleManager.shared.send(sender)
- }
- public func getMusicPlayMode(finished:@escaping (UInt8?,Bool)->Void){
+ //0x01(打开AI对话)
+// 0x02(关闭AI对话)
+// 0x03(打开耳机录音)
+// 0x04(关闭耳机录音)
+ func sendAiEventResponse(_ event:UInt8){
var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x03
- var content:UInt8 = 0x00
+ var cmd: UInt8 = 0x0F
+ var data:UInt8 = 0x0B
+ var content:UInt8 = event
var total = Data()
total.append(&head, count: 1)
total.append(&cmd, count: 1)
sender.data = total
sender.completion = { result in
DCLogger.debug("\(result.description)")
- if result.isSuccess{
- let value = UInt8(result.data[3].int)
- DCLogger.debug(value)
- finished(value,true)
- }
- else{
- finished(nil,false)
- }
}
DCBleManager.shared.send(sender)
+ sender.deinitTimer()//不需要回执
+ sender.remove()
}
-
- public func musicPlay(index:UInt16?,finished:@escaping (UInt16?,Bool)->Void){
- if let index = index {
- var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x05
-
- var total = Data()
- total.append(&head, count: 1)
- total.append(&cmd, count: 1)
- total.append(&data, count: 1)
- total.appendInt16(index)
- total.addCrc()
-
- let sender = BleSender()
- sender.data = total
- sender.completion = { result in
- DCLogger.debug("\(result.description)")
- if result.isSuccess{
- let value = UInt16(result.data[3...4].int)
- DCLogger.debug(value)
- finished(value,true)
- }
- else{
- finished(nil,false)
- }
- }
- DCBleManager.shared.send(sender)
- }
- else{
- var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x04
- var content:UInt8 = 0x00
-
- var total = Data()
- total.append(&head, count: 1)
- total.append(&cmd, count: 1)
- total.append(&data, count: 1)
- total.append(&content, count: 1)
- total.addCrc()
-
- let sender = BleSender()
- sender.data = total
- sender.completion = { result in
- DCLogger.debug("\(result.description)")
- if result.isSuccess{
- let value = UInt16(result.data[3...4].int)
- DCLogger.debug(value)
- finished(value,true)
- }
- else{
- finished(nil,false)
- }
- }
- DCBleManager.shared.send(sender)
- }
- }
- public func musicPause(finished:@escaping (UInt16?,Bool)->Void){
+ func startChat(){
var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x04
+ var cmd: UInt8 = 0x0F
+ var data:UInt8 = 0x0A
var content:UInt8 = 0x01
var total = Data()
total.append(&head, count: 1)
sender.data = total
sender.completion = { result in
DCLogger.debug("\(result.description)")
- if result.isSuccess{
- let value = UInt16(result.data[3...4].int)
- DCLogger.debug(value)
- finished(value,true)
- }
- else{
- finished(nil,false)
- }
}
DCBleManager.shared.send(sender)
}
- public func musicDelete(list:[UInt16],finished:@escaping (Bool)->Void){
+ func stopChat(){
var head: UInt8 = 0xBA
- var cmd: UInt8 = 0x10
- var data:UInt8 = 0x07
- var content:UInt8 = UInt8(list.count)
+ var cmd: UInt8 = 0x0F
+ var data:UInt8 = 0x0A
+ var content:UInt8 = 0x00
var total = Data()
total.append(&head, count: 1)
total.append(&cmd, count: 1)
total.append(&data, count: 1)
total.append(&content, count: 1)
- for item in list {
- total.appendInt16(item)
- }
total.addCrc()
let sender = BleSender()
sender.data = total
sender.completion = { result in
DCLogger.debug("\(result.description)")
- if result.isSuccess{
- let value = UInt16(result.data[3].int)
- DCLogger.debug(value)
- finished(value == 0)
- }
- else{
- finished(false)
- }
}
DCBleManager.shared.send(sender)
}
-
}
//
// Created by liangshi on 2025/12/17.
//
+import Foundation
public class DCMusic:Codable{
/// id
/// 时长
public var dur = 0
}
+
+extension DCDevice{
+
+ public func getTotalMusic(finished:@escaping (Int?)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x08
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[3...4].int
+ DCLogger.debug(value)
+ finished(value)
+ }
+ else{
+ finished(nil)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getMusicList(size:UInt8,index:UInt16,finished:@escaping ([DCMusic]?,Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x01
+ var pageSize = size
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&pageSize, count: 1)
+ total.appendInt16(index)
+ total.addCrc()
+
+ var totalList = [DCMusic]()
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ //let data = DCBleManager.contentData(result.data)
+ if result.data.count <= 8{
+ sender.deinitTimer()
+ sender.remove()
+ finished(nil,false)
+ return
+ }
+
+ let index = result.data[4].int
+ let total = result.data[5].int
+ DCLogger.debug(total,index)
+ let data = result.data.subdata(in: 6..<result.data.count - 3)
+ let str = String(data: data, encoding: .utf8)
+ DCLogger.debug(str ?? "")
+ guard let list = JSON.decode([DCMusic].self, from: data) else {
+ sender.deinitTimer()
+ sender.remove()
+ finished(nil,false)
+ return
+ }
+ totalList += list
+
+ if index == total {
+ sender.deinitTimer()
+ sender.remove()
+ finished(totalList,true)
+ }
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+ // 0x00:顺序循环
+ // 0x01:随机
+ // 0x02:单曲
+ public func setMusicPlayMode(mode:UInt8,finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x02
+ var mode:UInt8 = mode
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&mode, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[2].int
+ DCLogger.debug(value)
+ finished(value == 0)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getMusicPlayMode(finished:@escaping (UInt8?,Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x03
+ var content:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt8(result.data[3].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+ public func musicPlay(index:UInt16?,finished:@escaping (UInt16?,Bool)->Void){
+ if let index = index {
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x05
+
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.appendInt16(index)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3...4].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ else{
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x04
+ var content:UInt8 = 0x00
+
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3...4].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ }
+ public func musicPause(finished:@escaping (UInt16?,Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x04
+ var content:UInt8 = 0x01
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3...4].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func musicDelete(list:[UInt16],finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x07
+ var content:UInt8 = UInt8(list.count)
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ for item in list {
+ total.appendInt16(item)
+ }
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3].int)
+ DCLogger.debug(value)
+ finished(value == 0)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+}
//
import StarburstSdk
-public class DCRecord {
- public static let shared = DCRecord()
+public class DCPhoneRecord {
+ public static let shared = DCPhoneRecord()
/// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
- public var fromLanguage:String = ""
+ public var fromLanguage:String = "zh-CN"
/// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
- public var toLanguage:String = ""
+ public var toLanguage:String = "en-US"
/// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
public var isTranslate = false
/// 是否进⾏Tts,默认false
--- /dev/null
+/**
+ * 图片生成任务错误码枚举
+ */
+typedef NS_ENUM(NSInteger, AIGCErrorCode) {
+ /// 未授权访问
+ AIGCErrorUnauthorized = 401,
+ /// 调用次数或资源超出配额限制
+ AIGCErrorQuotaExceeded = 4001,
+ /// 无效的参数(如宽高非法)
+ AIGCErrorInvalidParam = -1,
+ /// 网络连接失败
+ AIGCErrorNetworkFailure = -2,
+ /// 任务已被取消
+ AIGCErrorTaskCanceled = -3,
+ /// 查询任务状态超时
+ AIGCErrorQueryTimeout = -4,
+ /// 未知错误
+ AIGCErrorUnknown = 9000
+};
@property (nonatomic, strong) NSString *msg;/// 提示语
@property (nonatomic, strong) NSString *requestId;/// 请求id
@property (nonatomic, assign) NSInteger dialogId;/// 对话id
+@property (nonatomic, assign) BOOL isAsrFinish;/// 识别是否已结束
@property (nonatomic, strong) NSString *textResult;/// 语⾳识别结果⽚段内容
@property (nonatomic, strong) NSString *responseText;/// 响应结果⽚段内容
@property (nonatomic, strong) NSString *intent;/// 意图
@property (nonatomic, assign) BOOL conversationFinish;/// 对话是否结束
@property (nonatomic, strong) StarburstTranslateResult *translateResult;///翻译结果
@property (nonatomic, strong) StarburstAsrTtsResult *ttsResult;///tts音频流
-
+@property (nonatomic, assign) NSInteger playAudioSampleRate;
@end
/// 手机录音asr配置
@interface StarburstAsrConfig : NSObject
-@property (nonatomic, assign) BOOL isTranslate;/// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
-@property (nonatomic, strong) NSString *fromLanguage;/// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
-@property (nonatomic, strong) NSString *toLanguage;/// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
-@property (nonatomic, assign) BOOL isTTs;/// 是否进⾏Tts,默认false
-@property (nonatomic, strong) NSString *ttsFormat;/// 默认pcm ⽀持pcm / ogg_opus / mp3
-@property (nonatomic, strong) NSString *ttsType;/// 默认只⽀持"stream",
-@property (nonatomic, strong) NSString *ttsSpeaker;/// tts声⾊设置
+/// 是否翻译,默认 false。如果为 true 翻译源语言和目标语言不能是同一种语言
+@property (nonatomic, assign) BOOL isTranslate;
+/// 源语言编码,默认为普通话(zh-CN),auto_lang 自动识别
+@property (nonatomic, strong) NSString *fromLanguage;
+/// 目标语言编码,默认为英语(en-US),auto_lang 自动识别
+@property (nonatomic, strong) NSString *toLanguage;
+/// 左声道源语言编码;如果不设置,则使用 fromLanguage
+@property (nonatomic, strong, nullable) NSString *leftFromLanguage;
+/// 左声道目标语言编码;如果不设置,则使用 toLanguage
+@property (nonatomic, strong, nullable) NSString *leftToLanguage;
+
+/// 右声道源语言编码;如果不设置,则使用 fromLanguage
+@property (nonatomic, strong, nullable) NSString *rightFromLanguage;
+/// 右声道目标语言编码;如果不设置,则使用 toLanguage
+@property (nonatomic, strong, nullable) NSString *rightToLanguage;
+
+/// 是否进行 TTS,默认 false
+@property (nonatomic, assign) BOOL isTTs;
+/// TTS 输出格式,默认 pcm,支持 pcm / ogg_opus / mp3
+@property (nonatomic, strong) NSString *ttsFormat;
+/// TTS 类型,默认只支持 "stream"
+@property (nonatomic, strong) NSString *ttsType;
+/// TTS 声色设置
+@property (nonatomic, strong) NSString *ttsSpeaker;
+/// 音频封装格式(opus 原始流 raw,封装 ogg)
+@property (nonatomic, strong) NSString *format;
+/// 音频编码格式(opus、raw)
+@property (nonatomic, strong) NSString *codec;
+/// Opus 输入包大小(字节数)
+@property (nonatomic, assign) NSInteger opusInputPackageSize;
+/// Opus 输出包大小(字节数)
+@property (nonatomic, assign) NSInteger opusOutputPackageSize;
+/// 音频采样率,单位 Hz(例如:16000 或 48000)
+@property (nonatomic, assign) NSInteger sampleRate;
+/// 声道数(1 单声道,2 立体声)
+@property (nonatomic, assign) NSInteger channels;
+/// 说话人分离
+@property (nonatomic, assign) BOOL isSpeakerSeparate;
@end
/// 蓝牙耳机录音asr配置
@property (nonatomic, strong) NSString *fromLanguage;/// 语⾔编码
@property (nonatomic, strong) NSString *toLanguage;/// ⽬标语⾔编码
@property (nonatomic, assign) BOOL summary;/// 是否进行总结,默认false
+/// 是否区分说话人,默认 NO
+@property (nonatomic, assign) BOOL speakerSeparate;
+/// 是否启用 ITN(数值/时间等标准化)
+@property (nonatomic, assign) BOOL enableItn;
+/// 端点检测窗口大小(VAD 终点判定),与服务端约定
+//@property (nonatomic, assign) NSInteger endWindowSize; // endWindowSize
+/// 翻译增强,默认 NO
+@property (nonatomic, assign) BOOL enableTranslateImprove; // enableTranslateImprove
@property (nonatomic, assign) BOOL speakerSplit;/// 是否区分说话人,默认false
@end
#import <Foundation/Foundation.h>
+NS_ASSUME_NONNULL_BEGIN
+
+/// 说话人分离结果(单段)
+@interface StarburstSpeakerSegment : NSObject
+@property (nonatomic, copy, nullable) NSString *speakerId; /// 说话人ID(字符串,如 "1")
+@property (nonatomic, assign) NSInteger startTime; /// 起始时间(ms)
+@property (nonatomic, assign) NSInteger endTime; /// 结束时间(ms)
+@property (nonatomic, copy, nullable) NSString *text; /// 该段文本
+@property (nonatomic, assign) NSInteger definiteIndex; /// 该段确定序号
+/// 工厂方法
++ (instancetype)modelWith:(NSDictionary *)dict;
+@end
+
/// 翻译结果
@interface StarburstTranslateResult : NSObject
-@property (nonatomic, strong) NSString *text;/// 语⾳识别后翻译的结果⽚段
-@property (nonatomic, assign) BOOL definite;/// 当前翻译⽚段是否确定
-@property (nonatomic, assign) int definiteIndex;/// 已翻译⽚段序号
+@property (nonatomic, copy, nullable) NSString *text; /// 语音识别后翻译的结果片段
+@property (nonatomic, assign) BOOL definite; /// 当前翻译片段是否确定
+@property (nonatomic, assign) int definiteIndex; /// 已翻译片段序号
+/// 工厂方法
++ (instancetype)modelWith:(NSDictionary *)dict;
@end
/// tts音频流
@interface StarburstAsrTtsResult : NSObject
-@property (nonatomic, assign) NSInteger index;/// 音频数据⽚段的序号
-@property (nonatomic, assign) NSInteger translateIndex;/// 翻译的序号
-@property (nonatomic, strong) NSString *streamPiece;/// 音频流
+@property (nonatomic, assign) NSInteger index; /// 音频数据片段的序号
+@property (nonatomic, assign) NSInteger translateIndex; /// 翻译的序号
+@property (nonatomic, copy, nullable) NSString *streamPiece; /// 音频流(Base64/文本)
++ (instancetype)modelWith:(NSDictionary *)dict;
@end
-
/// 识别结果
@interface StarburstAsrModel : NSObject
-@property (nonatomic, assign) NSInteger channel;/// 0非立体声,1左声道,2右声道
-@property (nonatomic, assign) NSInteger code;/// 状态码
-@property (nonatomic, strong) NSString *msg;/// 提示语
-@property (nonatomic, strong) NSString *requestId;/// 请求id
-@property (nonatomic, strong) NSString *textResult;/// 语⾳识别结果⽚段内容
-@property (nonatomic, assign) NSInteger sequence;/// 响应的编号
-@property (nonatomic, assign) BOOL definite;/// 语⾳识别结果⽚段是否已确定,后序不会有变化
-@property (nonatomic, assign) NSInteger definiteIndex;/// 已确定的识别结果序列号
-@property (nonatomic, strong) StarburstTranslateResult *translateResult;///翻译结果
-@property (nonatomic, strong) StarburstAsrTtsResult *ttsResult;///tts音频流
-
-+ (StarburstAsrModel *)modelWith:(NSDictionary *)dict;
+@property (nonatomic, assign) NSInteger channel; /// 0非立体声,1左声道,2右声道
+@property (nonatomic, assign) NSInteger code; /// 状态码
+@property (nonatomic, copy, nullable) NSString *msg; /// 提示语
+@property (nonatomic, copy, nullable) NSString *requestId; /// 请求id
+@property (nonatomic, copy, nullable) NSString *textResult; /// 语音识别结果片段内容
+@property (nonatomic, assign) NSInteger sequence; /// 响应的编号
+@property (nonatomic, assign) BOOL definite; /// 语音识别结果片段是否已确定,后序不会有变化
+@property (nonatomic, assign) NSInteger definiteIndex; /// 已确定的识别结果序列号
+@property (nonatomic, assign) BOOL isLastPackage; /// 是否为最后一包,后续没有数据(包括asr、tts、翻译结果)
+
+@property (nonatomic, strong, nullable) StarburstTranslateResult *translateResult; /// 翻译结果
+@property (nonatomic, strong, nullable) StarburstAsrTtsResult *ttsResult; /// tts音频流
+
+@property (nonatomic, copy, nullable) NSArray<StarburstSpeakerSegment *> *speakerResult; /// 说话人分离结果数组
+
++ (instancetype)modelWith:(NSDictionary *)dict;
@end
+NS_ASSUME_NONNULL_END
#import <Foundation/Foundation.h>
typedef NS_OPTIONS(NSInteger,StarburstSdkType) {
- StarburstSdkType_Ble = 1,/// 设备鉴权+设备拾音
- StarburstSdkType_Phone = 2,/// 账号鉴权+手机拾音
- StarburstSdkType_Mix = 3,/// 设备鉴权+手机拾音
- StarburstSdkType_Glasses_Ble = 4,/// 眼镜板+设备鉴权
- StarburstSdkType_Glasses_Account = 5,/// 眼镜板+账号鉴权
+ StarburstSdkType_Ble = 1,/// 设备鉴权+设备拾音(对话sdk内部封装耳机录音ble传输)
+ StarburstSdkType_Phone = 2,/// 账号鉴权+手机拾音(对话sdk内部封装手机录音)
+ StarburstSdkType_Mix = 3,/// 设备鉴权+手机拾音(对话sdk内部封装手机录音)
+ StarburstSdkType_Glasses_Ble = 4,/// 眼镜板+设备鉴权(对话需要外部喂音频流)
+ StarburstSdkType_Glasses_Account = 5,/// 眼镜板+账号鉴权(对话需要外部喂音频流)
};
@property (nonatomic, strong)NSString *sdkFolder;/// sdk路径,可以自定义
@property (nonatomic, strong)NSDictionary *debugInfo;/// 调试信息
@property (nonatomic, strong)NSString *user_custom_prompt_init;/// voicechat配置
+@property (nonatomic, assign) CGFloat ttsSpeed;//默认1.0,范围[0.8,2]
@property (nonatomic, assign)BOOL enableEarbudsSwitchSync;/// 主从耳机切换是否同步sdk信息到耳机,默认false
@property (nonatomic, assign)BOOL enableTextSyncToDevice;/// 是否下发文字到耳机仓,默认false
@property (nonatomic, assign)BOOL enableEmotionSyncToDevice;/// 耳机仓表情下发开关,默认false
+@property (nonatomic, assign)BOOL enableSpeakerSeparate;/// 是否开启人话分离,默认false
@property (nonatomic, assign)NSInteger callRecordChannel;/// 通话录音声道数。1:单声道 ;2:⽴体声;默认单声道
//enableExternalOpusDecoder
@property (nonatomic, strong)NSString *appId;/// 分配的id
/// - voiceCallBack: AI语音回复回调
/// - stateChange: 状态回调
/// - finished:录音地址回调
-- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
+- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish,NSInteger sampleRate))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
/// 手机拾音,开始对话
/// - Parameter vadType: 0 vad检测,1不启用vad(手动控制开始/结束讲话)
#import <StarburstSdk/StarburstStreamModel.h>
#import <StarburstSdk/StarburstOffLineFile.h>
#import <StarburstSdk/StartburstDecoderConfig.h>
-
+#import <StarburstSdk/TextToImageManager.h>
+#import <StarburstSdk/TextToImageCallback.h>
+#import <StarburstSdk/AIGCErrorCode.h>
+#import <StarburstSdk/TextToSpeechManager.h>
+#import <StarburstSdk/TextToSpeechCallback.h>
StarburstCode_UnAuth = 60000,///未鉴权
};
+typedef void (^AudioIntensityInputCallback)(NSArray<NSNumber*> *left,
+ NSArray<NSNumber*> *right,
+ NSTimeInterval timestampMs);
@interface StarburstSdk : NSObject
//@property (nonatomic, strong)void (^authSuccessCallback)(void);/// 鉴权成功回调
/// - Parameter fileCallback: 录音文件回调
- (void)stopRecordAsr:(void(^)(NSString *filePath))callback;
+/// 【自定义音频流识别】开始
+/// - Parameters:
+/// - config: ASR识别配置(和手机拾音配置一致)
+/// - recognize: 文本识别结果回调
+/// - stateChange: 状态变化回调
+- (void)startCustomAsr:(StarburstAsrConfig*)config
+ recognizeText:(void (^)(StarburstAsrModel *model))recognize
+ stateChange:(void(^)(StarburstCode code))stateChange;
+
+/// 【自定义音频流识别】发送音频数据
+/// - Parameter data: 外部采集的音频 PCM 或其他格式(根据 config 设定)
+- (void)sendCustomAudioData:(NSData *)data;
+
+/// 【自定义音频流识别】结束
+- (void)stopCustomAsr;
+
/// 开始耳机拾音
/// - Parameters:
/// - config: 识别配置
/// - voiceCallBack: AI语音回复回调
/// - stateChange: 状态回调
/// - finished:录音地址回调
-- (void)setupVoiceChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
+- (void)setupVoiceChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish, NSInteger sampleRate))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
/// 终止voice chat对话
- (void)stopVoiceChat:(NSInteger)dialogId;
/// 结束播放tts
- (void)stopPlayTtsAudio:(NSInteger)dialogId;
-
+/// 发送文字对话
+/// - Parameters:
+/// - text: 对话的文字
+/// - isTts: 是否tts
+- (void)sendVoiceChat:(NSString *)text tts:(BOOL)isTts;
//不可用
-- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
+- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish,NSInteger sampleRate))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
//不可用
- (void)startPhoneChat:(int)vadType;
//不可用
- (void)registerWithProductKey:(NSString *)productKey productSecret:(NSString *)productSecret deviceName:(NSString *)deviceName random:(NSString *)random finished:(void (^)(NSString *deviceSecret,NSError *error))finished;
//不可用
- (void)connectWithProductKey:(NSString *)productKey deviceName:(NSString *)deviceName deviceSecret:(NSString *)deviceSecret finished:(void (^)(BOOL isSuccess,NSError *error))finished;
+- (void)setInputAudioIntensityCallback:(AudioIntensityInputCallback)callback;
+
+-(NSString *)getDeviceName;
@end
/// - voiceCallBack: AI语音回复回调
/// - stateChange: 状态回调
/// - finished:录音地址回调
-- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
+- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish,NSInteger sampleRate))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
/// 开始对话
- (void)start;
/// - Parameter fileCallback: 录音文件回调
- (void)stopRecordAsr:(void(^)(NSString *filePath))fileCallback;
+
+/// 开始自定义音频流识别
+- (void)startCustomAsr:(StarburstAsrConfig*)config
+ recognizeText:(void (^)(StarburstAsrModel *model))recognize
+ stateChange:(void(^)(StarburstCode code))stateChange;
+
+/// 发送一段自定义音频数据(采样率、格式需匹配 config 设定)
+- (void)sendCustomAudioData:(NSData *)data;
+
+/// 停止自定义音频流识别
+- (void)stopCustomAsr;
+
/// 获取音色列表
/// - Parameter callBack: 结果回调
- (void)getVcSpeekerList:(void (^)(NSArray <StarbusrtSpeaker*> *list,BOOL success))callBack;
/// - voiceCallBack: AI语音回复回调
/// - stateChange: 状态回调
/// - finished:录音地址回调
-- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
+- (void)setupPhoneChatWith:(StarburstVoiceChatConfig*)config start:(void (^)(NSInteger dialogId))startCallback textCallback:(void (^)(StarbaustVoiceChatModel*))textCallBack responseVoice:(void (^)(NSInteger dialogId,NSData*data,BOOL finish, NSInteger sampleRate))voiceCallBack stateChange:(void(^)(StarburstCode code))stateChange finished:(void(^)(NSString *filePath))path;
/// 手机拾音,开始对话
--- /dev/null
+#import <Foundation/Foundation.h>
+#import <StarburstSdk/AIGCErrorCode.h>
+
+/**
+ * 文本生成图片回调协议
+ *
+ * 实现此协议可接收任务创建、进度、成功、失败、取消等事件。
+ */
+@protocol TextToImageCallback <NSObject>
+
+/**
+ * 当任务创建成功时触发
+ *
+ * @param taskId 唯一任务标识
+ */
+- (void)onCreated:(NSString *)taskId;
+
+/**
+ * 当任务处于进行状态时触发
+ *
+ * @param taskId 任务标识
+*/
+- (void)onProcessing:(NSString *)taskId;
+
+
+/**
+ * 当任务成功生成图片时触发
+ *
+ * @param taskId 任务标识
+ * @param images 生成图片的 URL 数组(NSString 类型)
+ */
+- (void)onSuccess:(NSString *)taskId images:(NSArray<NSString *> *)images;
+
+/**
+ * 当任务发生错误时触发
+ *
+ * @param taskId 任务标识
+ * @param code 错误码(AIGCErrorCode)
+ * @param message 错误说明
+ */
+- (void)onError:(NSString *)taskId code:(AIGCErrorCode)code message:(NSString *)message;
+
+/**
+ * 当任务被取消时触发
+ *
+ * @param taskId 任务标识
+ * @param success YES 表示取消成功,NO 表示取消失败
+ */
+- (void)onCanceled:(NSString *)taskId success:(BOOL)success;
+
+@end
--- /dev/null
+#import <Foundation/Foundation.h>
+#import <StarburstSdk/TextToImageCallback.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface TextToImageManager : NSObject
+
+/**
+ * 获取单例实例
+ *
+ * @return TextToImageManager 单例对象
+ */
++ (instancetype)sharedInstance;
+
+/**
+ * 创建图片生成任务并自动轮询任务状态直到完成
+ *
+ * @param prompt 文本提示词,例如“阳光下的海边风景”
+ * @param imageCount 生成的图片数量,建议范围 1~4
+ * @param imageWidth 生成图片的宽度(像素)
+ * @param imageHeight 生成图片的高度(像素)
+ * @param callback 实现了 TextToImageCallback 协议的回调对象,用于接收任务事件
+ *
+ * @discussion 调用此方法会创建任务并自动定时查询任务进度,
+ * 直到任务完成(成功或失败)或被取消。
+ */
+- (void)startTextToImage:(NSString *)prompt
+ imageCount:(NSInteger)imageCount
+ imageWidth:(NSInteger)imageWidth
+ imageHeight:(NSInteger)imageHeight
+ callback:(id<TextToImageCallback>)callback
+ NS_SWIFT_NAME(startTextToImage(prompt:imageCount:imageWidth:imageHeight:callback:));
+
+/**
+ * 按任务 ID 持续轮询任务状态
+ *
+ * @param taskId 已创建任务的唯一标识
+ * @param callback 回调对象,用于接收任务状态和结果
+ *
+ * @discussion 会持续查询任务状态直到任务完成,不会重新创建任务。
+ */
+- (void)queryByTaskId:(NSString *)taskId callback:(id<TextToImageCallback>)callback;
+
+/**
+ * 按任务 ID 查询一次任务状态
+ *
+ * @param taskId 已创建任务的唯一标识
+ * @param callback 回调对象
+ *
+ * @discussion 与 queryByTaskId 不同,此方法只查询一次,不进行持续轮询。
+ */
+- (void)queryOnceByTaskId:(NSString *)taskId
+ callback:(id<TextToImageCallback>)callback
+ NS_SWIFT_NAME(queryOnceByTaskId(_:callback:));
+
+/**
+ * 取消指定的图片生成任务
+ *
+ * @param taskId 要取消的任务 ID
+ */
+- (void)cancelTextToImage:(NSString *)taskId;
+
+/**
+ * 取消所有正在运行的图片生成任务
+ */
+- (void)cancelAllTasks;
+
+/// 释放全部资源(不取消正运行任务)
+- (void)releaseResources;
+
+@end
+
+NS_ASSUME_NONNULL_END
--- /dev/null
+#import <Foundation/Foundation.h>
+
+/**
+ * 文本转语音回调协议
+ *
+ * 客户端实现此协议,用于接收 TTS(Text To Speech)服务的结果或错误信息。
+ */
+@protocol TextToSpeechCallback <NSObject>
+
+@required
+
+/**
+ * 当云端成功返回语音数据(或语音下载地址等)时回调
+ *
+ * @param response 云端返回的完整响应字符串,通常为 JSON 格式或语音文件的 URL。
+ *
+ * @discussion 调用方可以在此方法中解析响应内容,例如:
+ * - 获取语音文件下载地址
+ * - 获取 Base64 编码的音频数据
+ */
+- (void)onResult:(NSString *)response;
+
+/**
+ * 当调用 TTS 服务发生错误时回调
+ *
+ * @param code 错误码(整数),具体含义由服务端定义
+ * @param message 错误提示信息,便于问题排查
+ *
+ * @discussion 常见错误:
+ * - 网络连接失败
+ * - 请求参数错误
+ * - 服务端内部错误
+ * - 授权失败
+ */
+- (void)onError:(NSInteger)code message:(NSString *)message;
+
+@end
--- /dev/null
+#import <Foundation/Foundation.h>
+#import <StarburstSdk/TextToSpeechCallback.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * 文本转语音管理器
+ *
+ * 封装了调用云端 TTS(Text To Speech)接口的过程,
+ * 支持设置语速、音色等参数,将文本合成成语音数据。
+ */
+@interface TextToSpeechManager : NSObject
+
+/**
+ * 获取单例对象
+ *
+ * @return TextToSpeechManager 单例实例
+ *
+ * @discussion 建议全局共享此管理器实例,避免重复创建和释放网络资源。
+ */
++ (instancetype)sharedInstance;
+
+/**
+ * 调用文本转语音服务
+ *
+ * @param companyId 企业或应用 ID(由服务方分配,用于鉴权)
+ * @param text 待合成的文本内容
+ * @param reqId 请求唯一标识,用于排查日志或防重复请求
+ * @param speedRatio 合成语音的语速倍率(1.0 为正常语速,>1.0 为加快,<1.0 为减慢)
+ * @param voiceType 音色类型标识(例如 "zh_female_qingchezizi_moon_bigtts")
+ * @param encoding 音频编码格式(如 "pcm"、"mp3"、"wav"),可为 nil 使用默认编码
+ * @param callback 回调对象,须实现 TextToSpeechCallback 协议,用于接收结果或错误
+ *
+ * @discussion 此方法会向云端发送 TTS 请求,云端返回后通过 callback 通知调用方。
+ * 建议:
+ * - 确保 text 不超过服务端最大长度限制
+ * - speedRatio 和 voiceType 需符合云端支持范围
+ * - callback 在主线程回调,可直接更新 UI 或播放音频
+ */
+- (void)textToSpeech:(NSString *)companyId
+ text:(NSString *)text
+ reqId:(NSString *)reqId
+ speedRatio:(float)speedRatio
+ voiceType:(NSString *)voiceType
+ encoding:(nullable NSString *)encoding
+ callback:(id<TextToSpeechCallback>)callback
+NS_SWIFT_NAME(textToSpeech(companyId:text:reqId:speedRatio:voiceType:encoding:callback:));
+
+@end
+
+NS_ASSUME_NONNULL_END
<dict>
<key>files</key>
<dict>
+ <key>Headers/AIGCErrorCode.h</key>
+ <data>
+ 6X+BFAl1GUlE673wijlbbmSDK7o=
+ </data>
<key>Headers/StarbaustVoiceChatModel.h</key>
<data>
- I6GwpMWb210AbU3/v9YLrfddoEA=
+ O8K7t0c5zyFzqsMRLB06Q9rMy98=
</data>
<key>Headers/StarburstAsrConfig.h</key>
<data>
- O5iJsUMPvwiRYlgGCgXp4TmAllQ=
+ tSk0X4yTu1hQB88SVtxWkHcfTRY=
</data>
<key>Headers/StarburstAsrModel.h</key>
<data>
- iiw2ZgUm4OBP2p0P0RSXd6gOwBY=
+ YMyp9i53bEO3diakJf+v5x2v2a0=
</data>
<key>Headers/StarburstConfig.h</key>
<data>
- /Bp9QOl1Vlv/1q1uwSh5zjn5IPA=
+ s3KYCCc8Cq0RWmlyfW7qe20T0c8=
</data>
<key>Headers/StarburstFileAsrModel.h</key>
<data>
</data>
<key>Headers/StarburstPhoneSdk.h</key>
<data>
- Qyvk+mUwCA6e59P6MqEGlKXAoV4=
+ rwT9UO4f4YJAdgYM9SUrQo6cW0M=
</data>
<key>Headers/StarburstSdk.h</key>
<data>
- UXMAS15KF45xW0cc4/2dI4vQTCQ=
+ aWY4JErrzMt9gCv0UqKyp5t+qGM=
</data>
<key>Headers/StarburstSdkManager.h</key>
<data>
- SO4o81CoyyO4XOPAsZo1GUvl1p4=
+ qhZrrBq0fWMMexpfZdAUj4ZVVNg=
</data>
<key>Headers/StarburstStreamModel.h</key>
<data>
</data>
<key>Headers/StartburstGlassChat.h</key>
<data>
- utqD1cN73IP2Kj6ThbunMmpf3S8=
+ EKmAva0NghWkD5BgB3v2JyOqcQo=
</data>
<key>Headers/StartburstGlassesSdk.h</key>
<data>
- PWqGuJ/I4XGFgkETcPBwQWnDEzg=
+ zjj7I7WFlFcTzkseAMNaUZyEIyI=
</data>
<key>Headers/StartburstMixSdk.h</key>
<data>
- bemNunuDBWDRu5cPpr/qtzb51HE=
+ CLg1FGxHPySPI5qCJH4N1zAZIw4=
+ </data>
+ <key>Headers/TextToImageCallback.h</key>
+ <data>
+ djrQqQ5J0JGsXn7fyLOzs0g705Q=
+ </data>
+ <key>Headers/TextToImageManager.h</key>
+ <data>
+ f7vVMHfHHqbi4Bi4seJMqHn4wnU=
+ </data>
+ <key>Headers/TextToSpeechCallback.h</key>
+ <data>
+ Q6/osX2ZUFgH9dbRA17GNlOraXI=
+ </data>
+ <key>Headers/TextToSpeechManager.h</key>
+ <data>
+ /j5GzHn6HDrV0eCdlQiwGi65QEQ=
</data>
<key>Info.plist</key>
<data>
- TbwY6qSKiZSNAQ4zKoI1WNFwZSA=
+ LYDkUlG3+K2ItUesIisY3Luuk1c=
</data>
<key>Modules/module.modulemap</key>
<data>
</dict>
<key>files2</key>
<dict>
+ <key>Headers/AIGCErrorCode.h</key>
+ <dict>
+ <key>hash</key>
+ <data>
+ 6X+BFAl1GUlE673wijlbbmSDK7o=
+ </data>
+ <key>hash2</key>
+ <data>
+ kB/hT+CxZkfSQW7qym0IydflbAkE3AYBvdij+bCDmlw=
+ </data>
+ </dict>
<key>Headers/StarbaustVoiceChatModel.h</key>
<dict>
<key>hash</key>
<data>
- I6GwpMWb210AbU3/v9YLrfddoEA=
+ O8K7t0c5zyFzqsMRLB06Q9rMy98=
</data>
<key>hash2</key>
<data>
- 1h090jtb3WRV25cr3cYc+NPRWUvlbO3j4QqjmThCV9c=
+ Te3DhLKFm7g9Cqh68BOLUikve5gURqN9RWUPumoYzZY=
</data>
</dict>
<key>Headers/StarburstAsrConfig.h</key>
<dict>
<key>hash</key>
<data>
- O5iJsUMPvwiRYlgGCgXp4TmAllQ=
+ tSk0X4yTu1hQB88SVtxWkHcfTRY=
</data>
<key>hash2</key>
<data>
- 9ieYYQ/XtFmG0peIjWVyt2juVka68xC3vcJqEwQ8qHM=
+ EY1t77d6qelm3wi1yYEcG5Kw1HNnR8mziKSGBadmqOg=
</data>
</dict>
<key>Headers/StarburstAsrModel.h</key>
<dict>
<key>hash</key>
<data>
- iiw2ZgUm4OBP2p0P0RSXd6gOwBY=
+ YMyp9i53bEO3diakJf+v5x2v2a0=
</data>
<key>hash2</key>
<data>
- 4P7mnRJalvX4ISPvk5QKj1CSZ762p7L8HNbs3dIVa9A=
+ r5bjhqHYbfX3MyhkjDOmAbqeXjuBI9fSoQRq/L0POEU=
</data>
</dict>
<key>Headers/StarburstConfig.h</key>
<dict>
<key>hash</key>
<data>
- /Bp9QOl1Vlv/1q1uwSh5zjn5IPA=
+ s3KYCCc8Cq0RWmlyfW7qe20T0c8=
</data>
<key>hash2</key>
<data>
- JMBJ67zUYPjxdjB6vpgfPtv5P5iPeEVIzIvo6tnFAmo=
+ q5+7n+PJt+RNcfGHp6EMO49CqhiFTaqcIZQbeDtZcTk=
</data>
</dict>
<key>Headers/StarburstFileAsrModel.h</key>
<dict>
<key>hash</key>
<data>
- Qyvk+mUwCA6e59P6MqEGlKXAoV4=
+ rwT9UO4f4YJAdgYM9SUrQo6cW0M=
</data>
<key>hash2</key>
<data>
- U7UlFVbYvM2vSO810pr82LySA9HeLA4uMBh6PnCY5aE=
+ kAdf5gAAX2xUk1XeiyxZjeGRvGhNe10TZexUz4PhxWU=
</data>
</dict>
<key>Headers/StarburstSdk.h</key>
<dict>
<key>hash</key>
<data>
- UXMAS15KF45xW0cc4/2dI4vQTCQ=
+ aWY4JErrzMt9gCv0UqKyp5t+qGM=
</data>
<key>hash2</key>
<data>
- OT9NyhWFaPzjchBx437Llm8zPGQdOJ1e/F2dRGEQEN8=
+ rnnCMlslMnwvphEZDLtWFp+XfQ1GqRFbhT7jnUVbBV4=
</data>
</dict>
<key>Headers/StarburstSdkManager.h</key>
<dict>
<key>hash</key>
<data>
- SO4o81CoyyO4XOPAsZo1GUvl1p4=
+ qhZrrBq0fWMMexpfZdAUj4ZVVNg=
</data>
<key>hash2</key>
<data>
- zYNzKgVctWkBxMvEJoFC+QgA9HMqVHL4rZ0ID3ef1/0=
+ J/65oVgQZfwUd8TWmGj/cvoeb7k9t79kPFQCeVGYRIQ=
</data>
</dict>
<key>Headers/StarburstStreamModel.h</key>
<dict>
<key>hash</key>
<data>
- utqD1cN73IP2Kj6ThbunMmpf3S8=
+ EKmAva0NghWkD5BgB3v2JyOqcQo=
</data>
<key>hash2</key>
<data>
- VaH6J5gUMxZ8Whr9yIF3iefTz8SKIWwpyY9dq3mMWYk=
+ YIfvJ+AmQws0QANocYZxmOahypPKgbsEZXeR6wEInTA=
</data>
</dict>
<key>Headers/StartburstGlassesSdk.h</key>
<dict>
<key>hash</key>
<data>
- PWqGuJ/I4XGFgkETcPBwQWnDEzg=
+ zjj7I7WFlFcTzkseAMNaUZyEIyI=
</data>
<key>hash2</key>
<data>
- Kql2VWlouLzv+FTfPR9+WlIFxgJUw4NpHhMzCTfAz8o=
+ h+sX2xVUY3pWvU9949WQN6IoZau4WG4Ad1qRwJeC6Yk=
</data>
</dict>
<key>Headers/StartburstMixSdk.h</key>
<dict>
<key>hash</key>
<data>
- bemNunuDBWDRu5cPpr/qtzb51HE=
+ CLg1FGxHPySPI5qCJH4N1zAZIw4=
+ </data>
+ <key>hash2</key>
+ <data>
+ Z6H7+vUoMzMfpR9r7joECzicS9kOX4b/rqZb0fOMoaU=
+ </data>
+ </dict>
+ <key>Headers/TextToImageCallback.h</key>
+ <dict>
+ <key>hash</key>
+ <data>
+ djrQqQ5J0JGsXn7fyLOzs0g705Q=
+ </data>
+ <key>hash2</key>
+ <data>
+ q/BtJzWpEpHfy9C5Bf07jUccilYQqgy94yGf3KLWwKM=
+ </data>
+ </dict>
+ <key>Headers/TextToImageManager.h</key>
+ <dict>
+ <key>hash</key>
+ <data>
+ f7vVMHfHHqbi4Bi4seJMqHn4wnU=
+ </data>
+ <key>hash2</key>
+ <data>
+ N96kZDSkodLOSzvpZTi6amQVAYq0AzsFO6tvFFlQEoE=
+ </data>
+ </dict>
+ <key>Headers/TextToSpeechCallback.h</key>
+ <dict>
+ <key>hash</key>
+ <data>
+ Q6/osX2ZUFgH9dbRA17GNlOraXI=
+ </data>
+ <key>hash2</key>
+ <data>
+ EXuN8dBBPFNJNuxSb0kaSfMs+i0WbS/9uA9tJ95RhlY=
+ </data>
+ </dict>
+ <key>Headers/TextToSpeechManager.h</key>
+ <dict>
+ <key>hash</key>
+ <data>
+ /j5GzHn6HDrV0eCdlQiwGi65QEQ=
</data>
<key>hash2</key>
<data>
- S6yNxpkYJSgoOVUAyuIhC8ourDLd4Pu6tKFnRkM+Me0=
+ ikdltWnYn+xcIZztjJovnuoIDocq2Zwz81BLGh2HmZM=
</data>
</dict>
<key>Modules/module.modulemap</key>
guard let _ = (scene as? UIWindowScene) else { return }
App.shared.window = window
window?.rootViewController = UINavigationController(rootViewController: DeviceListVC())
- DeepChordsAiSdk.shared.initSDK()
+ DCSdkManager.shared.initSdk()
}
func sceneDidDisconnect(_ scene: UIScene) {
//
public var kScreenWid: CGFloat { return UIScreen.main.bounds.size.width }
-
public var kScreenHei: CGFloat { return UIScreen.main.bounds.size.height }
import UIKit
var recordBtn = UIButton(type: .custom)
let tableView = UITableView(frame: CGRectZero, style: .plain)
-
deinit {
stopAction()
}
}
}
func setupSDk(){
- ChatManager.shared.chatNeedReloadData = {[weak self] in
+ DCChatManager.shared.chatNeedReloadData = {[weak self] in
guard let self = self else{return}
tableView.reloadData()
+ if DCChatManager.shared.dataList.count > 0 {
+ tableView.scrollToRow(at: IndexPath(row: DCChatManager.shared.dataList.count - 1, section: 0), at: .none, animated: true)
+ }
+ }
+ DCChatManager.shared.codeCallback = { [weak self] code in
+ guard let self = self else{return}
+ if code == 20001 {
+ self.recordBtn.isSelected = true
+ }
+ else if code == 20002 || code == 20003{
+ self.recordBtn.isSelected = false
+ }
+
+ }
+ DCChatManager.shared.finishCallback = { [weak self] path in
+ guard let self = self else{return}
+ // self.recordBtn.isSelected = false
}
}
func reloadData(){
}
@objc func recordAction() {
-// self.recordBtn.isSelected = !self.recordBtn.isSelected
-// if self.recordBtn.isSelected {
-// DCChat.shared.startChat()
-// }
-// else{
+ self.recordBtn.isSelected = !self.recordBtn.isSelected
+ if self.recordBtn.isSelected {
+ DCChat.shared.startChat()
+ }
+ else{
stopAction()
-// }
+ }
}
func stopAction() {
DCChat.shared.stopChat()
@objc func roleAction(){
let vc = RoleVC()
vc.didSelectedCallback = { role in
- ChatManager.shared.role = role
+ DCChatManager.shared.role = role
}
navigationController?.pushViewController(vc, animated: true)
}
extension ChatVC:UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return ChatManager.shared.dataList.count
+ return DCChatManager.shared.dataList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ChatCell.reuseID, for: indexPath) as? ChatCell
- cell!.data = ChatManager.shared.dataList[indexPath.row]
+ cell!.data = DCChatManager.shared.dataList[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
stopAction()
}
func setupView(){
- title = "手机录音"
+ title = "耳机录音"
view.backgroundColor = .white
fromItem = UIBarButtonItem(title: "源语言", style: .done, target: self, action: #selector(fromLanguageAction))
let range = NSMakeRange(toTextView.text.count - 1, 1)
self.toTextView.scrollRangeToVisible(range)
}
+ DCBleRecord.shared.codeCallback = { [weak self] code in
+ guard let self = self else{return}
+ if code == 20001 {
+ self.recordBtn.isSelected = true
+ }
+ else if code == 20002 || code == 20003{
+ self.recordBtn.isSelected = false
+ }
+
+ }
DCBleRecord.shared.filePathCallBack = { [weak self] path in
guard let self = self else{return}
+// self.recordBtn.isSelected = false
}
}
extension EarPhoneRecordVC{
func startAction(){
+ fromTextView.text = ""
+ toTextView.text = ""
DCBleRecord.shared.fromLanguage = fromLanguage
DCBleRecord.shared.toLanguage = toLanguage
DCBleRecord.shared.isTranslate = true
setupViews()
setupBle()
-
- DispatchQueue.main.asyncAfter(deadline:.now() + 2) {
- ChatManager.shared.setupSdk()
- }
}
func setupViews(){
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// var version = (Bundle.main.appVersion ?? "") + "\n"
- let version = "2025151801" + "\n"
+ let version = "2025151902" + "\n"
textView.text = "版本:\(version)" + DCLogger.logs.joined()
let range = NSMakeRange(textView.text.count - 1, 1)
textView.scrollRangeToVisible(range)
extension MusicVC {
func loadData(){
- DCDevice.shared.getMusicList(size: 10, index: 0) {[weak self] (list, result) in
- guard let self = self else{return}
- guard let list = list else{return}
+ DCDevice.shared.getTotalMusic { num in
+ if let num = num,num > 0{
+ DCDevice.shared.getMusicList(size: 10, index: 0) {[weak self] (list, result) in
+ guard let self = self else{return}
+ guard let list = list else{return}
+ }
+ }
}
}
}
}
func setupSdk(){
- DCRecord.shared.asrCallback = { [weak self] text in
+ DCPhoneRecord.shared.asrCallback = { [weak self] text in
guard let self = self else{return}
self.fromTextView.text = text
let range = NSMakeRange(fromTextView.text.count - 1, 1)
self.fromTextView.scrollRangeToVisible(range)
}
- DCRecord.shared.translateCallback = { [weak self] text in
+ DCPhoneRecord.shared.translateCallback = { [weak self] text in
guard let self = self else{return}
self.toTextView.text = text
let range = NSMakeRange(toTextView.text.count - 1, 1)
self.toTextView.scrollRangeToVisible(range)
}
- DCRecord.shared.filePathCallBack = { [weak self] path in
+ DCPhoneRecord.shared.filePathCallBack = { [weak self] path in
guard let self = self else{return}
}
}
extension PhoneRecordVC{
func startAction(){
- DCRecord.shared.fromLanguage = fromLanguage
- DCRecord.shared.toLanguage = toLanguage
- DCRecord.shared.isTranslate = true
- DCRecord.shared.start()
+ DCPhoneRecord.shared.fromLanguage = fromLanguage
+ DCPhoneRecord.shared.toLanguage = toLanguage
+ DCPhoneRecord.shared.isTranslate = true
+ DCPhoneRecord.shared.start()
}
func stopAction(){
- DCRecord.shared.stop()
+ DCPhoneRecord.shared.stop()
}
}
--- /dev/null
+import UIKit
+import StarburstSdk
+import AVFoundation
+
+class TttsVC: UIViewController {
+ private let textField = UITextField()
+ private let speedSlider = UISlider()
+ private let speedLabel = UILabel()
+ private let synthButton = UIButton(type: .system)
+ private let logView = UITextView()
+
+ private var ttsSpeed: Float = 1.0
+ private var audioPlayer: AVAudioPlayer?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ title = "文本合成 TTS"
+ view.backgroundColor = .white
+ setupUI()
+ }
+
+ func setupUI() {
+ textField.borderStyle = .roundedRect
+ textField.placeholder = "请输入要合成的文本"
+
+ speedSlider.minimumValue = 0.8
+ speedSlider.maximumValue = 2.0
+ speedSlider.value = ttsSpeed
+ speedSlider.addTarget(self, action: #selector(speedChanged), for: .valueChanged)
+
+ speedLabel.text = "语速:\(String(format: "%.1f", ttsSpeed))x"
+
+ synthButton.setTitle("合成并播放", for: .normal)
+ synthButton.addTarget(self, action: #selector(startTTS), for: .touchUpInside)
+
+ logView.isEditable = false
+ logView.font = UIFont.systemFont(ofSize: 14)
+
+ view.addSubview(textField)
+ view.addSubview(speedSlider)
+ view.addSubview(speedLabel)
+ view.addSubview(synthButton)
+ view.addSubview(logView)
+
+ textField.frame = CGRect(x: 20, y: 100, width: view.bounds.width-40, height: 40)
+ speedLabel.frame = CGRect(x: 20, y: 150, width: 200, height: 30)
+ speedSlider.frame = CGRect(x: 20, y: 180, width: view.bounds.width-40, height: 40)
+ synthButton.frame = CGRect(x: 20, y: 240, width: view.bounds.width-40, height: 50)
+ logView.frame = CGRect(x: 20, y: 300, width: view.bounds.width-40, height: 300)
+ }
+
+ @objc func speedChanged() {
+ ttsSpeed = speedSlider.value
+ speedLabel.text = "语速:\(String(format: "%.1f", ttsSpeed))x"
+ }
+
+ @objc func startTTS() {
+ guard let text = textField.text, !text.isEmpty else {
+ appendLog("请输入文本")
+ return
+ }
+ appendLog("开始合成语音...\n")
+
+ // 调用 iOS SDK 的 TTS 接口
+ TextToSpeechManager.sharedInstance().textToSpeech(
+ companyId: "2101982539",
+ text: text,
+ reqId: UUID().uuidString,
+ speedRatio: ttsSpeed,
+ voiceType: "zh_female_qingchezizi_moon_bigtts",
+ encoding: "pcm",
+ callback: self
+ )
+ }
+
+ func appendLog(_ msg: String) {
+ DispatchQueue.main.async {
+ self.logView.text.append(msg)
+ self.logView.scrollRangeToVisible(NSRange(location: self.logView.text.count, length: 0))
+ }
+ }
+
+ func playPCMData(_ pcmData: Data) {
+ // PCM裸数据要转成wav才能用AVAudioPlayer播放
+ if let wavData = pcmToWav(pcmData, sampleRate: 16000, channels: 1) {
+ DispatchQueue.main.async {
+ do {
+ self.audioPlayer = try AVAudioPlayer(data: wavData)
+ self.audioPlayer?.play()
+ self.appendLog("播放中...\n")
+ } catch {
+ self.appendLog("播放失败:\(error.localizedDescription)\n")
+ }
+ }
+ }
+ }
+
+ func pcmToWav(_ pcmData: Data, sampleRate: Int, channels: Int) -> Data? {
+ let byteRate = sampleRate * channels * 2
+ var header = Data()
+ header.append("RIFF".data(using: .ascii)!)
+ header.append(UInt32(pcmData.count + 36).littleEndianData)
+ header.append("WAVE".data(using: .ascii)!)
+
+ header.append("fmt ".data(using: .ascii)!)
+ header.append(UInt32(16).littleEndianData)
+ header.append(UInt16(1).littleEndianData) // PCM
+ header.append(UInt16(channels).littleEndianData)
+ header.append(UInt32(sampleRate).littleEndianData)
+ header.append(UInt32(byteRate).littleEndianData)
+ header.append(UInt16(channels * 2).littleEndianData)
+ header.append(UInt16(16).littleEndianData)
+
+ header.append("data".data(using: .ascii)!)
+ header.append(UInt32(pcmData.count).littleEndianData)
+
+ var wav = Data()
+ wav.append(header)
+ wav.append(pcmData)
+ return wav
+ }
+}
+
+extension TttsVC: TextToSpeechCallback {
+ func onResult(_ response: String) {
+ appendLog("合成完成,开始播放...\n")
+ guard let jsonObj = try? JSONSerialization.jsonObject(with: response.data(using: .utf8)!, options: []) as? [String:Any],
+ let respObj = jsonObj["resp"] as? [String:Any],
+ let base64Data = respObj["data"] as? String,
+ let pcmBytes = Data(base64Encoded: base64Data) else {
+ appendLog("解析PCM失败\n")
+ return
+ }
+ playPCMData(pcmBytes)
+ }
+
+ func onError(_ code: Int, message: String) {
+ appendLog("合成失败:\(message)\n")
+ }
+}
+
+// MARK: - Data扩展
+extension FixedWidthInteger {
+ var littleEndianData: Data {
+ withUnsafeBytes(of: self.littleEndian, { Data($0) })
+ }
+}
topVC().navigationController?.popToViewController(vcs[index], animated: true)
}
}
-
+ func goToPage(_ viewController: UIViewController,animated:Bool = true){
+ viewController.hidesBottomBarWhenPushed = true
+ topVC().navigationController?.pushViewController(viewController, animated: animated)
+ }
}
extension App{
private func getTopViewController(from vc: UIViewController) -> UIViewController {
}
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: (any Error)?) {
- DCLogger.debug("状态改变 == UUId ",characteristic.uuid)
+ DCLogger.debug("状态改变 == UUID ",characteristic.uuid)
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
//
-// ChatManager.swift
+// DCChatManager.swift
// Example
//
// Created by liangshi on 2025/12/15.
//
import AVFoundation
import DeepChordsSdk
+//typedef NS_OPTIONS(NSInteger,StarburstCode) {
+// StarburstCode_Start_Record = 20001,///开始录音
+// StarburstCode_Stop_Record = 20002,///停止录音
+// StarburstCode_Record_Error = 20003,///录音出错
+// StarburstCode_Ble_Disconected = 20004,///蓝牙断开
+// StarburstCode_Websocket_Connected = 30001,///socket连上
+// StarburstCode_Websocket_Disconnected = 30002,///socket断开连接
+// StarburstCode_Websocket_Connecting = 30003,///socket连接中...
+// StarburstCode_Websocket_pingTimeOut = 30004,///ping超时
+// StarburstCode_Net_Error = 50000,///网络错误
+// StarburstCode_UnAuth = 60000,///未鉴权
+//};
/// Ai回应模型
public class ChatCellModel:NSObject,NSCoding {
}
-class ChatManager:NSObject{
- static let shared = ChatManager()
- var isTtsPlaying = false
+class DCChatManager:NSObject{
+ static let shared = DCChatManager()
+ private var isTtsPlaying = false
private var audioData: Data?
- var dataList:[ChatCellModel] = []
- var chatNeedReloadData:(()->Void)?
+ public var dataList:[ChatCellModel] = []
+ public var chatNeedReloadData:(()->Void)?
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 结束对话回调
+ public var finishCallback:((String?)->Void)?
var role:DCRole? {
didSet{
DCChat.shared.getVcSpeekerList(finished: finished)
}
- func setupSdk(){
-
- PcmSound.sharedInstance().setup(16000, withchannels: 1)
- let options: AVAudioSession.CategoryOptions = [.allowBluetooth]
- do {
- try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
- try AVAudioSession.sharedInstance().setActive(true)
- } catch {
- DCLogger.debug(error)
- }
-
- setupChat()
- }
+// func setupSdk(){
+// PcmSound.sharedInstance().setup(16000, withchannels: 1)
+// let options: AVAudioSession.CategoryOptions = [.allowBluetooth]
+// do {
+// try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
+// try AVAudioSession.sharedInstance().setActive(true)
+// } catch {
+// DCLogger.debug(error)
+// }
+//
+// setupChat()
+// }
func setupChat(){
DCChat.shared.role = role
- DCChat.shared.initChat()
DCChat.shared.asrCallback = {[weak self] (text,index) in
guard let self = self else{return}
if let model = dataList.last,model.id == index,model.type == 1 {
self.audioData?.append(data!)
}
}
- DCChat.shared.codeCallback = { code in
+ DCChat.shared.codeCallback = {[weak self] code in
+ self?.codeCallback?(code)
+
// if code == 20001 {
// if (self.isTtsPlaying) {
// self.isTtsPlaying = false
// }
// }
}
- DCChat.shared.finishCallback = { path in
-
+ DCChat.shared.finishCallback = {[weak self] path in
+ self?.finishCallback?(path)
}
+
}
func saveToFile(data: Data) {
}
}
}
-extension ChatManager : PcmSoundDelegate {
+extension DCChatManager : PcmSoundDelegate {
func remaining(_ frames: UInt) {
DCLogger.debug("[frame:\(frames)]");
if (frames == 0) {
--- /dev/null
+//
+// Record.swift
+// Example
+//
+// Created by liangshi on 2025/12/19.
+//
+//import DeepChordsSdk
+//
+//class DCRecordManager{
+// static let shared = DCRecordManager()
+//
+// func setupRecord(){
+// DCBleRecord.shared.codeCallback = { [weak self] code in
+// guard let self = self else{return}
+// if code == 20001 {
+// if let vc = App.shared.topVC() as? EarPhoneRecordVC {
+// // vc.startRecord()
+// }else{
+// App.shared.goToPage(EarPhoneRecordVC())
+// }
+// }
+// else if code == 20002 || code == 20003{
+//// self.recordBtn.isSelected = false
+// }
+//
+// }
+// }
+//}
--- /dev/null
+//
+// DCSdkManager.swift
+// Example
+//
+// Created by liangshi on 2025/12/19.
+//
+import DeepChordsSdk
+
+class DCSdkManager{
+ static let shared = DCSdkManager()
+
+
+ func initSdk(){
+ DeepChordsAiSdk.shared.initSDK()
+// DCRecordManager.shared.setupRecord()
+ DCChatManager.shared.setupChat()
+
+ DCDevice.shared.eventCallback = { event in
+ switch event {
+ case 0x01:
+ if let vc = App.shared.topVC() as? ChatVC {
+ // vc.startRecord()
+ }else{
+ App.shared.goToPage(ChatVC())
+ }
+ case 0x02:
+// if let vc = App.shared.topVC() as? ChatVC {
+// // vc.startRecord()
+// }else{
+// App.shared.goToPage(ChatVC())
+// }
+ break
+ case 0x03:
+ if let vc = App.shared.topVC() as? EarPhoneRecordVC {
+ // vc.startRecord()
+ }else{
+ App.shared.goToPage(EarPhoneRecordVC())
+ }
+ case 0x04:
+// if let vc = App.shared.topVC() as? EarPhoneRecordVC {
+// // vc.startRecord()
+// }else{
+// App.shared.goToPage(EarPhoneRecordVC())
+// }
+ break
+ default:
+ break
+ }
+ }
+
+
+
+
+ }
+}
}
phoneView.do { v in
v.textField.placeholder = "请输入邮箱地址".l10n
+ v.textField.keyboardType = .emailAddress
}
loginBtn.set(title: "下一步".l10n,style: .theme1, target: self, action: #selector(loginAction))
view.addSubviews([titleLabel,phoneView,loginBtn])
"未处于通话状态":"ليست في حالة المكالمة",
"你":"أنت",
"对方":"الطرف الآخر",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"أستطيع مساعدتك في البحث والإجابة على الأسئلة والكتابة. أرفق مهامك بي~",
+
]
"未处于通话状态":"Hindi nasa estado ng tawag",
"你":"Ikaw",
"对方":"Kontrahan",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Maaari kitang tulungan sa paghahanap, pagsagot ng mga katanungan, at pagsusulat. Iampon mo ang iyong mga gawain sa akin~",
+
]
"未处于通话状态":"Nicht in einem Anruf",
"你":"Du", // 日常交互场景用 "Du",正式场景可替换为 "Sie"
"对方":"Die andere Partei",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Ich kann dir bei der Suche, der Beantwortung von Fragen und dem Schreiben helfen. Überlass mir deine Aufgaben~",
+
]
"未处于通话状态":"未處於通話狀態",
"你":"你", // 繁体中文通用表述,若需更口语化可使用"你"(与简体一致,繁体书写无差异)
"对方":"對方",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"我可以幫你搜尋、答疑、寫作,請把你的任務交給我吧~",
]
"未处于通话状态":"Không trong trạng thái cuộc gọi",
"你":"Bạn",
"对方":"Đối phương",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Tôi có thể giúp bạn tìm kiếm, trả lời câu hỏi và viết văn. Hãy giao nhiệm vụ của bạn cho tôi nhé~",
]
"未处于通话状态":"Not in a call",
"你":"You",
"对方":"The other party",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"I can help you with searching, answering questions and writing. Please entrust your tasks to me~",
+
]
"未处于通话状态":"Pas en appel",
"你":"Tu", // 日常交互场景用 "Tu",正式场景可替换为 "Vous"
"对方":"L'autre partie",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Je peux vous aider à chercher des informations, répondre à vos questions et écrire des textes. Veuillez me confier vos tâches~",
+
]
"未处于通话状态":"Tidak dalam panggilan",
"你":"Kamu", // 日常交互场景,正式场景可替换为 "Anda"
"对方":"Pihak lain",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Saya bisa membantu Anda mencari, menjawab pertanyaan, dan menulis. Silakan serahkan tugas Anda kepada saya~",
+
]
"未处于通话状态":"通話中ではない",
"你":"あなた",
"对方":"相手",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"検索、質問への回答、文章作成をお手伝いできます。ぜひお仕事をお任せくださいね~",
+
]
"未处于通话状态":"통화 중이 아님",
"你":"당신",
"对方":"상대방",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"검색, 질문 답변, 글쓰기를 도와드릴 수 있습니다. 당신의 업무를 맡겨주세요~",
+
]
"未处于通话状态":"Tidak dalam panggilan",
"你":"Awak", // 日常交互场景,正式场景可替换为 "Anda"
"对方":"Pihak satu lagi",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Saya boleh membantu anda mencari, menjawab soalan dan menulis. Sila serahkan tugas anda kepada saya~",
+
]
"未处于通话状态":"Не в звонке",
"你":"Ты", // 日常交互场景,正式场景可替换为 "Вы"
"对方":"Другая сторона",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Я могу помочь вам с поиском информации, ответом на вопросы и написанием текстов. Поверьте мне свои задачи~",
+
]
"未处于通话状态":"No en llamada",
"你":"Tú", // 日常交互场景用 "Tú",正式场景可替换为 "Usted"
"对方":"La otra parte",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"Puedo ayudarte con búsquedas, responder preguntas y escribir. ¡Confía tus tareas a mí~",
+
]
"未处于通话状态":"ไม่อยู่ในสถานะการโทรศัพท์",
"你":"คุณ",
"对方":"ฝ่ายตรงข้าม",
+ "我可以帮你搜索、答疑、写作,请把你的任务交给我吧~":"ฉันสามารถช่วยคุณค้นหาข้อมูล ตอบคำถาม และเขียนข้อความได้ โปรดมอบงานของคุณให้ฉันนะ~",
+
]