通过AI+图灵机器+Flask实现的只能问答
后端代码AI代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from aip import AipSpeech 2 from aip import AipNlp 3 from uuid import uuid4 4 import tulin 5 import os 6 """ 你的 APPID AK SK """ 7 APP_ID = '14940739' 8 API_KEY = 'xCnr5K8ESsmOVaA5bl5ot5QY' 9 SECRET_KEY = '4wH7W92hPUp8V7ogY4BZzV2pcZ3nC8LH ' 10 11 client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) 12 client_nlp = AipNlp(APP_ID, API_KEY, SECRET_KEY) 13 14 def get_file_content(filename): 15 os.system(f"ffmpeg -y -i {filename} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filename}.pcm") 16 with open(f"{filename}.pcm", 'rb') as fp: 17 res = client.asr(fp.read(), 'pcm', 16000, { 18 'dev_pid': 1536, 19 }) 20 print("res",res) 21 return res.get("result")[0] 22 23 def yycd(text): 24 filename = uuid4() 25 result = client.synthesis(text, 'zh', 1, { 26 "spd": 4, 27 'vol': 5, 28 "pit": 8, 29 "per": 4 30 }) 31 # 识别正确返回语音二进制 错误则返回dict 参照下面错误码 32 if not isinstance(result, dict): 33 with open(f'{filename}.mp3', 'wb') as f: 34 f.write(result) 35 print("yuyin2",filename) 36 return f'{filename}.mp3' 37 38 39 def my_nlp(text): 40 41 if client_nlp.simnet("你叫什么名字", text).get("score") >= 0.7: 42 return yycd("我的名字叫大王八") 43 44 if client_nlp.simnet("你今年多大了", text).get("score") >= 0.7: 45 return yycd("我今年9岁了") 46 47 else: 48 return yycd(tulin.tulin(text, "DragonFire"))
后端Flask代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from geventwebsocket.handler import WebSocketHandler 2 from gevent.pywsgi import WSGIServer 3 from geventwebsocket.websocket import WebSocket 4 5 from uuid import uuid4 6 7 from flask import Flask,render_template,request,send_file 8 9 import yuyin2 10 11 app = Flask(__name__) 12 13 @app.route("/") 14 def index(): 15 return render_template("index.html") 16 17 @app.route("/ws") 18 def ws(): 19 user_socket = request.environ.get("wsgi.websocket") # type: WebSocket 20 while 1: 21 audio_file = user_socket.receive() 22 file_name = uuid4() 23 with open(f"{file_name}.wav","wb") as f: 24 f.write(audio_file) 25 text = yuyin2.get_file_content(f"{file_name}.wav") 26 filename = yuyin2.my_nlp(text) 27 print(filename) 28 user_socket.send(filename) 29 30 @app.route("/get_audio/<filename>") 31 def get_audio(filename): 32 return send_file(filename) 33 34 35 36 if __name__ == '__main__': 37 # app.run() 38 http_serv = WSGIServer(("0.0.0.0",5000),app,handler_class=WebSocketHandler) 39 http_serv.serve_forever()
图灵机器人接口代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import requests 2 3 tuling_url = "http://openapi.tuling123.com/openapi/api/v2" 4 atr = { 5 "reqType": 0, 6 "perception": { 7 "inputText": { 8 "text": "讲个故事" 9 }, 10 }, 11 "userInfo": { 12 "apiKey": "3fbeb66884dc4e789a764c649c2fe19d", 13 "userId": "123" 14 } 15 } 16 def tulin(Q,uid): 17 atr["perception"]["inputText"]["text"]=Q 18 atr["userInfo"]["userId"]=uid 19 res = requests.post(tuling_url, json=atr) 20 res_json=res.json() 21 print(res_json.get("results")[0]["values"]["text"]) 22 return res_json.get("results")[0]["values"]["text"]
前端代码:
界面需要浏览器使用录音机功能,需要导入Rcorder.js文件
Rcorder.js文件代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Recorder = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 2 "use strict"; 3 4 module.exports = require("./recorder").Recorder; 5 6 },{"./recorder":2}],2:[function(require,module,exports){ 7 'use strict'; 8 9 var _createClass = (function () { 10 function defineProperties(target, props) { 11 for (var i = 0; i < props.length; i++) { 12 var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor); 13 } 14 }return function (Constructor, protoProps, staticProps) { 15 if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor; 16 }; 17 })(); 18 19 Object.defineProperty(exports, "__esModule", { 20 value: true 21 }); 22 exports.Recorder = undefined; 23 24 var _inlineWorker = require('inline-worker'); 25 26 var _inlineWorker2 = _interopRequireDefault(_inlineWorker); 27 28 function _interopRequireDefault(obj) { 29 return obj && obj.__esModule ? obj : { default: obj }; 30 } 31 32 function _classCallCheck(instance, Constructor) { 33 if (!(instance instanceof Constructor)) { 34 throw new TypeError("Cannot call a class as a function"); 35 } 36 } 37 38 var Recorder = exports.Recorder = (function () { 39 function Recorder(source, cfg) { 40 var _this = this; 41 42 _classCallCheck(this, Recorder); 43 44 this.config = { 45 bufferLen: 4096, 46 numChannels: 2, 47 mimeType: 'audio_pcm/wav' 48 }; 49 this.recording = false; 50 this.callbacks = { 51 getBuffer: [], 52 exportWAV: [] 53 }; 54 55 Object.assign(this.config, cfg); 56 this.context = source.context; 57 this.node = (this.context.createScriptProcessor || this.context.createJavaScriptNode).call(this.context, this.config.bufferLen, this.config.numChannels, this.config.numChannels); 58 59 this.node.onaudioprocess = function (e) { 60 if (!_this.recording) return; 61 62 var buffer = []; 63 for (var channel = 0; channel < _this.config.numChannels; channel++) { 64 buffer.push(e.inputBuffer.getChannelData(channel)); 65 } 66 _this.worker.postMessage({ 67 command: 'record', 68 buffer: buffer 69 }); 70 }; 71 72 source.connect(this.node); 73 this.node.connect(this.context.destination); //this should not be necessary 74 75 var self = {}; 76 this.worker = new _inlineWorker2.default(function () { 77 var recLength = 0, 78 recBuffers = [], 79 sampleRate = undefined, 80 numChannels = undefined; 81 82 self.onmessage = function (e) { 83 switch (e.data.command) { 84 case 'init': 85 init(e.data.config); 86 break; 87 case 'record': 88 record(e.data.buffer); 89 break; 90 case 'exportWAV': 91 exportWAV(e.data.type); 92 break; 93 case 'getBuffer': 94 getBuffer(); 95 break; 96 case 'clear': 97 clear(); 98 break; 99 } 100 }; 101 102 function init(config) { 103 sampleRate = config.sampleRate; 104 numChannels = config.numChannels; 105 initBuffers(); 106 } 107 108 function record(inputBuffer) { 109 for (var channel = 0; channel < numChannels; channel++) { 110 recBuffers[channel].push(inputBuffer[channel]); 111 } 112 recLength += inputBuffer[0].length; 113 } 114 115 function exportWAV(type) { 116 var buffers = []; 117 for (var channel = 0; channel < numChannels; channel++) { 118 buffers.push(mergeBuffers(recBuffers[channel], recLength)); 119 } 120 var interleaved = undefined; 121 if (numChannels === 2) { 122 interleaved = interleave(buffers[0], buffers[1]); 123 } else { 124 interleaved = buffers[0]; 125 } 126 var dataview = encodeWAV(interleaved); 127 var audioBlob = new Blob([dataview], { type: type }); 128 129 self.postMessage({ command: 'exportWAV', data: audioBlob }); 130 } 131 132 function getBuffer() { 133 var buffers = []; 134 for (var channel = 0; channel < numChannels; channel++) { 135 buffers.push(mergeBuffers(recBuffers[channel], recLength)); 136 } 137 self.postMessage({ command: 'getBuffer', data: buffers }); 138 } 139 140 function clear() { 141 recLength = 0; 142 recBuffers = []; 143 initBuffers(); 144 } 145 146 function initBuffers() { 147 for (var channel = 0; channel < numChannels; channel++) { 148 recBuffers[channel] = []; 149 } 150 } 151 152 function mergeBuffers(recBuffers, recLength) { 153 var result = new Float32Array(recLength); 154 var offset = 0; 155 for (var i = 0; i < recBuffers.length; i++) { 156 result.set(recBuffers[i], offset); 157 offset += recBuffers[i].length; 158 } 159 return result; 160 } 161 162 function interleave(inputL, inputR) { 163 var length = inputL.length + inputR.length; 164 var result = new Float32Array(length); 165 166 var index = 0, 167 inputIndex = 0; 168 169 while (index < length) { 170 result[index++] = inputL[inputIndex]; 171 result[index++] = inputR[inputIndex]; 172 inputIndex++; 173 } 174 return result; 175 } 176 177 function floatTo16BitPCM(output, offset, input) { 178 for (var i = 0; i < input.length; i++, offset += 2) { 179 var s = Math.max(-1, Math.min(1, input[i])); 180 output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); 181 } 182 } 183 184 function writeString(view, offset, string) { 185 for (var i = 0; i < string.length; i++) { 186 view.setUint8(offset + i, string.charCodeAt(i)); 187 } 188 } 189 190 function encodeWAV(samples) { 191 var buffer = new ArrayBuffer(44 + samples.length * 2); 192 var view = new DataView(buffer); 193 194 /* RIFF identifier */ 195 writeString(view, 0, 'RIFF'); 196 /* RIFF chunk length */ 197 view.setUint32(4, 36 + samples.length * 2, true); 198 /* RIFF type */ 199 writeString(view, 8, 'WAVE'); 200 /* format chunk identifier */ 201 writeString(view, 12, 'fmt '); 202 /* format chunk length */ 203 view.setUint32(16, 16, true); 204 /* sample format (raw) */ 205 view.setUint16(20, 1, true); 206 /* channel count */ 207 view.setUint16(22, numChannels, true); 208 /* sample rate */ 209 view.setUint32(24, sampleRate, true); 210 /* byte rate (sample rate * block align) */ 211 view.setUint32(28, sampleRate * 4, true); 212 /* block align (channel count * bytes per sample) */ 213 view.setUint16(32, numChannels * 2, true); 214 /* bits per sample */ 215 view.setUint16(34, 16, true); 216 /* data chunk identifier */ 217 writeString(view, 36, 'data'); 218 /* data chunk length */ 219 view.setUint32(40, samples.length * 2, true); 220 221 floatTo16BitPCM(view, 44, samples); 222 223 return view; 224 } 225 }, self); 226 227 this.worker.postMessage({ 228 command: 'init', 229 config: { 230 sampleRate: this.context.sampleRate, 231 numChannels: this.config.numChannels 232 } 233 }); 234 235 this.worker.onmessage = function (e) { 236 var cb = _this.callbacks[e.data.command].pop(); 237 if (typeof cb == 'function') { 238 cb(e.data.data); 239 } 240 }; 241 } 242 243 _createClass(Recorder, [{ 244 key: 'record', 245 value: function record() { 246 this.recording = true; 247 } 248 }, { 249 key: 'stop', 250 value: function stop() { 251 this.recording = false; 252 } 253 }, { 254 key: 'clear', 255 value: function clear() { 256 this.worker.postMessage({ command: 'clear' }); 257 } 258 }, { 259 key: 'getBuffer', 260 value: function getBuffer(cb) { 261 cb = cb || this.config.callback; 262 if (!cb) throw new Error('Callback not set'); 263 264 this.callbacks.getBuffer.push(cb); 265 266 this.worker.postMessage({ command: 'getBuffer' }); 267 } 268 }, { 269 key: 'exportWAV', 270 value: function exportWAV(cb, mimeType) { 271 mimeType = mimeType || this.config.mimeType; 272 cb = cb || this.config.callback; 273 if (!cb) throw new Error('Callback not set'); 274 275 this.callbacks.exportWAV.push(cb); 276 277 this.worker.postMessage({ 278 command: 'exportWAV', 279 type: mimeType 280 }); 281 } 282 }], [{ 283 key: 'forceDownload', 284 value: function forceDownload(blob, filename) { 285 var url = (window.URL || window.webkitURL).createObjectURL(blob); 286 var link = window.document.createElement('a'); 287 link.href = url; 288 link.download = filename || 'output.wav'; 289 var click = document.createEvent("Event"); 290 click.initEvent("click", true, true); 291 link.dispatchEvent(click); 292 } 293 }]); 294 295 return Recorder; 296 })(); 297 298 exports.default = Recorder; 299 300 },{"inline-worker":3}],3:[function(require,module,exports){ 301 "use strict"; 302 303 module.exports = require("./inline-worker"); 304 },{"./inline-worker":4}],4:[function(require,module,exports){ 305 (function (global){ 306 "use strict"; 307 308 var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 309 310 var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 311 312 var WORKER_ENABLED = !!(global === global.window && global.URL && global.Blob && global.Worker); 313 314 var InlineWorker = (function () { 315 function InlineWorker(func, self) { 316 var _this = this; 317 318 _classCallCheck(this, InlineWorker); 319 320 if (WORKER_ENABLED) { 321 var functionBody = func.toString().trim().match(/^function\s*\w*\s*\([\w\s,]*\)\s*{([\w\W]*?)}$/)[1]; 322 var url = global.URL.createObjectURL(new global.Blob([functionBody], { type: "text/javascript" })); 323 324 return new global.Worker(url); 325 } 326 327 this.self = self; 328 this.self.postMessage = function (data) { 329 setTimeout(function () { 330 _this.onmessage({ data: data }); 331 }, 0); 332 }; 333 334 setTimeout(function () { 335 func.call(self); 336 }, 0); 337 } 338 339 _createClass(InlineWorker, { 340 postMessage: { 341 value: function postMessage(data) { 342 var _this = this; 343 344 setTimeout(function () { 345 _this.self.onmessage({ data: data }); 346 }, 0); 347 } 348 } 349 }); 350 351 return InlineWorker; 352 })(); 353 354 module.exports = InlineWorker; 355 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 356 },{}]},{},[1])(1) 357 });
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="x-ua-compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 <title>Title</title> 8 </head> 9 <body> 10 <audio controls autoplay id="player" src="/static/audio.mp3"></audio> 11 <button onclick="start_reco()">开始录音</button> 12 <button onclick="stop_reco()">发送消息</button> 13 14 </body> 15 <script src="/static/Recorder.js"></script> 16 <script type="text/javascript"> 17 var reco = null; 18 var ws = new WebSocket("ws://127.0.0.1:5000/ws"); 19 ws.onmessage=function (data) { 20 console.log(data.data); 21 document.getElementById("player").src = "http://127.0.0.1:5000/get_audio/" + data.data; 22 }; 23 var audio_context = new AudioContext(); 24 navigator.getUserMedia = (navigator.getUserMedia || 25 navigator.webkitGetUserMedia || 26 navigator.mozGetUserMedia || 27 navigator.msGetUserMedia); 28 29 navigator.getUserMedia({audio: true}, create_stream, function (err) { 30 console.log(err) 31 }); 32 33 function create_stream(user_media) { 34 var stream_input = audio_context.createMediaStreamSource(user_media); 35 reco = new Recorder(stream_input); 36 } 37 38 function start_reco() { 39 reco.record(); 40 } 41 42 function stop_reco() { 43 reco.stop(); 44 get_audio(); 45 reco.clear(); 46 } 47 48 function get_audio() { 49 reco.exportWAV(function (wav_file) { 50 //wav_file 录音文件 Blob 51 console.log(wav_file); 52 ws.send(wav_file) 53 }) 54 } 55 56 </script> 57 </html>