产品概述
产品功能
产品优势
系统 | iOS 15.6 及以上系统 |
处理器架构 | arm64 CPU 架构 |
支持终端设备 | A12+ 处理器,M1+ 处理器 iPhone XS,iPhone XR,iPhone SE2,iPhone 11+ 及更新设备 iPad 8+,iPad Mini5+,iPad Air3+,iPad Pro3+,New iPad Pro1+ 及更新设备 (2018 年以后发布的 iPhone,2019 年以后发布的 iPad 设备) |
开发 IDE | Xcode |
内存要求 | 大于500MB |
common_model/ 如果有多个人物模型,可以共用一个基础模型包。human_xxxxx_540p_v3/,其中 xxxxx 为定制形象的名称。

#import <TencentVirtualHumanSDK/TencentVirtualHumanSDK.h>
TVHLogLevelOff。[[TVHLogManager shareInstance] setLogLevel:TVHLogLevelInfo];
TVHLogManager.shareInstance().setLogLevel(TVHLogLevelInfo)
日志等级 | 等级标识 |
关闭日志 | TVHLogLevelOff |
错误日志 | TVHLogLevelError |
警告日志 | TVHLogLevelWarn |
信息日志 | TVHLogLevelInfo |
调试日志 | TVHLogLevelDebug |
追踪日志 | TVHLogLevelTrace |
int result = [[TVHLicenseManager shareInstance] authWithAppID:@"0000000000" andSecretKey:@"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"];NSLog(@"license result: %d", result);
let result = TVHLicenseManager.shareInstance().auth(withAppID: "0000000000", andSecretKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");print("license result: \\(result)")
// 请事先将通用模型和形象模型放入沙盒 Documents 目录下NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentsPath = [paths firstObject];NSString* common_model = [NSString stringWithFormat:@"%@/common_model", documentsPath];NSString* human_model = [NSString stringWithFormat:@"%@/human_yunxi_540p_v3", documentsPath];// 初始化控制器self.controller = [[TVHController alloc] initWithCommonModelPath:common_model humanModelPath:human_model];self.controller.delegate = self;// 开始渲染[self.controller start];
// 请事先将通用模型和形象模型放入沙盒 Documents 目录下let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)let documentsPath = paths.first!let commonModel = "\\(documentsPath)/common_model"let humanModel = "\\(documentsPath)/human_youyou3_720p"// 初始化控制器controller = TVHController(commonModelPath: commonModel, humanModelPath: humanModel)if(controller != nil) {controller.delegate = self;// 开始渲染controller.start()}
RenderView 上,您可以和使用普通 View 一样设置此 RenderView 的大小位置等,可以将此 RenderView 作为子 View 添加到其他 View。TVHRenderViewDelegate 来获取 RGBA 原始数据进行绘制。TVHRenderView 以获得最好的渲染效果self.renderView = [[TVHRenderView alloc] initWithFrame:self.view.bounds];self.renderView.fillMode =TVHMetalViewContentModeFit;[self.view addSubview:self.renderView];// 将 renderView 设置给控制器self.controller.renderView = self.renderView;
renderView = TVHRenderView(frame: self.view.bounds)renderView.fillMode = .fitview.addSubview(renderView)// 将 renderView 设置给控制器controller.renderView = renderView
TVHMetalViewContentModeStretch | 拉伸图像 |
TVHMetalViewContentModeFit | 裁切图像 |
TVHMetalViewContentModeFill | 保留黑边(透明边) |
appendAudioData流式输入音频数据,输入的音频会被保存到音频缓冲队列中,每次调用时输入的音频数据时长可以是任意值。// 此代码片段演示了从文件读取 PCM 数据,模拟流式分段发送给控制器NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentsPath = [paths firstObject];NSString* pcmPath = [NSString stringWithFormat:@"%@/test.pcm", documentsPath];// 读取音频数据NSData* data = [NSData dataWithContentsOfFile:pcmPath];// 模拟流式,分片发送数据(仅供演示,丢掉了最后一个分片)int packageSize = 1280;int packageCount =(int)[data length] / packageSize;for(int i=0; i<packageCount; i++) {BOOL isFinal = (i == packageCount -1);[self.controller appendAudioData:[data subdataWithRange:NSMakeRange(i*packageSize, packageSize)] metaData:@"" isFinal:isFinal];}
// 此代码片段演示了从文件读取 PCM 数据,模拟流式分段发送给控制器let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)guard let documentsPath = paths.first else { return }let pcmPath = "\\(documentsPath)/test.pcm"// 读取音频数据guard let data = try? Data(contentsOf: URL(fileURLWithPath: pcmPath)) else { return }// 模拟流式,分片发送数据(仅供演示,丢掉了最后一个分片)let packageSize = 1280let packageCount = data.count / packageSizefor i in 0..<packageCount {let range = i * packageSize..<(i * packageSize + packageSize)let subData = data.subdata(in: range)let isFinal = (i == packageCount - 1)controller.appendAudioData(subData, metaData: "", isFinal: isFinal)}
interrupt 方法,数智人就会立刻闭嘴并停止音频播放。[self.controllerinterrupt]
controller.interrupt()
speakFinish 消息。speakFinish 消息, 在收到 speakFinish 消息之前,调用 appendAudioData 时,也会等到 speakFinish 后才会继续开始播报。pause 和 resume 两个方法,用来控制数智人暂停和恢复。NSNotificationCenter 注册监听器,获得应用进入后台和进入前台的消息。@implementation DemoViewController- (void)viewDidLoad {[super viewDidLoad];// ... 其他代码// 注册通知[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(appDidEnterBackground:)name:UIApplicationDidEnterBackgroundNotificationobject:nil];[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(appWillEnterForeground:)name:UIApplicationWillEnterForegroundNotificationobject:nil];}- (void)dealloc{// 在销毁时取消委托[[NSNotificationCenter defaultCenter] removeObserver:self];}- (void)appDidEnterBackground:(NSNotification *)notification {// 处理暂停[self.controller pause];}- (void)appWillEnterForeground:(NSNotification *)notification {// 处理恢复[self.controller resume];}@end
class DemoViewController2: UIViewController {override func viewDidLoad() {super.viewDidLoad()// ... 其他代码// 注册通知NotificationCenter.default.addObserver(self,selector: #selector(appDidEnterBackground(_:)),name: UIApplication.didEnterBackgroundNotification,object: nil)NotificationCenter.default.addObserver(self,selector: #selector(appWillEnterForeground(_:)),name: UIApplication.willEnterForegroundNotification,object: nil)}deinit {// 在销毁时取消委托NotificationCenter.default.removeObserver(self)}@objc private func appDidEnterBackground(_ notification: Notification) {// 处理暂停controller.pause()}@objc private func appWillEnterForeground(_ notification: Notification) {// 处理恢复controller.resume()}}
TVHControllerDelegate 委托,在控制器中注册委托对象,就可以收到消息通知。// 实现 TVHControllerDelegate@interface DemoViewController () <TVHControllerDelegate>// ... 其他代码@end@implementation DemoViewController// 渲染开始- (void)renderStart {NSLog(@"render start");}// 播报开始- (void)speakStart {NSLog(@"speak start");}// 播报完成- (void)speakFinish {NSLog(@"speak finish");}// 播报错误- (void)speakError:(NSInteger)errorCode message:(NSString*)message {NSLog(@"speak error code:%ld, message:%@", errorCode, message);}@end
// 实现 TVHControllerDelegateextension DemoViewController2 : TVHControllerDelegate {// 渲染开始nonisolated func renderStart() {print("render start");}// 播报开始nonisolated func speakStart() {print("speak start");}// 播报完成nonisolated func speakFinish() {print("speak finish");}// 播报错误nonisolated func speakError(_ errorCode: Int, message: String!) {print("speak error code:\\(errorCode), message:\\(message)");}}
[self.controller appendAudioData:data metaData:@"这里是附加信息" isFinal:isFinal];
controller.appendAudioData(data, metaData: "这里是附加信息", isFinal: isFinal)
// 实现 TVHControllerDelegate@interface DemoViewController () <TVHControllerDelegate>// ... 其他代码@end@implementation DemoViewController// 播报 Meta信息 开始- (void)speakMetaStart:(NSString *)metaData {NSLog(@"speak meta start: %@", metaData);}// 播报 Meta信息 完成- (void)speakMetaFinish:(NSString *)metaData {NSLog(@"speak meta finish: %@", metaData);}@end
// 实现 TVHControllerDelegateextension DemoViewController2 : TVHControllerDelegate {// 播报 Meta信息 开始nonisolated func speakMetaStart(_ metaData: String!) {print("speak meta start: \\(metaData)");}// 播报 Meta信息 完成nonisolated func speakMetaFinish(_ metaData: String!) {print("speak meta finish: \\(metaData)");}}
canSmoothlyRun 方法判断当前设备是否支持端渲染 SDK。BOOL canRun = [[TVHDeviceManager shareInstance] canSmoothlyRun]
let canRun = TVHDeviceManager.shareInstance().canSmoothlyRun()




文档反馈