feat: 1130
This commit is contained in:
@@ -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"]
|
||||
|
||||
216
MINIMAX_WEBSOCKET_TTS_使用说明.md
Normal file
216
MINIMAX_WEBSOCKET_TTS_使用说明.md
Normal 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
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 可选,默认不添加
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
60
web/package-lock.json
generated
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17455
web/yarn.lock
17455
web/yarn.lock
File diff suppressed because it is too large
Load Diff
BIN
xiaozhi-server-latest.tar
Normal file
BIN
xiaozhi-server-latest.tar
Normal file
Binary file not shown.
Reference in New Issue
Block a user