From b212fcf87e42e41778890e00b5ad2022d932e473 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Wed, 15 Mar 2023 23:33:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AF=AD=E9=9F=B3=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=B8=AD=E6=97=A5=E7=BB=93=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/chat.js | 2 +- utils/common.js | 89 +++++++++++++++++++++++++++++++++++++++++++++++-- utils/config.js | 2 +- utils/tts.js | 4 ++- 4 files changed, 91 insertions(+), 6 deletions(-) diff --git a/apps/chat.js b/apps/chat.js index 63dba72..da4fdd6 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -619,7 +619,7 @@ export class chatgpt extends plugin { } if (useTTS) { if (Config.ttsSpace && response.length <= 299) { - let wav = await generateAudio(response, speaker, '中文') + let wav = await generateAudio(response, speaker, '中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)') await e.reply(segment.record(wav)) if (Config.alsoSendText) { await this.reply(`${response}`, e.isGroup) diff --git a/utils/common.js b/utils/common.js index 3b6f676..bd7ac9b 100644 --- a/utils/common.js +++ b/utils/common.js @@ -375,10 +375,93 @@ export async function isCN () { } } -export function limitString(str, maxLength) { +export function limitString (str, maxLength) { if (str.length <= maxLength) { - return str; + return str } else { - return str.slice(0, maxLength) + '...'; + return str.slice(0, maxLength) + '...' } } + +/** + * ``` + * var text = '你好,こんにちは,Hello!'; + * var wrappedText = wrapTextByLanguage(text); + * console.log(wrappedText); + * ``` + * @param text + * @returns {string} + */ +export function wrapTextByLanguage (text) { + // 根据标点符号分割句子 + const symbols = /([。!?,])/ + let sentences = text.split(symbols) + sentences = sentences.reduce((acc, cur, index) => { + if (symbols.test(cur)) { + // 如果当前字符串是标点符号,则将其添加到前一个字符串的末尾 + acc[acc.length - 1] += cur + } else { + // 否则,将当前字符串添加到结果数组中 + acc.push(cur) + } + + return acc + }, []) + let wrappedSentences = [] + for (let i = 0; i < sentences.length; i++) { + let sentence = sentences[i] + + // 如果是标点符号,则跳过 + if (sentence === '。' || sentence === '!' || sentence === '?' || sentence === ',') { + continue + } + const pattern = /[a-zA-Z]/g + sentence = sentence.replace(pattern, '') + // 判断这一句话是中文还是日语 + let isChinese = true + let isJapanese = false + for (let j = 0; j < sentence.length; j++) { + let char = sentence.charAt(j) + if (char.match(/[\u3040-\u309F\u30A0-\u30FF]/)) { + isJapanese = true + isChinese = false + break + } + } + + // 包裹句子 + if (isChinese) { + sentence = `[ZH]${sentence}[ZH]` + } else if (isJapanese) { + sentence = `[JA]${sentence}[JA]` + } + + wrappedSentences.push(sentence) + } + + const mergedSentences = wrappedSentences.reduce((acc, cur) => { + if (cur === '') { + // 如果当前字符串为空或者是标点符号,则直接将其添加到结果数组中 + acc.push(cur) + } else { + // 否则,判断前一个字符串和当前字符串是否为同种语言 + const prev = acc[acc.length - 1] + let curPrefix = `${cur.slice(0, 4)}` + if (prev && prev.startsWith(curPrefix)) { + // 如果前一个字符串和当前字符串为同种语言,则将它们合并 + let a = (acc[acc.length - 1] + cur) + a = lodash.replace(a, curPrefix + curPrefix, '') + acc[acc.length - 1] = a + } else { + // 否则,将当前字符串添加到结果数组中 + acc.push(cur) + } + } + + return acc + }, []) + + return mergedSentences.join('') +} + +// console.log(wrapTextByLanguage('你好,这里是哈哈,こんにちは,Hello!')) diff --git a/utils/config.js b/utils/config.js index b585371..cf822dd 100644 --- a/utils/config.js +++ b/utils/config.js @@ -61,7 +61,7 @@ const defaultConfig = { initiativeChatGroups: [], enableDraw: true, helloPrompt: '写一段话让大家来找我聊天。类似于“有人找我聊天吗?"这种风格,轻松随意一点控制在20个字以内', - version: 'v2.1.7' + version: 'v2.1.8' } const _path = process.cwd() let config = {} diff --git a/utils/tts.js b/utils/tts.js index a9c4aa5..9882733 100644 --- a/utils/tts.js +++ b/utils/tts.js @@ -1,6 +1,7 @@ import { Config } from './config.js' import fetch from 'node-fetch' import _ from 'lodash' +import {wrapTextByLanguage} from "./common.js"; let proxy if (Config.proxy) { try { @@ -35,11 +36,12 @@ function randomNum (minNum, maxNum) { return 0 } } -export async function generateAudio (text, speaker = '随机', language = '中文', noiseScale = Config.noiseScale, noiseScaleW = Config.noiseScaleW, lengthScale = Config.lengthScale) { +export async function generateAudio (text, speaker = '随机', language = '中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)', noiseScale = Config.noiseScale, noiseScaleW = Config.noiseScaleW, lengthScale = Config.lengthScale) { if (!speaker || speaker === '随机') { logger.info('随机角色!这次哪个角色这么幸运会被选到呢……') speaker = speakers[randomNum(0, speakers.length)] } + text = wrapTextByLanguage(text) logger.info(`正在使用${speaker},基于文本:'${text}'生成语音`) let body = { data: [