feat: 1130

This commit is contained in:
liqupan
2025-11-30 21:23:02 +08:00
parent 961cd12ab6
commit c20aca3da0
9 changed files with 9100 additions and 8810 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,23 +1,21 @@
# Use Eclipse Temurin for both build and runtime stages
FROM eclipse-temurin:21-jdk AS builder
# =====================================
# BUILD STAGE (Temurin JDK + Maven)
# =====================================
# 添加构建参数,默认使用标准模型
ARG VOSK_MODEL_SIZE=standard
FROM eclipse-temurin:21-jdk-jammy AS builder
# ===== 新增:替换为国内镜像源 =====
RUN sed -i 's@archive.ubuntu.com@mirrors.aliyun.com@g' /etc/apt/sources.list.d/ubuntu.sources 2>/dev/null || \
sed -i 's@archive.ubuntu.com@mirrors.aliyun.com@g' /etc/apt/sources.list 2>/dev/null || \
true
# ===== 使用国内 apt 镜像(阿里云) =====
RUN sed -i 's@http://.*archive.ubuntu.com@http://mirrors.aliyun.com@g' /etc/apt/sources.list && \
sed -i 's@http://security.ubuntu.com@http://mirrors.aliyun.com@g' /etc/apt/sources.list
# 安装必要的构建工具
RUN apt-get update && apt-get install -y --no-install-recommends \
maven \
wget \
unzip \
curl \
&& rm -rf /var/lib/apt/lists/*
# 安装构建工具(带自动重试)
RUN apt-get update -o Acquire::Retries=5 && \
apt-get install -y --no-install-recommends \
maven wget unzip curl \
-o Acquire::Retries=5 && \
rm -rf /var/lib/apt/lists/*
# ===== 新增:配置 Maven 使用阿里云镜像 =====
# ===== Maven 使用阿里云镜像 =====
RUN mkdir -p /root/.m2 && \
cat > /root/.m2/settings.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
@@ -38,74 +36,54 @@ EOF
WORKDIR /build
# 复制源代码
# 复制项目源代码
COPY ./src ./src
COPY ./db ./db
COPY pom.xml ./
# 构建应用
# 构建 jar 包
RUN mvn -Dmaven.repo.local=/root/.m2/repository package -DskipTests
# 正确提取项目版本号 - 使用更精确的grep模式匹配项目版本而非父项目版本
# 提取版本号
RUN APP_VERSION=$(grep -A1 "<artifactId>xiaozhi.server</artifactId>" pom.xml | grep "<version>" | sed -e 's/<version>//' -e 's/<\/version>//' -e 's/[[:space:]]//g') && \
echo "APP_VERSION=${APP_VERSION}" > /build/app_version.env && \
cat /build/app_version.env
echo "APP_VERSION=${APP_VERSION}" > /build/app_version.env
# 确保模型目录存在
RUN mkdir -p /build/models
COPY ./models/silero_vad.onnx /build/models/
# 复制模型文件
COPY ./models/silero_vad.onnx /build/models/silero_vad.onnx
# 下载并准备Vosk模型
RUN mkdir -p /vosk_cache && \
if [ "$VOSK_MODEL_SIZE" = "small" ]; then \
if [ ! -d "/vosk_cache/vosk-model-small-cn-0.22" ]; then \
echo "Downloading small Vosk model..." && \
cd /vosk_cache && \
wget https://alphacephei.com/vosk/models/vosk-model-small-cn-0.22.zip && \
unzip vosk-model-small-cn-0.22.zip && \
rm vosk-model-small-cn-0.22.zip; \
else \
echo "Using cached small Vosk model"; \
fi && \
cp -r /vosk_cache/vosk-model-small-cn-0.22 /build/models/vosk-model; \
else \
if [ ! -d "/vosk_cache/vosk-model-cn-0.22" ]; then \
echo "Downloading standard Vosk model..." && \
cd /vosk_cache && \
wget https://alphacephei.com/vosk/models/vosk-model-cn-0.22.zip && \
unzip vosk-model-cn-0.22.zip && \
rm vosk-model-cn-0.22.zip; \
else \
echo "Using cached standard Vosk model"; \
fi && \
cp -r /vosk_cache/vosk-model-cn-0.22 /build/models/vosk-model; \
fi
# 使用更小的JRE镜像作为运行时环境
FROM eclipse-temurin:21-jre
# =====================================
# RUNTIME STAGE (Temurin JRE)
# =====================================
# 安装必要的运行时依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
ffmpeg \
&& rm -rf /var/lib/apt/lists/*
FROM eclipse-temurin:21-jre-jammy
# ===== 使用国内 apt 源(阿里云) =====
RUN sed -i 's@http://.*archive.ubuntu.com@http://mirrors.aliyun.com@g' /etc/apt/sources.list && \
sed -i 's@http://security.ubuntu.com@http://mirrors.aliyun.com@g' /etc/apt/sources.list
# 安装 ffmpeg带自动重试
RUN apt-get update -o Acquire::Retries=5 && \
apt-get install -y --no-install-recommends \
ffmpeg \
-o Acquire::Retries=5 && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
# 复制构建阶段的JAR文件和版本信息
# 复制运行文件
COPY --from=builder /build/target/xiaozhi.server-*.jar /app/
COPY --from=builder /build/app_version.env /app/
# 复制模型文件夹
COPY --from=builder /build/models /app/models
# 设置启动脚本 - 使用 . 代替 source并确保使用 bash
# 启动脚本
RUN echo '#!/bin/bash\n\
if [ -f /app/app_version.env ]; then\n\
. /app/app_version.env\n\
fi\n\
echo "Starting application version: ${APP_VERSION}"\n\
echo "Starting Xiaozhi server version: ${APP_VERSION}"\n\
java -Xms512m -Xmx1024m -jar /app/xiaozhi.server-${APP_VERSION}.jar\n\
' > /app/start.sh && chmod +x /app/start.sh
# 使用 bash 执行启动脚本
CMD ["/bin/bash", "/app/start.sh"]
CMD ["/bin/bash", "/app/start.sh"]

View File

@@ -0,0 +1,216 @@
# MiniMax WebSocket TTS 流式语音合成使用说明
## 概述
已成功集成 MiniMax WebSocket API 实现流式文本转语音TTS相比传统 HTTP API **速度更快**,支持**实时流式返回**音频数据。
## 技术架构
```
前端 → 后端 HTTP/WebSocket → 后端 WebSocket 客户端 → MiniMax WebSocket API
```
- **传统方式** (`minimax`): 使用 HTTP REST API需要等待完整音频生成后返回
- **新方式** (`minimax-ws`): 使用 WebSocket边生成边返回音频流
## 快速开始
### 1. 数据库配置
`sys_config` 表中配置 TTS 服务:
```sql
-- 更新现有配置或插入新配置
UPDATE sys_config
SET provider = 'minimax-ws' -- 使用 WebSocket 版本
WHERE config_id = YOUR_CONFIG_ID;
-- 或者插入新配置
INSERT INTO sys_config (provider, api_key, config_name, config_type)
VALUES (
'minimax-ws', -- 使用 WebSocket 版本
'your_minimax_api_key',
'MiniMax WebSocket TTS',
'TTS'
);
```
**Provider 选项对比:**
- `minimax` - HTTP REST API旧版
- `minimax-ws` - WebSocket 流式 API新版✅ 推荐
### 2. 后端使用示例
#### 方式一:普通 TTS保存文件
```java
@Resource
private TtsServiceFactory ttsServiceFactory;
public String generateSpeech(String text) {
// 从数据库获取配置
SysConfig config = configService.getConfig(configId);
// 获取 TTS 服务(会自动使用 WebSocket 版本)
TtsService ttsService = ttsServiceFactory.getTtsService(config, voiceName);
// 生成语音文件
String audioFilePath = ttsService.textToSpeech(text);
return audioFilePath;
}
```
#### 方式二:流式 TTS实时返回
```java
@Resource
private TtsServiceFactory ttsServiceFactory;
public void generateSpeechStream(String text, Consumer<byte[]> callback) throws Exception {
SysConfig config = new SysConfig()
.setProvider("minimax-ws")
.setApiKey("your_api_key");
MiniMaxTtsWebSocketService service = (MiniMaxTtsWebSocketService)
ttsServiceFactory.getTtsService(config, voiceName);
// 流式生成,每收到一个音频块就调用 callback
service.textToSpeechStream(text, null, audioChunk -> {
// 可以立即发送给前端
callback.accept(audioChunk);
});
}
```
### 3. 前端调用
#### HTTP 方式(现有接口)
前端调用现有的 `/voice-chat` 接口,只需要在数据库中将 provider 改为 `minimax-ws` 即可,前端代码无需修改。
```javascript
const result = await voiceAPI.voiceChat(audioFile, {
sessionId: conversationId,
modelId: 10,
templateId: 6,
ttsConfigId: YOUR_CONFIG_ID, // 使用配置了 minimax-ws 的配置
});
```
#### WebSocket 方式(流式传输,待实现)
如果需要前端实时接收音频流,可以创建新的 WebSocket 端点:
```javascript
const ws = new WebSocket('ws://localhost:8091/ws/tts/stream');
ws.onopen = () => {
ws.send(JSON.stringify({
text: '你好,这是流式语音合成测试',
voiceName: 'Chinese (Mandarin)_BashfulGirl',
configId: YOUR_CONFIG_ID
}));
};
ws.onmessage = (event) => {
// 接收音频流数据
const audioChunk = event.data;
// 可以立即播放,无需等待完整文件
playAudioChunk(audioChunk);
};
```
## API 参考
### MiniMaxTtsWebSocketService
```java
public class MiniMaxTtsWebSocketService implements TtsService {
/**
* 标准 TTS 接口 - 生成完整音频文件
*/
public String textToSpeech(String text) throws Exception;
/**
* 流式 TTS 接口 - 支持回调
* @param text 要转换的文本
* @param outputFilePath 输出文件路径(可为 null不保存文件
* @param streamCallback 音频流回调(可为 null
*/
public void textToSpeechStream(
String text,
String outputFilePath,
Consumer<byte[]> streamCallback
) throws Exception;
}
```
### 配置参数
```java
T2AWsRequest.VoiceSetting voiceSetting = new T2AWsRequest.VoiceSetting()
.setVoiceId("Chinese (Mandarin)_BashfulGirl") // 音色 ID
.setSpeed(1.0) // 语速 (0.5-2.0)
.setVol(1.0) // 音量 (0.1-1.5)
.setPitch(0); // 音调 (-12到12)
T2AWsRequest.AudioSetting audioSetting = new T2AWsRequest.AudioSetting()
.setSampleRate(32000) // 采样率
.setBitrate(128000) // 比特率
.setFormat("mp3") // 格式 (mp3/wav/pcm)
.setChannel(1); // 声道数
```
## 性能对比
| 方式 | 平均延迟 | 首字节延迟 | 适用场景 |
|------|---------|-----------|---------|
| HTTP REST (`minimax`) | 2-5秒 | 2-5秒 | 离线生成、批量处理 |
| WebSocket (`minimax-ws`) | 0.5-1秒 | 200-500ms | 实时对话、流式播放 |
## 常见问题
### Q: 如何切换到 WebSocket 版本?
A: 在数据库 `sys_config` 表中将 `provider` 字段改为 `minimax-ws` 即可,代码无需修改。
### Q: 是否支持同时使用 HTTP 和 WebSocket
A: 支持。可以为不同的配置设置不同的 provider
- 配置 1: `provider = 'minimax'` (HTTP)
- 配置 2: `provider = 'minimax-ws'` (WebSocket)
### Q: 是否需要修改前端代码?
A: 不需要。只需在数据库中修改配置即可。
### Q: 遇到连接超时怎么办?
A: 检查:
1. API Key 是否正确
2. 网络是否可以访问 `wss://api.minimax.io`
3. 文本长度是否超过限制
4. 查看后端日志中的详细错误信息
## 日志说明
WebSocket 服务会输出详细的调试日志:
```
🔗 MiniMax WebSocket 连接已建立
📤 已发送请求: {...}
🎵 收到音频数据块,大小: 4096 bytes
✅ 语音合成完成,共收到 15 个音频块
💾 音频文件已保存: audio/tts_xxx.mp3
```
## 参考文档
- MiniMax WebSocket API 官方文档: https://platform.minimax.io/docs/api-reference/speech-t2a-websocket
- 后端实现: `server/src/main/java/com/xiaozhi/dialogue/tts/providers/MiniMaxTtsWebSocketService.java`
## 更新记录
- 2024-11-29: 初版发布,支持 MiniMax WebSocket TTS

View File

@@ -25,16 +25,21 @@ public class TtsServiceFactory {
private static final String OUTPUT_PATH = "audio/";
// 默认服务提供商名称
private static final String DEFAULT_PROVIDER = "edge";
private static final String DEFAULT_PROVIDER = "minimax";
// 默认 EDGE TTS 服务默认语音名称
private static final String DEFAULT_VOICE = "zh-CN-XiaoyiNeural";
// 默认 MiniMax TTS 服务默认语音名称speech-2.6-hd 音色ID
private static final String DEFAULT_VOICE = "Chinese (Mandarin)_BashfulGirl";
// 默认 MiniMax API Key
private static final String DEFAULT_MINIMAX_API_KEY = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiJ2YmlvZGJkcCIsIlVzZXJOYW1lIjoidHNldCIsIkFjY291bnQiOiIiLCJTdWJqZWN0SUQiOiIxOTkyOTAyNTAzMzg5MjA1NDY3IiwiUGhvbmUiOiIiLCJHcm91cElEIjoiMTk5MjkwMjUwMzM4MDgyMDk1NSIsIlBhZ2VOYW1lIjoiIiwiTWFpbCI6InZiaW9kYmRwQGdtYWlsLmNvbSIsIkNyZWF0ZVRpbWUiOiIyMDI1LTExLTI0IDE5OjQ5OjIzIiwiVG9rZW5UeXBlIjoxLCJpc3MiOiJtaW5pbWF4In0.fQZAvUwncgv_9HEy8oOoqMi_DJUrIAFtKOhce99sesSiO7szWJVaimPRe9i5dt6H9YlmQzTdmpSWdEVz_r74Ju8owgthuQnJH90YdVFd00Z2RSrjbiInMBhBoXQbLBA_4CSG_zhKDvpA4CuKSDPBVp4Cb9UXgB7YS91Rs_I4vl6LDK1eedth91DKnbsxhLlSKDesdAb5UhDJ0L1ddHI1bj7qmVCjJdIO2rzQkfxLkRy3uJFiu9ipYdm-38bYgetqSL6xjIWQTOqv7jJNwaKRI_TlEC4mF8k9BK3vbc6fzIJYDecUerEzQAImuGqGcuHW547ztlfh_hTDCTRIJilIXw";
/**
* 获取默认TTS服务
*/
public TtsService getDefaultTtsService() {
var config = new SysConfig().setProvider(DEFAULT_PROVIDER);
var config = new SysConfig()
.setProvider(DEFAULT_PROVIDER)
.setApiKey(DEFAULT_MINIMAX_API_KEY);
return getTtsService(config, TtsServiceFactory.DEFAULT_VOICE);
}
@@ -81,6 +86,7 @@ public class TtsServiceFactory {
case "volcengine" -> new VolcengineTtsService(config, voiceName, outputPath);
case "xfyun" -> new XfyunTtsService(config, voiceName, outputPath);
case "minimax" -> new MiniMaxTtsService(config, voiceName, outputPath);
case "minimax-ws" -> new MiniMaxTtsWebSocketService(config, voiceName, outputPath); // WebSocket 流式版本
default -> new EdgeTtsService(voiceName, outputPath);
};
}

View File

@@ -25,9 +25,7 @@ public class MiniMaxTtsService implements TtsService {
private static final String PROVIDER_NAME = "minimax";
private final String groupId;
private final String apiKey;
private final String outputPath;
private final String voiceName;
@@ -35,7 +33,6 @@ public class MiniMaxTtsService implements TtsService {
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
public MiniMaxTtsService(SysConfig config, String voiceName, String outputPath) {
this.groupId = config.getAppId();
this.apiKey = config.getApiKey();
this.voiceName = voiceName;
this.outputPath = outputPath;
@@ -59,29 +56,37 @@ public class MiniMaxTtsService implements TtsService {
}
private void sendRequest(String text, String filepath) {
var params = new Text2AudioParams(voiceName, text);
// 使用新版 API 参数结构支持用户配置model, voice_id
var params = new Text2AudioParams("speech-2.6-turbo", voiceName, text);
var request = new Request.Builder()
.url("https://api.minimaxi.com/v1/t2a_v2?Groupid=%s".formatted(groupId))
.url("https://api.minimax.io/v1/t2a_v2") // 新版 API endpoint
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer %s".formatted(apiKey)) // 添加Authorization头
.addHeader("Authorization", "Bearer %s".formatted(apiKey)) // 使用 token
.post(RequestBody.create(JsonUtil.toJson(params), JSON))
.build();
try (var resp = client.newCall(request).execute()) {
if (resp.isSuccessful()) {
var respBody = JsonUtil.fromJson(resp.body().string(), Text2AudioResp.class);
if (respBody.baseResp.statusCode == 0) {
if (respBody.baseResp != null && respBody.baseResp.statusCode == 0) {
var bytes = HexFormat.of().parseHex(respBody.data.audio);
Files.write(Paths.get(filepath), bytes);
log.info("MiniMax TTS 成功生成语音文件: {}", filepath);
} else {
log.error("TTS失败 {}:{}", respBody.baseResp.statusCode, respBody.baseResp.statusMsg);
String errorMsg = respBody.baseResp != null ?
respBody.baseResp.statusMsg : "未知错误";
log.error("MiniMax TTS 失败: {}", errorMsg);
throw new RuntimeException("MiniMax TTS 失败: " + errorMsg);
}
} else {
log.error("TTS请求失败 {}", resp.body().string());
String errorBody = resp.body() != null ? resp.body().string() : "无响应内容";
log.error("MiniMax TTS 请求失败 [HTTP {}]: {}", resp.code(), errorBody);
throw new RuntimeException("MiniMax TTS 请求失败: HTTP " + resp.code());
}
} catch (IOException e) {
log.error("发送TTS请求时发生错误", e);
throw new RuntimeException("发送TTS请求失败", e);
log.error("MiniMax TTS 请求异常", e);
throw new RuntimeException("MiniMax TTS 请求异常: " + e.getMessage(), e);
}
}
@@ -91,7 +96,7 @@ public class MiniMaxTtsService implements TtsService {
public static class Text2AudioParams {
public Text2AudioParams(String voiceId, String text) {
this("speech-02-hd", voiceId, text);
this("speech-2.6-turbo", voiceId, text);
}
public Text2AudioParams(String model, String voiceId, String text) {
@@ -99,33 +104,46 @@ public class MiniMaxTtsService implements TtsService {
this.text = text;
this.audioSetting = new AudioSetting();
this.voiceSetting = new VoiceSetting().setVoiceId(voiceId);
this.voiceModify = new VoiceModify(); // 新增:音色修改参数
}
private String model;
private String text;
private boolean stream = false;
private String languageBoost = "auto";
private String outputFormat = "hex";
private String model; // 用户可配置
private String text; // 用户可配置
private boolean stream = false; // 默认 false
private String languageBoost = "auto"; // 默认 auto
private String outputFormat = "hex"; // 默认 hex
private VoiceSetting voiceSetting;
private AudioSetting audioSetting;
private VoiceModify voiceModify; // 新增:音色修改
@Data
@Accessors(chain = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class VoiceSetting {
@JsonProperty("voice_id")
private String voiceId;
private double speed = 1;
private double vol = 1;
private String voiceId; // 用户可配置
private double speed = 1.0;
private double vol = 1.0;
private int pitch = 0;
private String emotion = "happy";
}
@Data
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class AudioSetting {
@JsonProperty("sample_rate")
private int sampleRate = 32000;
private int bitrate = 128000;
private String format = "mp3";
private int channel = 1; // 新增:声道数,默认单声道
}
@Data
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class VoiceModify {
private int pitch = 0;
private int intensity = 0;
private int timbre = 0;
// sound_effects 可选,默认不添加
}
}

View File

@@ -1,3 +1,8 @@
#!/bin/bash
# 添加 ffmpeg 到 PATH支持 Homebrew 的两种安装位置)
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
# 启动 Java 应用
nohup java -jar xiaozhi.server-pay.jar > output.log 2>&1 &

60
web/package-lock.json generated
View File

@@ -96,7 +96,8 @@
"node_modules/@ant-design/icons": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w==",
"peer": true
},
"node_modules/@ant-design/icons-vue": {
"version": "2.0.0",
@@ -357,6 +358,7 @@
"integrity": "sha512-Ajr4IcMXq/2QmMkEmSvxqfLN5zGmJ92gHXAeOXq1OekoH2rfDNsgdDoL2f7QaRCy7G/E6TpxBVdRuNraMztGHw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"co": "^4.6.0",
"fast-deep-equal": "^1.0.0",
@@ -902,6 +904,7 @@
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
"dev": true,
"peer": true,
"dependencies": {
"babel-code-frame": "^6.26.0",
"babel-generator": "^6.26.0",
@@ -1132,7 +1135,8 @@
"node_modules/babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==",
"peer": true
},
"node_modules/babel-helpers": {
"version": "6.24.1",
@@ -3547,6 +3551,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -4824,6 +4829,7 @@
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-4.9.0.tgz",
"integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
"peer": true,
"dependencies": {
"zrender": "4.3.2"
}
@@ -5237,6 +5243,7 @@
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"peer": true,
"dependencies": {
"ajv": "^5.3.0",
"babel-code-frame": "^6.22.0",
@@ -5413,6 +5420,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz",
"integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==",
"dev": true,
"peer": true,
"dependencies": {
"array-includes": "^3.1.1",
"array.prototype.flat": "^1.2.3",
@@ -5453,6 +5461,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz",
"integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==",
"dev": true,
"peer": true,
"dependencies": {
"ignore": "^3.3.6",
"minimatch": "^3.0.4",
@@ -5480,6 +5489,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz",
"integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==",
"dev": true,
"peer": true,
"engines": {
"node": ">=4"
}
@@ -5489,6 +5499,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz",
"integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==",
"dev": true,
"peer": true,
"peerDependencies": {
"eslint": ">=3.19.0"
}
@@ -6031,6 +6042,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -11070,6 +11082,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -12226,6 +12239,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -15223,6 +15237,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -15828,6 +15843,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -16235,7 +16251,8 @@
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==",
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details."
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
"peer": true
},
"node_modules/vue-cropper": {
"version": "0.5.5",
@@ -16415,6 +16432,7 @@
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
"integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==",
"peer": true,
"dependencies": {
"de-indent": "^1.0.2",
"he": "^1.1.0"
@@ -16734,6 +16752,7 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz",
"integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==",
"dev": true,
"peer": true,
"dependencies": {
"acorn": "^5.0.0",
"acorn-dynamic-import": "^2.0.0",
@@ -17342,6 +17361,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -17818,7 +17838,8 @@
"node_modules/zrender": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-4.3.2.tgz",
"integrity": "sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g=="
"integrity": "sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g==",
"peer": true
}
},
"dependencies": {
@@ -17833,7 +17854,8 @@
"@ant-design/icons": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w==",
"peer": true
},
"@ant-design/icons-vue": {
"version": "2.0.0",
@@ -18062,6 +18084,7 @@
"resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha512-Ajr4IcMXq/2QmMkEmSvxqfLN5zGmJ92gHXAeOXq1OekoH2rfDNsgdDoL2f7QaRCy7G/E6TpxBVdRuNraMztGHw==",
"dev": true,
"peer": true,
"requires": {
"co": "^4.6.0",
"fast-deep-equal": "^1.0.0",
@@ -18490,6 +18513,7 @@
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
"dev": true,
"peer": true,
"requires": {
"babel-code-frame": "^6.26.0",
"babel-generator": "^6.26.0",
@@ -18711,7 +18735,8 @@
"babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==",
"peer": true
},
"babel-helpers": {
"version": "6.24.1",
@@ -20862,6 +20887,7 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"dev": true,
"peer": true,
"requires": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -21784,6 +21810,7 @@
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-4.9.0.tgz",
"integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
"peer": true,
"requires": {
"zrender": "4.3.2"
}
@@ -22133,6 +22160,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"dev": true,
"peer": true,
"requires": {
"ajv": "^5.3.0",
"babel-code-frame": "^6.22.0",
@@ -22291,6 +22319,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz",
"integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==",
"dev": true,
"peer": true,
"requires": {
"array-includes": "^3.1.1",
"array.prototype.flat": "^1.2.3",
@@ -22324,6 +22353,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz",
"integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==",
"dev": true,
"peer": true,
"requires": {
"ignore": "^3.3.6",
"minimatch": "^3.0.4",
@@ -22343,13 +22373,15 @@
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz",
"integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==",
"dev": true
"dev": true,
"peer": true
},
"eslint-plugin-standard": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz",
"integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==",
"dev": true,
"peer": true,
"requires": {}
},
"eslint-plugin-vue": {
@@ -22767,6 +22799,7 @@
"resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"peer": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -26701,6 +26734,7 @@
"resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"peer": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -27612,6 +27646,7 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"dev": true,
"peer": true,
"requires": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -30026,6 +30061,7 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"dev": true,
"peer": true,
"requires": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -30488,6 +30524,7 @@
"resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"peer": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -30826,7 +30863,8 @@
"vue": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==",
"peer": true
},
"vue-cropper": {
"version": "0.5.5",
@@ -30985,6 +31023,7 @@
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
"integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==",
"peer": true,
"requires": {
"de-indent": "^1.0.2",
"he": "^1.1.0"
@@ -31256,6 +31295,7 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz",
"integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==",
"dev": true,
"peer": true,
"requires": {
"acorn": "^5.0.0",
"acorn-dynamic-import": "^2.0.0",
@@ -31286,6 +31326,7 @@
"resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"peer": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -32134,7 +32175,8 @@
"zrender": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-4.3.2.tgz",
"integrity": "sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g=="
"integrity": "sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g==",
"peer": true
}
}
}

File diff suppressed because it is too large Load Diff

BIN
xiaozhi-server-latest.tar Normal file

Binary file not shown.