官方文档
第一步
- 进入控制台
- 人工智能
- 语音识别
- 先创建应用:获得appid、apikey、secritkey
第二步
- 创建一个文件夹test
- cd test 进入文件夹
- 创建index.js文件
- 安装依赖:npm i baidu-aip-sdk
环境配置说明
-
百度语音需要的格式是pcm,所以需要转码
-
转码用的是ffmpeg:
1、由于node版本更新后,npm上的ffmpeg 包使用不上,则采用命令行使用官方下载的 build 包
2、官方地址:点这里:http://ffmpeg.org/ffmpeg.html
3、百度语音使用ffmpeg的使用说明:点这里:https://ai.baidu.com/docs#/ASR-Tool-convert/ec5eb053 -
这里比较烦的是ffmpeg的配置,由于linux和Windows不同,所以配置环境变量的方式也不一样
-
配置windows:设置命令行执行指令
set path=D:\dev\ffmpeg-20180903-23fe072-win64-static\bin;%path%
ffmpeg -y -i <音频路径> -acodec pcm_s16le -f s16le -ac 1 -ar 16000 <转码后存放音频路径>
- 配置linux:设置命令行执行指令
export PATH=$PATH:/data/ffmpeg/ffmpeg-git-20180831-64bit-static
ffmpeg -y -i <音频路径> -acodec pcm_s16le -f s16le -ac 1 -ar 16000 <转码后存放音频路径>
注释:由于linux涉及到用户权限问题,每一个node子进程的用户不一样,会导致找不到ffmpeg模块,所以需要将ffmpeg设置为永久性全局环境变量
- 如何在代码中执行指令:nodejs给我们提供了,子进程的方法,官方文档有提供示例
const exec = require('child_process').exec; // node自带的子进程方法
// 代码中自执行,执行时会出现编码问题,设置参数,编码格式gbk或者utf-8
// 这句是设置ffmpeg路径,注意到bin目录即可
exec('set path=D:\\dev\\ffmpeg-20180903-23fe072-win64-static\\bin;%path%', { 'encoding': 'GBK' });
- 代码示例如下:百度ai(人工智能)接入
const BD_API_SDK = require('baidu-aip-sdk'); // 引入百度api sdk
const AipSpeechClient = BD_API_SDK.speech; // 获取客户端
const incfg = {
appid: appid, apikey: apikey, secretkey: secretkey,
inEncoding: 'GBK', // 设置dos命令行的编码格式
}; // 指定参数
const { appid, apikey, secretkey, inEncoding } = incfg;
// 实例化客户端,建议只保存一个对象调用服务接口
const client = new AipSpeechClient(appid, apikey, secretkey);
const fs = require('fs'); // node文件系统
const os = require('os'); // 系统参数
const util = require('util');
const child_process = require('child_process'); // node子进程
const log = require('../util/log')('logic/baidu'); // 日志
export default class Baidu {
static async parse(data) {
let RS = null;
try {
if (!data) { return RS; }
const indos = [];
const entry = `${data.filePath}${data.fileName}`;
const output = `${data.filePath}${new Date().getTime()}.pcm`;
if (os && os.EOL === '\r\n') { // Windows系统
indos.push('set path=D:\\dev\\ffmpeg-20180903-23fe072-win64-static\\bin;%path%');
indos.push(`ffmpeg -y -i ${entry} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 ${output}`);
} else { // Linux系统
indos.push('export PATH=$PATH:/data/ffmpeg/ffmpeg-git-20180831-64bit-static');
indos.push(`ffmpeg -y -i ${entry} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 ${output}`);
}
log.debug(`parse entry:${entry}; output:${output}; indos:${util.inspect(indos)}`);
await toFFmpeg(indos[0]);
await toFFmpeg(indos[1]);
log.debug(`toFFmpeg 转换完成`);
const voice = fs.readFileSync(output);
log.debug(`读取文件 voice:${typeof voice}`);
if (voice) {
const voiceBuffer = new Buffer(voice); // 转换Buffer数据流
// 调用百度语音api
RS = await new Promise((resolve, reject) => {
client.recognize(voiceBuffer, 'pcm', 16000).then((rs) => {
log.debug(`recognize rs:${util.inspect(rs)}`);
resolve(rs);
}, function (err) {
log.debug(`recognize err:${util.inspect(err)}`);
reject(err);
});
});
}
return RS;
} catch (e) {
log.error('baidu parse error:', e.message);
return RS;
}
}
/**
* 命令行调用ffmpeg指令,每次只能运行一条指令
* 注:node在Linux下运行多个子程序,每个子程序对于一个用户(类似于作用域),导致设置的临时环境变量,运行命令时找不到模块或者程序
* @param {String} instructs 指令
* @param {String} encoding 编码格式,缺省gbk
* @returns {Object}
*/
static toFFmpeg(...args /* instructs, encoding */) {
console.log(`toFFmpeg arguments:${util.inspect(arguments)}; args[0]:${args[0]}; args[1]:${args[1]}`);
if (!args || args.length <= 0) return '';
console.log(`toFFmpeg start`);
return new Promise((resolve, reject) => {
console.log(`toFFmpeg start Promise`);
child_process.exec(args[0], { encoding: args[1] || 'GBK' }, (error, stdout, stderr) => {
console.log(`toFFmpeg error:${error}; stdout:${stdout && stdout.toString()}; stderr:${stderr};`);
if (error) {
reject(false);
} else {
resolve({ error, stdout, stderr });
}
});
});
}
}