def exec(command_id): try: conn = "" conn = connector.connect(host=mysql_con.HOST, user=mysql_con.USERNAME, password=mysql_con.PASSWORD, port=mysql_con.PORT, database=mysql_con.DATABASE, charset=mysql_con.CHARSET) cursor = conn.cursor() cursor.execute("UPDATE command SET `status`=%s WHERE id=%s", ('1', command_id)) # 提交记录 conn.commit() log.normal("更新命令状态 命令编号:%d" % command_id) except Exception as e: log.exp("更新命令状态 命令编号:%d" % command_id, e) finally: if "" != conn: conn.close()
def get_text(cls, file_name): log.normal("音频转文字: " + file_name) # 请求地址 request_url = "http://vop.baidu.com/server_api" # 参数 p_rate = config.RATE # 采样率,支持 8000 或者 16000 p_cuid = "FC-AA-14-D0-1D-67" # 用户唯一标识,用来区分用户,填写机器 MAC 地址,长度为60以内 p_token = cls.get_access_token() # 开放平台获取到的开发者 access_token fp = wave.open(file_name, 'rb') nf = fp.getnframes() p_len = nf * 2 p_speech = fp.readframes(nf) srv_url = request_url + '?cuid=' + p_cuid + '&token=' + p_token http_header = [ 'Content-Type: audio/pcm; rate=%d' % p_rate, 'Content-Length: %d' % p_len ] c = pycurl.Curl() c.setopt(pycurl.URL, str(srv_url)) # curl doesn't support unicode c.setopt(c.HTTPHEADER, http_header) # must be list, not dict c.setopt(c.POST, 1) c.setopt(c.CONNECTTIMEOUT, 30) c.setopt(c.TIMEOUT, 30) c.setopt(c.WRITEFUNCTION, cls.parse_text_result) c.setopt(c.POSTFIELDS, p_speech) c.setopt(c.POSTFIELDSIZE, p_len) try: c.perform() except Exception as e: log.exp("语音转文字发生异常。", e)
def insert(text): try: conn = "" conn = connector.connect(host=mysql_con.HOST, user=mysql_con.USERNAME, password=mysql_con.PASSWORD, port=mysql_con.PORT, database=mysql_con.DATABASE, charset=mysql_con.CHARSET) cursor = conn.cursor() cursor.execute( "INSERT INTO command (`content`,`status`,`posttime`) VALUES (%s,%s,%s)", (text, 0, datetime.timestamp(datetime.now()))) # 提交记录 conn.commit() log.normal("往数据库中插入新命令:" + text) except Exception as e: log.exp("往数据库中插入新命令:" + text, e) finally: if "" != conn: conn.close()
def deal(trans_id, trans_script_name,trans_script_arvg): try: log.normal("执行命令: 命令编号: %d 脚本名称: %s 参数:%s" % (trans_id, trans_script_name, trans_script_arvg)) os.system("python script/%s %s" % (trans_script_name, trans_script_arvg)) except Exception as e: log.exp("执行命令: 命令编号: %d 脚本名称: %s 参数:%s" % (trans_id, trans_script_name, trans_script_arvg), e)
def deal(filename): try: filename_before = "cache/sound/" + "before_" + filename log.normal("开始处理音频文件:" + filename_before) # 转换文字 baidu_voice.Voice.get_text(filename_before) # 重命名文件,避免表明重复扫描 os.rename(filename_before, "cache/sound/" + "end_" + filename) log.normal("音频文件处理完毕:" + filename_before) except Exception as e: log.exp("处理音频文件发生异常: ", e)
def parse_text_result(data): data = json.loads(data.decode("utf-8")) if "success." == data["err_msg"]: result = data["result"][0] # 正则去除标点符号,空格等 p = re.compile("([,。 ]?)") result = p.sub("", result) if "" != result: command.Command.insert(result) else: log.normal("语音转文字为空") else: log.warning("语音转文字失败。原因:" + data["err_msg"])
def start(): # 扫描目录 root_dir = "cache/sound" log.normal("开始扫描音频文件...") while True: try: for file in os.listdir(root_dir): # 搜索 before_ 开头的wav文件 re_wav = re.compile(r'^before_(.+)') m = re_wav.match(file) if m: # 开始处理音频文件 VoiceScan.deal(m.group(1)) except Exception as e: log.exp("扫描音频文件发生异常: ", e)
def tts(cls, text): if len(text) > 1024: log.warning("tts文本过长") return False log.normal("TTS: " + text) # 参数 p_token = cls.get_access_token() # 开放平台获取到的开发者 access_token p_cuid = "FC-AA-14-D0-1D-67" # 用户唯一标识,用来区分用户,填写机器 MAC 地址,长度为60以内 request_url = "http://tsn.baidu.com/text2audio?" data = { "tex": text, "lan": "zh", "tok": p_token, "cuid": p_cuid, "ctp": 1, "spd": "4", "pit": "3", "vol": "9", "per": "3", } request_url_tts = request_url + parse.urlencode(data) try: with request.urlopen(request_url_tts) as f: data = f.read() if 200 != f.status: # 获取错误,返回false log.warning("获取baidu_tts失败,网络错误") return False log.normal("获取baidu_tts成功") # 保存到文件 random.seed() filename = "cache/mp3/" + datetime.now().strftime("%Y-%m-%d_%H_%M_%S") + \ str(random.randint(0, 99999)) + ".mp3" with open(filename, "wb") as file: file.write(data) # 播放 cls.play_mp3(filename) return True except Exception as e: log.exp("获取baidu_tts发生异常。", e) return False
def start(): # 开启声音输入 pa = pyaudio.PyAudio() stream = pa.open(format=pyaudio.paInt16, channels=1, rate=config.RATE, input=True, frames_per_buffer=config.NUM_BLOCK) save_count = 0 save_buffer = [] start_recode = 0 log.normal("开始监听麦克风...") while True: # 读入NUM_SAMPLES个取样 string_audio_data = stream.read(config.NUM_BLOCK) # 将读入的数据转换为数组 audio_data = np.fromstring(string_audio_data, dtype=np.short) # 计算大于LEVEL的取样的个数 large_sample_count = np.sum(audio_data > config.LEVEL) if large_sample_count < config.COUNT_NUM: # 未达到记录等级 if save_count > 1: save_count -= 1 save_buffer.append(string_audio_data) else: if 1 == start_recode: start_recode = 0 save_buffer.append(string_audio_data) log.normal("录音结束") else: save_buffer = [ string_audio_data, ] time.sleep(0.01) else: # 达到记录等级 # 将要保存的数据存放到save_buffer中 save_buffer.append(string_audio_data) if 0 == start_recode: save_count = config.SAVE_LENGTH start_recode = 1 log.normal("开始录音") if 0 == start_recode: # 将save_buffer中的数据写入WAV文件,WAV文件的文件名是保存的时刻 if len(save_buffer) > 1: filename = "cache/sound/before_" + datetime.now().strftime( "%Y-%m-%d_%H_%M_%S") + ".wav" save_wave_file(filename, save_buffer) save_buffer = [] log.normal(filename + " 保存文件")
def trans(command_id, content): try: log.normal("执行命令: 命令编号: %d 内容: %s" % (command_id, content)) try: conn = "" conn = connector.connect(host=mysql_con.HOST, user=mysql_con.USERNAME, password=mysql_con.PASSWORD, port=mysql_con.PORT, database=mysql_con.DATABASE, charset=mysql_con.CHARSET) cursor = conn.cursor() cursor.execute("""SELECT * FROM translates WHERE (`type`=1 AND command=%s) OR (`type`=0 AND command LIKE %s)""", (content, "%" + content + "%", )) is_exec = False # 获取所有记录 row = cursor.fetchone() if None is not row: # 处理 CommandScan.deal(row[0], row[2], row[3]) is_exec = True cursor.close() if False is is_exec: log.normal("命令未执行: 命令编号: %d 内容: %s" % (command_id, content)) except Exception as e: log.exp("翻译命令: %s" % content, e) finally: command.Command.exec(command_id) if "" != conn: conn.close() except Exception as e: log.exp("翻译命令: 命令编号: %d 内容: %s" % (command_id, content), e)
def play_mp3(filename): log.normal("播放MP3 " + filename) try: if os.path.isfile(filename): if os.path.getsize(filename): path_now = os.path.dirname(os.path.abspath(__file__)) if "nt" == os.name: # windows player = os.path.join(path_now, "player", "mpg123-win32.exe") else: # mac linux player = os.path.join(path_now, "player", "mpg123-mac") os.system("%s %s" % (player, filename)) else: log.warning("播放MP3错误,文件不存在:" + filename) else: log.warning("播放MP3错误,文件不存在:" + filename) except Exception as e: log.exp("播放MP3发生异常。", e)
def start(): # 扫描目录 log.normal("开始扫描数据库中未完成的命令...") try: conn = "" while True: try: conn = connector.connect(host=mysql_con.HOST, user=mysql_con.USERNAME, password=mysql_con.PASSWORD, port=mysql_con.PORT, database=mysql_con.DATABASE, charset=mysql_con.CHARSET) cursor = conn.cursor() cursor.execute("SELECT * FROM command WHERE status=%s ORDER BY posttime", ('0', )) # 获取所有记录 results = cursor.fetchall() for row in results: # 处理 CommandScan.trans(row[0], row[1]) cursor.close() time.sleep(1) except Exception as e: log.exp("扫描音频文件发生异常: ", e) finally: if "" != conn: conn.close() except Exception as e: log.exp("扫描数据库未完成命令", e)
def get_access_token(): if "" != Voice.access_token_cache: log.normal("从缓存获取baidu_access_token成功") return Voice.access_token_cache # access_token 保存文件 access_token_filename = "cache/token/baidu_access_token" # 计算时间差,21天换一次 modifiedtime = time.localtime(os.stat(access_token_filename).st_mtime) y = time.strftime('%Y', modifiedtime) m = time.strftime('%m', modifiedtime) d = time.strftime('%d', modifiedtime) try: if 21 > (datetime.now() - datetime(int(y), int(m), int(d))).days: with open(access_token_filename, "r") as file: Voice.access_token_cache = file.read() log.normal("从文件获取baidu_access_token成功") return Voice.access_token_cache except BaseException as e: log.exp("获取baidu_access_token发生异常。", e) return False # 请求地址 grant_type = "client_credentials" # 固定值 client_id = "dnHpAdOFm2jxG0rmnfDbxSsT" # api key client_secret = "c5046dee23e31cf9b542953425f7821e" # secret key request_url_token = "https://openapi.baidu.com/oauth/2.0/token?grant_type=" + grant_type\ + "&client_id=" + client_id \ + "&client_secret=" + client_secret try: with request.urlopen(request_url_token) as f: data = f.read() if 200 != f.status: # 获取错误,返回false log.warning("获取baidu_access_token失败,网络错误") return False data = json.loads(data.decode('utf-8')) log.normal("获取baidu_access_token成功") # 保存到文件 with open(access_token_filename, "w") as file: file.write(data["access_token"]) Voice.access_token_cache = data["access_token"] return Voice.access_token_cache except Exception as e: log.exp("获取baidu_access_token发生异常。", e) return False