24cd9cef53
- uni-app Vue3 frontend with dark glassmorphism theme - 5 AI dimensions: Origin / Development / Current / Learning / Trend - AI Chat system prompt updated from geometry to AI - 23 AI knowledge articles initialized in DB - Trend API + cron job for daily news - Product pricing (Pro ¥19.9, VIP ¥39.9) - Pinia stores + API utilities - AGENTS.md documentation
177 lines
4.9 KiB
JavaScript
Executable File
177 lines
4.9 KiB
JavaScript
Executable File
/**
|
|
* 批量生成拼音音频URL脚本
|
|
* 支持多种TTS服务:有道词典、百度语音、科大讯飞等
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// 拼音列表
|
|
const initials = ['b','p','m','f','d','t','n','l','g','k','h','j','q','x','zh','ch','sh','r','z','c','s','y','w'];
|
|
const finals = ['a','o','e','i','u','ü','ai','ei','ui','ao','ou','iu','ie','üe','er','an','en','in','un','ün','ang','eng','ing','ong'];
|
|
const overalls = ['zhi','chi','shi','ri','zi','ci','si','yi','wu','yu','ye','yue','yuan','yin','yun','ying'];
|
|
|
|
/**
|
|
* 有道词典TTS服务
|
|
* 优点:免费、无需注册、支持中文
|
|
* 缺点:音质一般
|
|
*/
|
|
function getYoudaoUrl(text) {
|
|
// 从环境变量读取TTS基础URL
|
|
const ttsBaseUrl = process.env.TTS_BASE_URL || 'https://dict.youdao.com/dictvoice';
|
|
return `${ttsBaseUrl}?audio=${encodeURIComponent(text)}&type=1`;
|
|
}
|
|
|
|
/**
|
|
* 生成所有拼音的音频URL配置
|
|
*/
|
|
function generateAudioConfig() {
|
|
// 从环境变量读取配置
|
|
const ttsProvider = process.env.TTS_PROVIDER || 'youdao';
|
|
const ttsBaseUrl = process.env.TTS_BASE_URL || 'https://dict.youdao.com/dictvoice';
|
|
|
|
const config = {
|
|
// TTS服务提供商
|
|
provider: ttsProvider,
|
|
// 基础URL
|
|
baseUrl: ttsBaseUrl,
|
|
// 所有拼音的音频URL
|
|
audios: {}
|
|
};
|
|
|
|
// 声母
|
|
initials.forEach(symbol => {
|
|
config.audios[symbol] = {
|
|
url: getYoudaoUrl(symbol),
|
|
name: getPinyinName(symbol),
|
|
type: 'initial'
|
|
};
|
|
});
|
|
|
|
// 韵母
|
|
finals.forEach(symbol => {
|
|
config.audios[symbol] = {
|
|
url: getYoudaoUrl(symbol),
|
|
name: getPinyinName(symbol),
|
|
type: 'final'
|
|
};
|
|
});
|
|
|
|
// 整体认读
|
|
overalls.forEach(symbol => {
|
|
config.audios[symbol] = {
|
|
url: getYoudaoUrl(symbol),
|
|
name: getPinyinName(symbol),
|
|
type: 'overall'
|
|
};
|
|
});
|
|
|
|
return config;
|
|
}
|
|
|
|
/**
|
|
* 获取拼音名称
|
|
*/
|
|
function getPinyinName(symbol) {
|
|
const nameMap = {
|
|
'b': '玻', 'p': '坡', 'm': '摸', 'f': '佛',
|
|
'd': '得', 't': '特', 'n': '讷', 'l': '勒',
|
|
'g': '哥', 'k': '科', 'h': '喝',
|
|
'j': '基', 'q': '欺', 'x': '希',
|
|
'zh': '知', 'ch': '蚩', 'sh': '诗', 'r': '日',
|
|
'z': '资', 'c': '雌', 's': '思',
|
|
'y': '医', 'w': '巫',
|
|
'a': '啊', 'o': '喔', 'e': '鹅', 'i': '衣', 'u': '乌', 'ü': '迂',
|
|
'ai': '哀', 'ei': '诶', 'ui': '威', 'ao': '熬', 'ou': '欧',
|
|
'iu': '优', 'ie': '耶', 'üe': '约', 'er': '儿',
|
|
'an': '安', 'en': '恩', 'in': '因', 'un': '温', 'ün': '晕',
|
|
'ang': '昂', 'eng': '亨', 'ing': '英', 'ong': '雍',
|
|
'zhi': '织', 'chi': '吃', 'shi': '狮', 'ri': '日',
|
|
'zi': '资', 'ci': '疵', 'si': '丝',
|
|
'yi': '衣', 'wu': '乌', 'yu': '迂',
|
|
'ye': '耶', 'yue': '约', 'yuan': '冤',
|
|
'yin': '因', 'yun': '晕', 'ying': '英'
|
|
};
|
|
return nameMap[symbol] || symbol;
|
|
}
|
|
|
|
/**
|
|
* 生成SQL更新语句(用于直接更新数据库)
|
|
*/
|
|
function generateSqlUpdates() {
|
|
const config = generateAudioConfig();
|
|
const sqls = [];
|
|
|
|
Object.entries(config.audios).forEach(([symbol, data]) => {
|
|
const sql = `UPDATE pinyin_contents SET audio_url = '${data.url}' WHERE symbol = '${symbol}';`;
|
|
sqls.push(sql);
|
|
});
|
|
|
|
return sqls.join('\n');
|
|
}
|
|
|
|
/**
|
|
* 生成MongoDB更新脚本
|
|
*/
|
|
function generateMongoScript() {
|
|
const config = generateAudioConfig();
|
|
const updates = [];
|
|
|
|
Object.entries(config.audios).forEach(([symbol, data]) => {
|
|
updates.push({
|
|
updateOne: {
|
|
filter: { symbol: symbol },
|
|
update: { $set: { audioUrl: data.url } }
|
|
}
|
|
});
|
|
});
|
|
|
|
return `db.pinyincontents.bulkWrite(${JSON.stringify(updates, null, 2)});`;
|
|
}
|
|
|
|
/**
|
|
* 保存配置文件
|
|
*/
|
|
function saveConfig() {
|
|
const config = generateAudioConfig();
|
|
const outputPath = path.join(__dirname, '../../config/pinyin-audio-config.json');
|
|
|
|
// 确保目录存在
|
|
const dir = path.dirname(outputPath);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
|
|
fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));
|
|
console.log(`✅ 音频配置已保存到: ${outputPath}`);
|
|
|
|
// 生成SQL文件
|
|
const sqlPath = path.join(__dirname, '../../config/update-audio-urls.sql');
|
|
fs.writeFileSync(sqlPath, generateSqlUpdates());
|
|
console.log(`✅ SQL更新脚本已保存到: ${sqlPath}`);
|
|
|
|
// 生成MongoDB脚本
|
|
const mongoPath = path.join(__dirname, '../../config/update-audio-urls.js');
|
|
fs.writeFileSync(mongoPath, generateMongoScript());
|
|
console.log(`✅ MongoDB更新脚本已保存到: ${mongoPath}`);
|
|
|
|
// 输出统计
|
|
console.log('\n📊 生成统计:');
|
|
console.log(` - 声母: ${initials.length} 个`);
|
|
console.log(` - 韵母: ${finals.length} 个`);
|
|
console.log(` - 整体认读: ${overalls.length} 个`);
|
|
console.log(` - 总计: ${initials.length + finals.length + overalls.length} 个拼音`);
|
|
}
|
|
|
|
// 运行
|
|
if (require.main === module) {
|
|
saveConfig();
|
|
}
|
|
|
|
module.exports = {
|
|
generateAudioConfig,
|
|
generateSqlUpdates,
|
|
generateMongoScript,
|
|
getYoudaoUrl
|
|
};
|