d4bf3627fd
新增运动节拍RepClock全套小程序页面、后端API与数据库服务,新增subhub子工具汇总页面,优化全局主页样式与配置,为web静态资源添加版本缓存参数,补充配套调试脚本
80 lines
2.7 KiB
JavaScript
80 lines
2.7 KiB
JavaScript
const fs = require('fs')
|
|
const path = require('path')
|
|
const envPath = path.join(process.env.USERPROFILE || 'C:\\Users\\Administrator', 'Toolbox_local_creds.env.local')
|
|
if (fs.existsSync(envPath)) {
|
|
const text = fs.readFileSync(envPath, 'utf8')
|
|
for (const line of text.split(/\r?\n/)) {
|
|
if (!line || /^\s*#/.test(line)) continue
|
|
const i = line.indexOf('=')
|
|
if (i < 0) continue
|
|
const k = line.slice(0, i).trim(), v = line.slice(i + 1).trim().replace(/^["']|["']$/g, '')
|
|
if (k && !(k in process.env)) process.env[k] = v
|
|
}
|
|
}
|
|
process.chdir('d:/Trae_Files/TRAE-Toolbox')
|
|
global.__builtin_fetch = globalThis.fetch
|
|
|
|
const crypto = require('crypto')
|
|
const apiKey = process.env.DASHSCOPE_API_KEY
|
|
const t = '热身开合跳'
|
|
const headers = {
|
|
'Authorization': `Bearer ${apiKey}`,
|
|
'Content-Type': 'application/json',
|
|
}
|
|
|
|
const CANDIDATES = []
|
|
CANDIDATES.push({
|
|
name: 'Fallback-A:Qwen3-TTS',
|
|
url: 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation',
|
|
body: {
|
|
model: 'qwen3-tts-flash',
|
|
input: { text: t, voice: 'Cherry', language_type: 'Chinese' },
|
|
},
|
|
})
|
|
CANDIDATES.push({
|
|
name: 'Fallback-B:CosyVoice-v3',
|
|
url: 'https://dashscope.aliyuncs.com/api/v1/services/audio/tts/SpeechSynthesizer',
|
|
body: {
|
|
model: 'cosyvoice-v3-flash',
|
|
input: { text: t, voice: 'longanyang', format: 'mp3', sample_rate: 24000 },
|
|
},
|
|
})
|
|
|
|
async function run() {
|
|
for (const c of CANDIDATES) {
|
|
console.log('\n======== try', c.name, '========')
|
|
try {
|
|
const resp = await global.__builtin_fetch(c.url, {
|
|
method: 'POST',
|
|
headers,
|
|
body: JSON.stringify(c.body),
|
|
})
|
|
console.log('status=', resp.status, 'OK=', resp.ok)
|
|
const txt = await resp.text()
|
|
console.log('text head=', txt.slice(0, 800))
|
|
if (resp.ok) {
|
|
try {
|
|
const j = JSON.parse(txt)
|
|
let audioUrl = ''
|
|
const output = (j && j.output) || null
|
|
if (output) {
|
|
if (output.audio && typeof output.audio.url === 'string') audioUrl = output.audio.url
|
|
}
|
|
console.log('audioUrl=', audioUrl)
|
|
if (audioUrl) {
|
|
const dl = await global.__builtin_fetch(audioUrl)
|
|
console.log('download status=', dl.status, 'len=', dl.headers && dl.headers.get ? dl.headers.get('content-length') : '?')
|
|
if (dl.ok) {
|
|
const buf = Buffer.from(await dl.arrayBuffer())
|
|
const p = path.join(process.env.TEMP || '.', 'tts_dl_' + Date.now() + '.mp3')
|
|
fs.writeFileSync(p, buf)
|
|
console.log('saved to', p, 'bytes=', buf.length)
|
|
}
|
|
}
|
|
} catch (e) { console.log('json parse err', e.message) }
|
|
}
|
|
} catch (e) { console.log('ex', e && e.message ? e.message : e) }
|
|
}
|
|
}
|
|
run()
|