Skip to content

Commit e63d07a

Browse files
committed
发布:模型自定义接入,异常捕获优化,工单反馈功能
1 parent 5c7f670 commit e63d07a

File tree

2 files changed

+196
-2
lines changed

2 files changed

+196
-2
lines changed

README.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,199 @@
5959

6060
安装完成后,打开软件,下载模型一键启动包,即可使用。
6161

62+
## 模型自定义接入
63+
64+
如果有第三方一键启动的模型,可以按照以下方式接入。
65+
66+
模型文件夹格式,只需要编写 `config.json``server.js` 两个文件即可。
67+
68+
```
69+
|- 模型文件夹/
70+
|-|- config.json - 模型配置文件
71+
|-|- server.js - 模型对接文件
72+
|-|- xxx - 其他模型文件,推荐将模型文件放在 model 文件夹下
73+
```
74+
75+
### config.json 文件示例
76+
77+
```json5
78+
{
79+
"name": "server-xxx", // 模型名称
80+
"version": "0.1.0", // 模型版本
81+
"title": "语音模型", // 模型标题
82+
"description": "模型描述", // 模型描述
83+
"platformName": "win", // 支持系统,win, osx, linux
84+
"platformArch": "x86", // 支持架构,x86, arm64
85+
"entry": "server/main", // 入口文件,一键启动包文件
86+
"functions": [
87+
"videoGen", // 支持视频生成
88+
"soundTTS", // 支持语音合成
89+
"soundClone" // 支持语音克隆
90+
],
91+
"settings": [ // 模型配置项,可以显示在模型配置页面
92+
{
93+
"name": "port",
94+
"type": "text",
95+
"title": "服务端口",
96+
"default": "",
97+
"placeholder": "留空会检测使用随机端口"
98+
}
99+
]
100+
}
101+
```
102+
103+
### server.js 文件示例
104+
105+
> 以下以 MuseTalk 为例
106+
107+
```js
108+
const serverRuntime = {
109+
port: 0,
110+
}
111+
112+
let shellController = null
113+
114+
module.exports = {
115+
ServerApi: null,
116+
_url() {
117+
return `http://localhost:${serverRuntime.port}/`
118+
},
119+
async _client() {
120+
return await this.ServerApi.GradioClient.connect(this._url());
121+
},
122+
_send(serverInfo, type, data) {
123+
this.ServerApi.event.sendChannel(serverInfo.eventChannelName, {type, data})
124+
},
125+
126+
// 模型初始化
127+
async init(ServerApi) {
128+
this.ServerApi = ServerApi;
129+
},
130+
// 模型启动
131+
async start(serverInfo) {
132+
console.log('start', JSON.stringify(serverInfo))
133+
this._send(serverInfo, 'starting', serverInfo)
134+
let command = []
135+
if (serverInfo.setting?.['port']) {
136+
serverRuntime.port = serverInfo.setting.port
137+
} else if (!serverRuntime.port || !await this.ServerApi.app.isPortAvailable(serverRuntime.port)) {
138+
serverRuntime.port = await this.ServerApi.app.availablePort(50617)
139+
}
140+
if (serverInfo.setting?.['startCommand']) {
141+
command.push(serverInfo.setting.startCommand)
142+
} else {
143+
//command.push(`"${serverInfo.localPath}/server/main"`)
144+
command.push(`"${serverInfo.localPath}/server/.ai/python.exe"`)
145+
command.push('-u')
146+
command.push(`"${serverInfo.localPath}/server/run.py"`)
147+
if (serverInfo.setting?.['gpuMode'] === 'cpu') {
148+
command.push('--gpu_mode=cpu')
149+
}
150+
}
151+
shellController = await this.ServerApi.app.spawnShell(command, {
152+
cwd: `${serverInfo.localPath}/server`,
153+
env: {
154+
GRADIO_SERVER_PORT: serverRuntime.port,
155+
PATH: [
156+
process.env.PATH,
157+
`${serverInfo.localPath}/server`,
158+
`${serverInfo.localPath}/server/.ai/ffmpeg/bin`,
159+
].join(';')
160+
},
161+
stdout: (data) => {
162+
this.ServerApi.file.appendText(serverInfo.logFile, data)
163+
},
164+
stderr: (data) => {
165+
this.ServerApi.file.appendText(serverInfo.logFile, data)
166+
},
167+
success: (data) => {
168+
this._send(serverInfo, 'success', serverInfo)
169+
},
170+
error: (data, code) => {
171+
this.ServerApi.file.appendText(serverInfo.logFile, data)
172+
this._send(serverInfo, 'error', serverInfo)
173+
},
174+
})
175+
},
176+
// 模型启动检测
177+
async ping(serverInfo) {
178+
try {
179+
const res = await this.ServerApi.request(`${this._url()}info`)
180+
return true
181+
} catch (e) {
182+
}
183+
return false
184+
},
185+
// 模型停止
186+
async stop(serverInfo) {
187+
this._send(serverInfo, 'stopping', serverInfo)
188+
try {
189+
shellController.stop()
190+
shellController = null
191+
} catch (e) {
192+
console.log('stop error', e)
193+
}
194+
this._send(serverInfo, 'stopped', serverInfo)
195+
},
196+
// 模型配置
197+
async config() {
198+
return {
199+
"code": 0,
200+
"msg": "ok",
201+
"data": {
202+
"httpUrl": shellController ? this._url() : null,
203+
"functions": {
204+
"videoGen": {
205+
"param": [
206+
{
207+
name: "box",
208+
type: "inputNumber",
209+
title: "嘴巴张开度",
210+
defaultValue: -7,
211+
placeholder: "",
212+
tips: '嘴巴张开度可以控制生成视频中嘴巴的张开程度',
213+
min: -9,
214+
max: 9,
215+
step: 1,
216+
}
217+
]
218+
},
219+
}
220+
}
221+
}
222+
},
223+
// 视频生成
224+
async videoGen(serverInfo, data) {
225+
console.log('videoGen', serverInfo, data)
226+
const client = await this._client()
227+
const resultData = {
228+
// success, querying, retry
229+
type: 'success',
230+
start: 0,
231+
end: 0,
232+
jobId: '',
233+
data: {
234+
filePath: null
235+
}
236+
}
237+
resultData.start = Date.now()
238+
const result = await client.predict("/predict", [
239+
this.ServerApi.GradioHandleFile(data.videoFile),
240+
this.ServerApi.GradioHandleFile(data.soundFile),
241+
parseInt(data.param.box)
242+
]);
243+
// console.log('videoGen.result', JSON.stringify(result))
244+
resultData.end = Date.now()
245+
resultData.data.filePath = result.data[0].value.video.path
246+
return {
247+
code: 0,
248+
msg: 'ok',
249+
data: resultData
250+
}
251+
},
252+
}
253+
```
254+
62255
## 技术栈
63256
64257
- `electron`

changelog.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
## v0.2.0
1+
## v0.2.0 模型自定义接入,异常捕获优化,工单反馈功能
22

33
- 新增:工单反馈功能,便于解决问题
44
- 新增:应用 loading 窗口
5+
- 新增:支持自定义模型接入
56
- 优化:请求异常时增加错误码
67
- 优化:调用错误日志显示优化
78
- 优化:模型调用接口内置到项目中,方便更新升级
89

9-
## v0.1.0
10+
## v0.1.0 Mac支持声音克隆和声音合成
1011

1112
- 新增:Mac(Apple芯片)支持声音克隆和声音合成
1213
- 新增:调试窗口统一管理,方便查看调试信息

0 commit comments

Comments
 (0)