(node)暑假到了,给儿子做一个文字转语音的听写。

718 阅读5分钟

这里总共有两种方案来实现

第一种方案 主要利用我们电脑自带的文字转语音功能实现的不花钱

利用node 封装好的say模块来实现(这个是有问题的,就是她只能读引文无法读出来汉字,最后经过自己的处理也是实现好了)

实现的逻辑

1 将say模块源码改成可以识别中文的。
2 获取当前的时间,将最后得到的音频文件放到同一时间里面。
3 获取到所有要听写的词语,后面实现一个随机抽取20个词语,进行听写。
4 遍历这20个词语。
5 将每个词语词语(也就是听写的答案)答案放到同一时间文件夹里面。
6 将每次词语进行文件转语音,答案放到同一时间文件夹里面。

提示: 我们在开发的时候可以按照上面的不走写一下你要实现的业务逻辑,这样你开发起来能做到事半功倍

下面看代码,后面我们会有解释。
时间date.js 文件很简单。

getTime = ()=>{
    var now = new Date();
    var year = now.getFullYear(); //获取年份
    var month = now.getMonth() + 1; //获取当前月份(0-11,0代表1月)
    var day = now.getDate(); //获取当前日
    var hour = now.getHours(); //获取当前小时数
    var minute = now.getMinutes(); //获取当前分钟数
    var second = now.getSeconds(); //获取当前秒数
    var timeStr = year + "年" + (month<10?"0"+month:month) + "月" + (day<10?"0"+day:day)+ "日"+ (hour<10?"0"+hour:hour) + "时" + (minute<10?"0"+minute:minute) + "分" ;
    console.log(timeStr);
    return timeStr
}

module.exports=getTime

文字(text.js)文件,二年级上学期的。我们里可以利用微信的提取文件直接获取到

let str=''
+'诗歌 村庄 儿童 碧绿 化妆 嫩绿 丝绸 剪刀 冲动 寻找 姑娘 吞吞吐吐 杨柳 荡秋千 桃花 杏仁 鲜红 邮递员 原来 叔叔 邮局 堆放 礼貌 邓小平 植树'
+' 格外 引人注目 注意 满足 休息 雷锋 昨天 冒号 留弯 背面 洒水 温暖 能力 桌子 味道 买卖 文具 甘蔗 甜菜 劳动 匹配 姐妹 波纹 好像'
+' 景色 恋恋不舍  要求 识字 州长 中华 民族 谊 整齐 奋斗 街道 艾草 尊敬 热闹 烤鸭 鸡蛋 炒饭 贝壳 甲骨 钱币'
+' 美食 红烧 茄子 烤鸭 羊肉 蛋炒饭 课文 彩色 脚尖 森林 雪松 歌声 苹果 精灵 季节 好像 一直 说话 童话 对岸 发现 弟弟 游戏 发明'
+' 字母 周围 补充 飞机 地道 火药 合力 公主 胜利 忘记 屁股 苍耳 留神 干净 从来 幸运 使劲 夜晚 听见 草地 亡羊 补牢  劝告 禾苗 筋疲力尽 '
+' 明白 图画 老师 讲桌 座位 教室 哈哈大笑 五角星 然后 画纸 神情 角度 愿意  麦子为难 四周 伯伯 立刻 突然 吃惊 认真 脚步 难为情 雷雨 乌云'
+' 闪电 雷声 房子 窗户 清新 迎面 野外 大自然 天然 指南针 帮助 方向 向导 指点 北极星 永远 黑夜 帮忙 特别 积雪 太空 生活 别处 主要'
+' 方便 活动 杯子 喝水 使用 洗澡 容易 浴桶 耳朵 扇子 遇到 兔子 毛病 后来 不安 头痛 最后 人家 决定 商店 终于 围巾 星期 工夫'
+' 青蛙 草籽 野鸭 泉水 竹子 应该 花丛 尽情 道路 毛虫 叶子 目光 周游 纺织 编织 怎样 声音 花纹 消失 祖先 原始 意思 浓绿 一望无边 蓝天 野果'
+' 野免 赛跑 回忆 世界 学习 成功 月亮 主意 反反复复 变化 方式 简单 自由 生长 相当 结局 开头 光明 觉得 值日 人类 艰难 决心 苦海 炎热 害怕'
+' 从此 花草 树木 生机 春天 寻找 姑娘 野花 柳枝 桃花 杏花 鲜花 邮递员 先生 原来 大叔 邮局 太太 做客 惊奇 快活 美好 礼物 钱财 有关 比如'
+' 爷爷 植树 碧空如洗 万里无云 公园 格外 引人注目 汗珠 休息 树苗 小心 笔直 温暖 爱心 叔叔 足迹 昨天 迷路 转眼 团圆 热闹'
+' 也许 就是 桌子 平时 难道 味道 加工 种子 甜菜 劳动 经过 农具 工具 出色 妹妹 河水 碧绿 波纹 河岸 柳叶 景色 恋恋不舍 柳树 枝条 识字'
+' 中华 山川 黄河 长江 长城 神州 台湾岛 海峡 民族 奋发 节日 花灯 清明节 先人 龙舟 中秋 春节 动物 贝壳 甲骨文 张开 样子 可以 钱币'

module.exports = str

say.js 我们看下我们自己做的修改,我是直接将源码复制出来做了一个修改

image.png 引入node自带的,可以识别汉字的模块iconv-lite,也不需要我们安装,直接使用就可以了 iconv-lite 字符编码转换,感兴趣的可以看这里www.npmjs.com/package/ico…

image.png image.png 将文件转化成中文gbk编码的,这样读出来的就是中文的。

上面就是我们自己修改say模块的整个过程

实现文件转语音的主文件

var say = require("./say/index.js");
const fs = require("fs"); //导入模块
// 自己封装的时间模块,很简单
const getTime = require("./date.js"); 
// 这里是准备听写的文字
let str = require('./text.js')  
// 获取时间,将最后得到的音频文件放到同一时间里面
let time = getTime() 
// 判断文件夹是否存在,不存在则创建这个存放音频文件的文件夹
if (!fs.existsSync('./wav/'+time)) fs.mkdirSync('./wav/'+time); 
// 判断文件夹是否存在,不存在则创建这个存放音频文件的文件夹
if (!fs.existsSync('./text')) fs.mkdirSync('./text');
let exportfn = (text, random) => {
  console.log(text, random);
  
![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4b3d349ea8684a6e901a2f787e978afa~tplv-k3u1fbpfcp-watermark.image?)
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ecd2c019a2654184a09c38e9b4fd8be9~tplv-k3u1fbpfcp-watermark.image?)
  // 文字转语音
  say.export(
    text,
    "Microsoft Huihui Desktop",  // 电脑的声音,可以通过下面的say.getInstalledVoices方法获取到
    0.5,
    './wav/'+time+'/'+random + ".wav", 
    function (err) {
      if (err) {
        return console.error(err);
      }
      console.log(`Text has been saved to ${random}".wav"`);
    }
  );
};
let arr = str.split(" ");
let random = Math.floor(Math.random() * arr.length).toFixed(0);
let arrRandom = [];
// 循环遍历20条数据
while (arrRandom.length < 20) {
  random = Math.floor(Math.random() * arr.length).toFixed(0);
  if (!arrRandom.includes(random)) {
    arrRandom.push(random);

    fs.writeFile(
        './text/'+time+".js",
      arr[random] + arrRandom.length+'\n',
      {
        flag:'as',
        encoding :'utf8'
      },
      function (err) {}
    );
    //arr[arrRandom[i]] 我写了3边表示会读三次
    exportfn(arr[random] + " " + arr[random]+" " + arr[random], arrRandom.length);        
  }
}
console.log("arrRandom", arrRandom);

// 获取电脑安装的声音
function callback(err, data) {
  console.log("err", err);
  console.log("data", data); // 这里就是我们电脑自带的声音 [ 'Microsoft Huihui Desktop', 'Microsoft Zira Desktop' ]
}
say.getInstalledVoices(callback);

最后实现出来的我们的语音就是这样的

image.png

第二种方案 利用百度提供好的API来实现(baidu-aip-sdk).

因为调用了百度的API只能免费使用5000万次(也还挺多的),再多了就收费了

首先我们去百度智能云去注册cloud.baidu.com/

image.png 注册以后我们就可以获取到 APP_ID API Key和 Secret Key,这三个值后面调用百度SDK会用到,如下图所示

image.png 这里显示给我免费的次数和已经用过的次数,如下图所示 image.png

上面进行完之后就是下面就是我们的代码了

const AipSpeechClient = require('baidu-aip-sdk').speech;
// const fs = require('fs');
const APP_ID = '35468388';
const API_KEY = 'M78Z5iqYuP7fmPNTzsMVmki4';
const SECRET_KEY = 'TN8HbRT7hspp4VyKRkHBaoGcvxCHvrpS';

// var say = require("./say/index.js");
const fs = require("fs"); //导入模块
const getTime = require("./date.js"); // 时间模块和上面一样
let str = require('./text.js') // 文字模块也和上面一样
let time = getTime()
if (!fs.existsSync('./wav/'+time)) fs.mkdirSync('./wav/'+time);
if (!fs.existsSync('./text')) fs.mkdirSync('./text');
let i=0;
let count= 20
const client = new AipSpeechClient(APP_ID, API_KEY, SECRET_KEY);
let exportfn = async (arrRandom) => {
  console.log('arrRandom',arrRandom,arr[arrRandom[i]],i);
  // 这里就是调用百度的API来实现的,arr[arrRandom[i]] 我写了3边表示会读三次
  
  await client.text2audio(' '+arr[arrRandom[i]]+' '+arr[arrRandom[i]]+' '+arr[arrRandom[i]], { spd: 3, per:'1',aue:'6'  }).then((result) => {
    if (result.data) {
      fs.writeFileSync('./wav/'+time+'/'+i + ".wav", result.data,)
      i++
      if(count>i){
        exportfn(arrRandom)
      }
      console.log('语音保存成功!');
    } else {
      console.log('语音合成失败:' + JSON.stringify(result));
    }
  }).catch((err) => {
    console.error('语音合成出错:', err);
  });
};
let arr = str.split(" ");
console.log("arr", arr.length);

let random = Math.floor(Math.random() * arr.length).toFixed(0);
let arrRandom = [];
while (arrRandom.length < count) {
  random = Math.floor(Math.random() * arr.length).toFixed(0);
  if (!arrRandom.includes(random)) {
    arrRandom.push(random);
    fs.writeFile(
        './text/'+time+".txt",
      arr[random] + arrRandom.length+'\n',
      {
        flag:'as',
        encoding :'utf8'
      },
      function (err) {}
    );
    if(arrRandom.length ===count ){
      exportfn(arrRandom);
    }
   
  }
}

关于 client.text2audio第二个是它的参数,具体看下图

image.png 在具体的的大家可以观看官方文档console.bce.baidu.com/tools/#/api…
最后也看我们的成果

语音的

image.png

文字的

image.png

大家喜欢的就给点个赞吧,

最后欢迎大家关注我的公众号: 前端就业课,一个喜欢分享的博主。