mirror of
https://github.com/m5stack/StackFlow.git
synced 2026-05-20 11:32:11 -07:00
[update] release cosyvoice2
This commit is contained in:
@@ -17,7 +17,7 @@ cosy_voice
|
||||
"object": "cosy_voice.setup",
|
||||
"data": {
|
||||
"model": "CosyVoice2-0.5B-axcl",
|
||||
"response_format": "sys.pcm",
|
||||
"response_format": "file",
|
||||
"input": "tts.utf-8",
|
||||
"enoutput": false
|
||||
}
|
||||
@@ -30,7 +30,8 @@ cosy_voice
|
||||
- action:调用的方法为 `setup`。
|
||||
- object:传输的数据类型为 `cosy_voice.setup`。
|
||||
- model:使用的模型为 `CosyVoice2-0.5B-axcl` 模型。
|
||||
- response_format:返回结果为 `sys.pcm`, 系统音频数据,并直接发送到 llm-audio 模块进行播放。
|
||||
- prompt_files:要克隆的音频信息文件。
|
||||
- response_format:返回结果为 `sys.pcm`, 系统音频数据,并直接发送到 llm-audio 模块进行播放。返回结果为 `file`, 生成的音频写 wav 文件,可用 `prompt_data` 指定路径或文件名。
|
||||
- input:输入的为 `tts.utf-8`,代表的是从用户输入。
|
||||
- enoutput:是否起用用户结果输出。
|
||||
|
||||
|
||||
@@ -17,7 +17,10 @@ LDFLAGS = []
|
||||
LINK_SEARCH_PATH = []
|
||||
STATIC_FILES = []
|
||||
|
||||
python_venv = check_wget_down("https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/linux/llm/m5stack_llm-cosy-voice-python-venv_v1.7.tar.gz", 'm5stack_llm-cosy-voice-python-venv_v1.7.tar.gz')
|
||||
if "CONFIG_AXCL_ENABLED" in os.environ:
|
||||
python_venv = check_wget_down("https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/linux/llm/m5stack_llm-cosy-voice-python-axcl-venv_v1.8.tar.gz", 'm5stack_llm-cosy-voice-python-axc-venv_v1.8.tar.gz')
|
||||
else:
|
||||
python_venv = check_wget_down("https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/linux/llm/m5stack_llm-cosy-voice-python-venv_v1.7.tar.gz", 'm5stack_llm-cosy-voice-python-venv_v1.7.tar.gz')
|
||||
|
||||
# REQUIREMENTS += ['Backward_cpp']
|
||||
# DYNAMIC_LIB += [ AFile('../static_lib/libdw.so.1'),
|
||||
@@ -45,6 +48,7 @@ INCLUDE += [ADir('../static_lib/include/sentencepiece'),
|
||||
static_file = Glob('../static_lib/module-llm/libabsl_*')
|
||||
static_file += [AFile('../static_lib/module-llm/libre2.a'), AFile('../static_lib/module-llm/libsentencepiece.a'), AFile('../static_lib/module-llm/libsentencepiece_train.a')]
|
||||
STATIC_LIB += static_file * 4
|
||||
|
||||
REQUIREMENTS += ['onnxruntime']
|
||||
STATIC_FILES += [os.path.join(python_venv, 'cosy-voice')]
|
||||
STATIC_FILES += Glob('scripts/tokenizer*')
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
"flow_estimator_300": "flow_estimator_300.axmodel",
|
||||
"hift_p2_50_first": "hift_p2_50_first.axmodel",
|
||||
"hift_p2_58": "hift_p2_58.axmodel",
|
||||
"hift_p1_50_first": "hift_p1_50_first.onnx",
|
||||
"hift_p1_58": "hift_p1_58.onnx",
|
||||
"hift_p1_50_first": "hift_p1_50_first.ort",
|
||||
"hift_p1_58": "hift_p1_58.ort",
|
||||
"prompt_dir": "prompt_data",
|
||||
"prompt_text": "prompt_text.txt",
|
||||
"llm_prompt_speech_token": "llm_prompt_speech_token.txt",
|
||||
|
||||
@@ -317,10 +317,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
readtxt(infer_mode_config_.prompt_text, prompt_text_token);
|
||||
readtxt(infer_mode_config_.llm_prompt_speech_token, prompt_speech_token);
|
||||
readtxt(infer_mode_config_.prompt_speech_feat, prompt_feat);
|
||||
readtxt<float>(infer_mode_config_.flow_embedding, spk_embeds);
|
||||
if (readtxt(infer_mode_config_.prompt_text, prompt_text_token)) return -3;
|
||||
if (readtxt(infer_mode_config_.llm_prompt_speech_token, prompt_speech_token)) return -3;
|
||||
if (readtxt(infer_mode_config_.prompt_speech_feat, prompt_feat)) return -3;
|
||||
if (readtxt<float>(infer_mode_config_.flow_embedding, spk_embeds)) return -3;
|
||||
|
||||
lLaMa_ = std::make_unique<LLM>();
|
||||
if (!lLaMa_->Init(mode_config_)) {
|
||||
@@ -432,6 +432,7 @@ public:
|
||||
int prompt_token_len = prompt_speech_embeds_flow.size() / lToken2Wav._attr.flow_embed_size;
|
||||
if (prompt_token_len < 75) {
|
||||
SLOGE("Error, prompt speech token len %d < 75", prompt_token_len);
|
||||
if (llm_thread.joinable()) llm_thread.join();
|
||||
return -1;
|
||||
}
|
||||
int prompt_token_align_len = 75;
|
||||
|
||||
@@ -3,71 +3,52 @@
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <type_traits> // 用于类型检查
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <stdexcept> // 用于异常处理
|
||||
#include <stdexcept>
|
||||
|
||||
// 函数模板:支持任意元素类型的vector
|
||||
template <typename T>
|
||||
void savetxt(const std::string& filename,
|
||||
const std::vector<T>& data,
|
||||
char delimiter = ' ',
|
||||
int precision = 6) // 默认精度调整为6位
|
||||
void savetxt(const std::string& filename, const std::vector<T>& data, char delimiter = ' ', int precision = 6)
|
||||
{
|
||||
std::ofstream outfile(filename);
|
||||
if (!outfile.is_open()) {
|
||||
throw std::runtime_error("无法打开文件: " + filename);
|
||||
throw std::runtime_error("Unable to open file: " + filename);
|
||||
}
|
||||
|
||||
// 保存流的原始格式状态
|
||||
std::ios_base::fmtflags original_flags = outfile.flags();
|
||||
|
||||
// 仅对浮点类型启用科学计数法
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
outfile << std::scientific << std::setprecision(precision);
|
||||
}
|
||||
|
||||
// 优化输出:先输出第一个元素,再循环输出后续元素
|
||||
if (!data.empty()) {
|
||||
outfile << data[0];
|
||||
for (size_t i = 1; i < data.size(); ++i) {
|
||||
outfile << delimiter << data[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复流的原始格式状态
|
||||
outfile.flags(original_flags);
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 函数模板:读取文本文件到 vector<T>
|
||||
template <typename T>
|
||||
int readtxt(const std::string& filename, std::vector<T>& data) {
|
||||
int readtxt(const std::string& filename, std::vector<T>& data)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "错误:无法打开文件 " << filename << std::endl;
|
||||
std::cerr << "Error: Unable to open file " << filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
// 跳过空行
|
||||
if (line.empty()) continue;
|
||||
|
||||
std::istringstream iss(line);
|
||||
T value;
|
||||
// 解析行中的每个数值
|
||||
while (iss >> value) {
|
||||
data.push_back(value);
|
||||
// 跳过分隔符(兼容逗号、分号等)
|
||||
if (iss.peek() == ',' || iss.peek() == ';') iss.ignore();
|
||||
}
|
||||
}
|
||||
@@ -75,23 +56,19 @@ int readtxt(const std::string& filename, std::vector<T>& data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<float> linspace(float start, float end, std::size_t num_steps) {
|
||||
std::vector<float> linspace(float start, float end, std::size_t num_steps)
|
||||
{
|
||||
if (num_steps == 0) {
|
||||
return {}; // 返回空向量
|
||||
return {};
|
||||
}
|
||||
if (num_steps == 1) {
|
||||
return {start}; // 如果只需要一个点,返回起始值
|
||||
return {start};
|
||||
}
|
||||
|
||||
std::vector<float> result(num_steps);
|
||||
float step_size = (end - start) / (num_steps - 1); // 计算步长
|
||||
|
||||
float step_size = (end - start) / (num_steps - 1);
|
||||
for (std::size_t i = 0; i < num_steps; ++i) {
|
||||
result[i] = start + i * step_size;
|
||||
}
|
||||
|
||||
// 确保最后一个值精确等于 end,避免浮点数精度带来的误差
|
||||
result.back() = end;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -150,52 +150,67 @@ def create_lib_deb(package_name, version, src_folder, revision = 'm5stack1'):
|
||||
shutil.rmtree(deb_folder)
|
||||
return package_name + " creat success!"
|
||||
|
||||
def create_data_deb(package_name, version, src_folder, revision = 'm5stack1', depends = 'lib-llm (>= 1.6)'):
|
||||
def create_data_deb(package_name, version, src_folder, revision='m5stack1', depends='lib-llm (>= 1.6)'):
|
||||
deb_file = f"{package_name}_{version}-{revision}_arm64.deb"
|
||||
deb_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'debian-{}'.format(package_name))
|
||||
deb_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), f'debian-{package_name}')
|
||||
|
||||
if os.path.exists(deb_folder):
|
||||
shutil.rmtree(deb_folder)
|
||||
os.makedirs(deb_folder, exist_ok = True)
|
||||
os.makedirs(deb_folder, exist_ok=True)
|
||||
|
||||
zip_file = f"m5stack_{package_name[0:4]+package_name[10:]}_{version}_data.tar.gz"
|
||||
down_url = f"https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/linux/llm/m5stack_{package_name[0:4]+package_name[10:]}_{version}_data.tar.gz"
|
||||
zip_file_extrpath = f"m5stack_{package_name}_{version}_data"
|
||||
|
||||
if not os.path.exists(zip_file_extrpath):
|
||||
# Downloading via HTTP (more common)
|
||||
if not os.path.exists(zip_file):
|
||||
response = requests.get(down_url)
|
||||
if response.status_code == 200:
|
||||
with open(zip_file, 'wb') as file:
|
||||
file.write(response.content)
|
||||
else:
|
||||
print("{} down failed".format(down_url))
|
||||
print(f"{down_url} download failed.")
|
||||
with tarfile.open(zip_file, 'r:gz') as tar:
|
||||
tar.extractall(path=zip_file_extrpath)
|
||||
print("The {} download successful.".format(down_url))
|
||||
print(f"The {down_url} download successful.")
|
||||
|
||||
if os.path.exists(zip_file_extrpath):
|
||||
shutil.copytree(zip_file_extrpath, os.path.join(deb_folder, 'opt/m5stack/data'))
|
||||
|
||||
RED = "\033[31m"
|
||||
RESET = "\033[0m"
|
||||
os.makedirs(os.path.join(deb_folder, 'opt/m5stack/data/models'), exist_ok = True)
|
||||
mode_config_file = os.path.join(src_folder,'mode_{}.json'.format(package_name[10:]))
|
||||
os.makedirs(os.path.join(deb_folder, 'opt/m5stack/data/models'), exist_ok=True)
|
||||
|
||||
mode_config_file = os.path.join(src_folder, f'mode_{package_name[10:]}.json')
|
||||
if os.path.exists(mode_config_file):
|
||||
shutil.copy2(mode_config_file, os.path.join(deb_folder, 'opt/m5stack/data/models', 'mode_{}.json'.format(package_name[10:])))
|
||||
shutil.copy2(mode_config_file, os.path.join(deb_folder, 'opt/m5stack/data/models', f'mode_{package_name[10:]}.json'))
|
||||
|
||||
try:
|
||||
with open(mode_config_file, 'r', encoding='utf-8') as file:
|
||||
data = json.load(file)
|
||||
for scripts_file in data['mode_param']['ext_scripts']:
|
||||
tokenizer_py_file = os.path.join(src_folder, scripts_file)
|
||||
if os.path.exists(tokenizer_py_file):
|
||||
os.makedirs(os.path.join(deb_folder, 'opt/m5stack/scripts'), exist_ok = True)
|
||||
shutil.copy2(tokenizer_py_file, os.path.join(deb_folder, 'opt/m5stack/scripts', scripts_file))
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
print(RED, mode_config_file, " miss", RESET)
|
||||
|
||||
os.makedirs(os.path.join(deb_folder, 'DEBIAN'), exist_ok = True)
|
||||
with open(os.path.join(deb_folder, 'DEBIAN/control'),'w') as f:
|
||||
for scripts_file in data['mode_param'].get('ext_scripts', []):
|
||||
src_path = os.path.join(src_folder, scripts_file)
|
||||
dest_dir = os.path.join(deb_folder, 'opt/m5stack/scripts')
|
||||
os.makedirs(dest_dir, exist_ok=True)
|
||||
|
||||
if os.path.isfile(src_path):
|
||||
shutil.copy2(src_path, os.path.join(dest_dir, os.path.basename(scripts_file)))
|
||||
print(f"Copied file: {scripts_file}")
|
||||
elif os.path.isdir(src_path):
|
||||
shutil.copytree(src_path, os.path.join(dest_dir, os.path.basename(scripts_file)), dirs_exist_ok=True)
|
||||
print(f"Copied folder: {scripts_file}")
|
||||
else:
|
||||
print(f"Warning: {scripts_file} not found in {src_folder}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error reading ext_scripts: {e}")
|
||||
|
||||
else:
|
||||
print(RED, mode_config_file, " missing", RESET)
|
||||
|
||||
os.makedirs(os.path.join(deb_folder, 'DEBIAN'), exist_ok=True)
|
||||
with open(os.path.join(deb_folder, 'DEBIAN/control'), 'w') as f:
|
||||
f.write(f'Package: {package_name}\n')
|
||||
f.write(f'Version: {version}\n')
|
||||
f.write(f'Architecture: arm64\n')
|
||||
@@ -207,21 +222,22 @@ def create_data_deb(package_name, version, src_folder, revision = 'm5stack1', de
|
||||
f.write(f'Homepage: https://www.m5stack.com\n')
|
||||
if deb_file.startswith('llm-model-'):
|
||||
deb_name = deb_file[:deb_file.find('_')]
|
||||
old_deb_name = deb_name.replace('model-','').lower()
|
||||
f.write(f'Conflicts: {old_deb_name}\n')
|
||||
f.write(f'Packaged-Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n')
|
||||
old_deb_name = deb_name.replace('model-', '').lower()
|
||||
f.write(f'Conflicts: {old_deb_name}\n')
|
||||
f.write(f'Packaged-Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n')
|
||||
f.write(f'Description: llm-module\n')
|
||||
f.write(f' bsp.\n')
|
||||
with open(os.path.join(deb_folder, 'DEBIAN/postinst'),'w') as f:
|
||||
f.write(f'#!/bin/sh\n')
|
||||
f.write(f'exit 0\n')
|
||||
with open(os.path.join(deb_folder, 'DEBIAN/prerm'),'w') as f:
|
||||
f.write(f'#!/bin/sh\n')
|
||||
f.write(f'exit 0\n')
|
||||
|
||||
with open(os.path.join(deb_folder, 'DEBIAN/postinst'), 'w') as f:
|
||||
f.write('#!/bin/sh\nexit 0\n')
|
||||
with open(os.path.join(deb_folder, 'DEBIAN/prerm'), 'w') as f:
|
||||
f.write('#!/bin/sh\nexit 0\n')
|
||||
os.chmod(os.path.join(deb_folder, 'DEBIAN/postinst'), 0o755)
|
||||
os.chmod(os.path.join(deb_folder, 'DEBIAN/prerm'), 0o755)
|
||||
|
||||
subprocess.run(["dpkg-deb", "-b", deb_folder, deb_file], check=True)
|
||||
print(f"Debian package created: {deb_file}")
|
||||
|
||||
shutil.rmtree(deb_folder)
|
||||
return package_name + " creat success!"
|
||||
|
||||
@@ -262,6 +278,10 @@ def create_bin_deb(package_name, version, src_folder, revision = 'm5stack1', dep
|
||||
vlm_dir = os.path.join(src_folder, 'vlm')
|
||||
if os.path.exists(vlm_dir):
|
||||
shutil.copytree(vlm_dir, os.path.join(deb_folder, 'opt/m5stack/lib/vlm'))
|
||||
if package_name == 'llm-cosy-voice':
|
||||
cosy_voice_dir = os.path.join(src_folder, 'cosy-voice')
|
||||
if os.path.exists(cosy_voice_dir):
|
||||
shutil.copytree(cosy_voice_dir, os.path.join(deb_folder, 'opt/m5stack/lib/cosy-voice'))
|
||||
|
||||
bin_file_name = package_name.replace("-", "_")
|
||||
if version_info != 0.0:
|
||||
@@ -368,6 +388,7 @@ if __name__ == "__main__":
|
||||
'llm-vad':[create_bin_deb,'llm-vad', '1.8', src_folder, revision],
|
||||
'llm-whisper':[create_bin_deb,'llm-whisper', '1.8', src_folder, revision],
|
||||
'llm-openai-api':[create_bin_deb,'llm-openai-api', '1.8', src_folder, revision],
|
||||
'llm-cosy-voice':[create_bin_deb,'llm-cosy-voice', '1.8', src_folder, revision],
|
||||
# keyword spotting Audio file
|
||||
'llm-model-audio-en-us':[create_data_deb,'llm-model-audio-en-us', data_version, src_folder, revision],
|
||||
'llm-model-audio-zh-cn':[create_data_deb,'llm-model-audio-zh-cn', data_version, src_folder, revision],
|
||||
@@ -409,6 +430,9 @@ if __name__ == "__main__":
|
||||
'llm-model-melotts-en-us-axcl':[create_data_deb,'llm-model-melotts-en-us-axcl', '0.6', src_folder, revision],
|
||||
'llm-model-melotts-ja-jp-axcl':[create_data_deb,'llm-model-melotts-ja-jp-axcl', '0.6', src_folder, revision],
|
||||
'llm-model-melotts-es-es-axcl':[create_data_deb,'llm-model-melotts-es-es-axcl', '0.5', src_folder, revision],
|
||||
# CosyVoice2 model
|
||||
## AXCL
|
||||
'llm-model-CosyVoice2-0.5B-axcl':[create_data_deb,'llm-model-CosyVoice2-0.5B-axcl', '0.6', src_folder, revision],
|
||||
# Yolo model
|
||||
## AX630C
|
||||
'llm-model-yolo11n':[create_data_deb,'llm-model-yolo11n', data_version, src_folder, revision],
|
||||
|
||||
Reference in New Issue
Block a user