chatgpt-plugin/utils/tts/voicevox.js
2ndelement 6267d2d842
在新的多TTS源模式下添加了VoiceVox源 (#381)
* feat: 添加基于voicevox语音支持

* fix: 配置里添加voicevox语音源

* fix: 切换语音模式对各种语言源提示错误

* fix: 修正voicevox角色风格设置问题

* fix: 修改角色性格切换问题

* fix: 解决角色性格切换问题

* fix 换源分支少打个break(java17-user是这样的)

* fix: 支持云转码的一些调整

---------

Co-authored-by: 葛胤池 <geyinchi@buaa.edu.cn>
2023-04-29 18:45:33 +08:00

225 lines
8.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Config } from '../config.js'
let proxy
if (Config.proxy) {
try {
proxy = (await import('https-proxy-agent')).default
} catch (e) {
console.warn('未安装https-proxy-agent请在插件目录下执行pnpm add https-proxy-agent')
}
}
const newFetch = (url, options = {}) => {
const defaultOptions = Config.proxy
? {
agent: proxy(Config.proxy)
}
: {}
const mergedOptions = {
...defaultOptions,
...options
}
return fetch(url, mergedOptions)
}
async function generateAudio (text, options = {}) {
let host = Config.voicevoxSpace
let speaker = options.speaker || '随机'
if (speaker === '随机') {
speaker = supportConfigurations[Math.floor(Math.random() * supportConfigurations.length)].name
}
let regex = /^(.*?)-(.*)$/
let match = regex.exec(speaker)
let style = null
if (match) {
speaker = match[1]
style = match[2]
}
speaker = supportConfigurations.find(s => s.name === speaker)
let speakerId
if (style) {
speakerId = speaker.styles.find(s => s.name === style).id
} else {
speakerId = speaker.styles[Math.floor(Math.random() * speaker?.styles.length)].id
}
logger.info(`使用${speaker.name}${speaker.styles.find(s => s.id === speakerId).name}风格基于文本${text}生成语音。`)
const accentPhrasesResponse = await newFetch(`${host}/accent_phrases?text=${encodeURIComponent(text)}&speaker=${speakerId}`, {
method: 'POST'
})
const accentPhrases = await accentPhrasesResponse.json()
const synthesisResponse = await newFetch(`${host}/synthesis?speaker=${speakerId}&enable_interrogative_upspeak=false`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
accent_phrases: accentPhrases,
speedScale: 1,
pitchScale: 0,
intonationScale: 1,
volumeScale: 1,
prePhonemeLength: 0.1,
postPhonemeLength: 0.1,
outputSamplingRate: 24000,
outputStereo: false
})
})
const synthesisResponseData = await synthesisResponse.arrayBuffer()
return Buffer.from(synthesisResponseData)
}
const supportConfigurations = [
{
supported_features: { permitted_synthesis_morphing: 'SELF_ONLY' },
name: '四国めたん',
speaker_uuid: '7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff',
styles: [{ name: 'ノーマル', id: 2 }, { name: 'あまあま', id: 0 }, { name: 'ツンツン', id: 6 }, {
name: 'セクシー', id: 4
}, { name: 'ささやき', id: 36 }, { name: 'ヒソヒソ', id: 37 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'SELF_ONLY' },
name: 'ずんだもん',
speaker_uuid: '388f246b-8c41-4ac1-8e2d-5d79f3ff56d9',
styles: [{ name: 'ノーマル', id: 3 }, { name: 'あまあま', id: 1 }, { name: 'ツンツン', id: 7 }, {
name: 'セクシー', id: 5
}, { name: 'ささやき', id: 22 }, { name: 'ヒソヒソ', id: 38 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '春日部つむぎ',
speaker_uuid: '35b2c544-660e-401e-b503-0e14c635303a',
styles: [{ name: 'ノーマル', id: 8 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '雨晴はう',
speaker_uuid: '3474ee95-c274-47f9-aa1a-8322163d96f1',
styles: [{ name: 'ノーマル', id: 10 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '波音リツ',
speaker_uuid: 'b1a81618-b27b-40d2-b0ea-27a9ad408c4b',
styles: [{ name: 'ノーマル', id: 9 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '玄野武宏',
speaker_uuid: 'c30dc15a-0992-4f8d-8bb8-ad3b314e6a6f',
styles: [{ name: 'ノーマル', id: 11 }, { name: '喜び', id: 39 }, { name: 'ツンギレ', id: 40 }, {
name: '悲しみ', id: 41
}],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '白上虎太郎',
speaker_uuid: 'e5020595-5c5d-4e87-b849-270a518d0dcf',
styles: [{ name: 'ふつう', id: 12 }, { name: 'わーい', id: 32 }, { name: 'びくびく', id: 33 }, {
name: 'おこ', id: 34
}, { name: 'びえーん', id: 35 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '青山龍星',
speaker_uuid: '4f51116a-d9ee-4516-925d-21f183e2afad',
styles: [{ name: 'ノーマル', id: 13 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '冥鳴ひまり',
speaker_uuid: '8eaad775-3119-417e-8cf4-2a10bfd592c8',
styles: [{ name: 'ノーマル', id: 14 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'SELF_ONLY' },
name: '九州そら',
speaker_uuid: '481fb609-6446-4870-9f46-90c4dd623403',
styles: [{ name: 'ノーマル', id: 16 }, { name: 'あまあま', id: 15 }, { name: 'ツンツン', id: 18 }, {
name: 'セクシー', id: 17
}, { name: 'ささやき', id: 19 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'SELF_ONLY' },
name: 'もち子さん',
speaker_uuid: '9f3ee141-26ad-437e-97bd-d22298d02ad2',
styles: [{ name: 'ノーマル', id: 20 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '剣崎雌雄',
speaker_uuid: '1a17ca16-7ee5-4ea5-b191-2f02ace24d21',
styles: [{ name: 'ノーマル', id: 21 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: 'WhiteCUL',
speaker_uuid: '67d5d8da-acd7-4207-bb10-b5542d3a663b',
styles: [{ name: 'ノーマル', id: 23 }, { name: 'たのしい', id: 24 }, { name: 'かなしい', id: 25 }, {
name: 'びえーん', id: 26
}],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '後鬼',
speaker_uuid: '0f56c2f2-644c-49c9-8989-94e11f7129d0',
styles: [{ name: '人間ver.', id: 27 }, { name: 'ぬいぐるみver.', id: 28 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: 'No.7',
speaker_uuid: '044830d2-f23b-44d6-ac0d-b5d733caa900',
styles: [{ name: 'ノーマル', id: 29 }, { name: 'アナウンス', id: 30 }, { name: '読み聞かせ', id: 31 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: 'ちび式じい',
speaker_uuid: '468b8e94-9da4-4f7a-8715-a22a48844f9e',
styles: [{ name: 'ノーマル', id: 42 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '櫻歌ミコ',
speaker_uuid: '0693554c-338e-4790-8982-b9c6d476dc69',
styles: [{ name: 'ノーマル', id: 43 }, { name: '第二形態', id: 44 }, { name: 'ロリ', id: 45 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '小夜/SAYO',
speaker_uuid: 'a8cc6d22-aad0-4ab8-bf1e-2f843924164a',
styles: [{ name: 'ノーマル', id: 46 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '护士机器子T',
speaker_uuid: '882a636f-3bac-431a-966d-c5e6bba9f949',
styles: [{ name: 'ノーマル', id: 47 }, { name: '楽々', id: 48 }, { name: '恐怖', id: 49 }, {
name: '内緒話', id: 50
}],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '†聖騎士 紅桜†',
speaker_uuid: '471e39d2-fb11-4c8c-8d89-4b322d2498e0',
styles: [{ name: 'ノーマル', id: 51 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '雀松朱司',
speaker_uuid: '0acebdee-a4a5-4e12-a695-e19609728e30',
styles: [{ name: 'ノーマル', id: 52 }],
version: '0.14.2'
}, {
supported_features: { permitted_synthesis_morphing: 'ALL' },
name: '麒ヶ島宗麟',
speaker_uuid: '7d1e7ba7-f957-40e5-a3fc-da49f769ab65',
styles: [{ name: 'ノーマル', id: 53 }],
version: '0.14.2'
}]
export default { generateAudio, supportConfigurations }