From fe3d6cadc6e255a7acea8a794677ab350195a474 Mon Sep 17 00:00:00 2001 From: Yannik Schmidt Date: Sun, 9 Feb 2020 02:17:26 +0100 Subject: [PATCH] refactor --- python-server/exec_server.py | 45 ------- python-server/filesystem.py | 97 ++++----------- python-server/server.py | 46 ++++++++ python-server/server_interface.py | 111 ------------------ python-server/speech.py | 48 +++----- .../{transcribe_async.py => transcribe.py} | 0 6 files changed, 85 insertions(+), 262 deletions(-) delete mode 100755 python-server/exec_server.py create mode 100755 python-server/server.py delete mode 100644 python-server/server_interface.py rename python-server/{transcribe_async.py => transcribe.py} (100%) diff --git a/python-server/exec_server.py b/python-server/exec_server.py deleted file mode 100755 index 8b2f870..0000000 --- a/python-server/exec_server.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/python3 - -import socketserver -import server_interface -from configparse_wrapper.cpwrap import CFG, parse_config, change_cfg - -class AppRequestHandler(socketserver.BaseRequestHandler): - def __init__(self, request, client_address, server): - socketserver.BaseRequestHandler.__init__(self, request, client_address, server) - return - - def setup(self): - return socketserver.BaseRequestHandler.setup(self) - - def handle(self): - data = b"" - print("Recieved request") - while True: - tmp = self.request.recv(1024) - if not tmp or b"\nterminate\n" in tmp: - if len(tmp) > len("\nterminate\n"): - data += tmp[:-len("\nterminate\n")] - break - data += tmp - retval = server_interface.parse_request(data) - try: - self.request.send(retval) - self.request.send(b"terminate\n") - print("Replied with: {}".format(retval)) - except BrokenPipeError: - print("Connection was closed before reply could be sent.") - return - - def finish(self): - return socketserver.BaseRequestHandler.finish(self) - -def start_server(): - socketserver.TCPServer.allow_reuse_address = True - server = socketserver.TCPServer((CFG("interface"),CFG("port")),AppRequestHandler) - server.serve_forever() - - -if __name__ == "__main__": - parse_config() - start_server() diff --git a/python-server/filesystem.py b/python-server/filesystem.py index 8d51533..08d99dd 100644 --- a/python-server/filesystem.py +++ b/python-server/filesystem.py @@ -3,89 +3,42 @@ import os.path import audiosegment_wrapper as AudioSegment from configparse_wrapper.cpwrap import CFG -audiofiles = [] FTP_DIR = CFG("shareDir") -def save_audio(filename, base64_string): - global audiofiles - audiofiles += [filename[:-4]] - decoded = None - orig_filename = filename[:-4]+"_orig" - try: - decoded = base64.b64decode(base64_string) - except TypeError: - return b"ERROR_INVALID_ENCODING_64" +def saveAudio(filename, data): + '''Save a single Audiofile to disk''' + if os.path.isfile(filename): - return b"ERROR_FILE_EXISTS" - write_file(orig_filename, decoded) + raise ValueError("File: {} already exists.".format(filename)) - seg = AudioSegment.from_file(orig_filename) - seg = seg.resample(sample_rate_Hz=32000, sample_width=2, channels=1) + with open(filename,"wb") as f: + f.write(data) - seg.export(filename,format="wav") - seg.export(FTP_DIR + filename,format="wav") + if False: + seg = AudioSegment.from_file(orig_filename) + seg = seg.resample(sample_rate_Hz=32000, sample_width=2, channels=1) + seg.export("{}.wav".format(filename), format="wav") - return b"SUCCESS" +def saveAudioChain(filename, dataArray): + '''Combine multiple received audio files into one and save it''' -def save_audio_chain(file_str_tupels): completeAudio = None - for fname, base64_string in file_str_tupels: - print("Filename: {}".format(fname)) - decoded = None - orig_filename = fname[:-4]+"_orig" - try: - decoded = base64.b64decode(base64_string) - except TypeError: - return b"ERROR_INVALID_ENCODING_64" - with open(orig_filename,"wb") as f: - f.write(decoded) - if completeAudio == None: - completeAudio = AudioSegment.from_file(orig_filename) + for index, data in enumerate(dataArray): + tmpFile = "{}.{}.tmp".format(filename, index) + with open(filename, "wb") as f: + f.write(data) + if not completeAudio: + completeAudio = AudioSegment.from_file(tmpFile) else: - completeAudio += AudioSegment.from_file(orig_filename) - if not completeAudio: - return b"ERROR_AUDIO_CONCAT_FAILED" - else: - completeAudio = completeAudio.resample(sample_rate_Hz=32000, sample_width=2, channels=1) - completeAudio.export(file_str_tupels[0][0],format="wav") - completeAudio.export(FTP_DIR + file_str_tupels[0][0],format="wav") - return b"SUCCESS" + completeAudio += AudioSegment.from_file(tmpFile) -def save_transcript(filename, transcript): - global audiofiles - try: - audiofiles.remove(filename[:4]) - except: - print("Audiofile not in working list") - if os.path.isfile(filename): - pass - with open(filename + "_transcript","w") as f: - f.write(transcript) - with open(FTP_DIR + filename + "_transcript","w") as f: + completeAudio = completeAudio.resample(sample_rate_Hz=32000, sample_width=2, channels=1) + completeAudio.export("{}.wav".format(filename), format="wav") + +def saveTranscript(filename, transcript): + with open("{}_transcript.txt".format(filename), "w") as f: f.write(transcript) def get_transcript(filename): - global audiofiles - try: - with open("data/" + filename + ".wav_transcript","r") as f: + with open("{}_transcript.txt".format(filename), "r") as f: return f.read() - except FileNotFoundError: - if filename in audiofiles: - return "ERROR_FILE_STILL_IN_WORK" - return "ERROR_FILE_NOT_AVAILIABLE" - -def filelist(): - return "" - -def fileinfo(filename): - return "" - -def copy_to_output(filename): - return "" - -def write_file(filename, data): - global FTP_DIR - with open(FTP_DIR + filename,"wb") as f: - f.write(data) - with open(filename,"wb") as f: - f.write(data) diff --git a/python-server/server.py b/python-server/server.py new file mode 100755 index 0000000..f2a8ee1 --- /dev/null +++ b/python-server/server.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 + +import flask + +@app.route('/submit') +def transferToServer(): + # TODO receive data + data = None + decoded = decoded = base64.b64decode(data) + filesystem.saveAudio(filename, data) + return "", 204 + +@app.route('/submit-chain') +def transferToServerChain(): + # TODO receive data + data = [] + dataDecoded = [ base64.b64decode(d) for d in data ] + filesystem.saveAudioChain(filename, dataDecoded) + return "", 204 + +@app.route('/transcript') +def queryTranscript(): + filename = flask.request.args.filename + transcript = filesystem.getTranscript(filename) + return transcript + +@app.route('/fileinfo') +def singleFileInfo(): + filename = flask.request.args.filename + return filesystem.fileinfo(filename) + +@app.route('/filelist') +def getMultiFileInfo(): + return filesystem.filelist() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Start speech app server', \ + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('--interface', default="localhost", \ + help='Interface on which flask (this server) will take requests on') + parser.add_argument('--port', default="5002", \ + help='Port on which flask (this server) will take requests on') + args = parser.parse_args() + + app.run(host=args.interface, port=args.port) diff --git a/python-server/server_interface.py b/python-server/server_interface.py deleted file mode 100644 index f48090a..0000000 --- a/python-server/server_interface.py +++ /dev/null @@ -1,111 +0,0 @@ -import speech -import filesystem -from configparse_wrapper.cpwrap import CFG - -MAIN_DIR = bytes(CFG("mainDataDir"),CFG("encoding")) - - -def parse_request(data): - ''' parse request and call correct function ''' - #return b"DUMMY" - print(data.split(b",")[0]) - # echo/test connection # - cleared_data = is_data_type(b"ECHOREQUEST,",data) - if cleared_data: - return cleared_data - - # reply transcript # - cleared_data = is_data_type(b"GET_TRANSCRIPT,",data) - if cleared_data: - filename = cleared_data.decode("utf-8") - return filesystem.get_transcript(filename).encode("utf-8") - - # get single file info # - cleared_data = is_data_type(b"GET_FILEINFO,",data) - if cleared_data: - filename = data.decode("utf-8") - return filesystem.fileinfo(filename).encode("utf-8") - - # get single file info # - cleared_data = is_data_type(b"GET_FILEINFO_ALL,",data) - if cleared_data: - return filesystem.filelist().encode("utf-8") - - # handle audio transmission # - cleared_data = is_data_type(b"AUDIO_TRANSMISSION,",data) - if cleared_data: - print("Handling audio transmission") - filename = None - try: - filename, base64_string = cleared_data.split(b',') - filename = MAIN_DIR + filename.split(b"/")[-1] + b".wav" - filename = filename.decode("utf-8") - except ValueError: - return b"ERROR_MALFORMED_REQUEST" - ret = filesystem.save_audio(filename, base64_string) - if b"ERROR" in ret: - return ret - speech.async_create_transcript(filename) - return ret - - # handle a chain of audiotransmissions # - if data.startswith(b"CHAIN_AUDIO_TRANSMISSION"): - file_str_tuples = [] - arr = data.split(b"|") - for el in arr[1:-1]: - filename, base64_string = el.split(b',') - filename = MAIN_DIR + filename.split(b"/")[-1] + b".wav" - filename = filename.decode("utf-8") - file_str_tuples += [(filename,base64_string)] - - if len(file_str_tuples) < 2: # a chain has 2 or more elements - return bytes("ERROR_INVALID_NUMBER_FILES_{}".format(len(file_str_tuples)),"utf-8") - - ret = filesystem.save_audio_chain(file_str_tuples); - if b"ERROR" in ret: - return ret - speech.async_create_transcript(file_str_tuples[0][0]) - return ret - - - # other shit - return b"UNRECOGNIZED_SERVER_OPTION\n" - - - -def is_data_type(tag,data): - data = data.strip(b"\n") - if data.startswith(tag): - ret = data.split(tag)[1] - if not ret: - ret = b"NULL\n" - return ret - return None - - -def reply_logs(loglevel=0,lines=100): - ''' replies with recent logs ''' - pass - -def reply_backend(backend=None): - ''' replies with current backend if None or sets the new one ''' - pass - -def reply_files(after=None, before=None, regex=None): - ''' replies with a list of transcribed or to be transcribed files ''' - -def reply_transcript(filename=None): - ''' replies with the latest transcript or the transcript of the chosen name ''' - pass - -def reply_audio(filename=None): - ''' replies with the chosen audio as a file ''' - pass - -def recive_transcribe_request(audiofile): - ''' saves and transcribes and audiofile ''' - pass - -def android_unittest_transcribe_request(audiofile): - ''' the android unittests append a special keyword, requests are dummy handled ''' - pass diff --git a/python-server/speech.py b/python-server/speech.py index bdfbf91..2abad87 100644 --- a/python-server/speech.py +++ b/python-server/speech.py @@ -1,43 +1,23 @@ -import speech_recognition as spr import multiprocessing as mp import os.path import filesystem import log -import transcribe_async -import os +import transcribe USE_FREE=False USE_PAID=True -def async_create_transcript(filename): - print("Creating transcript..") - mp.Process(target=create_and_save_transcript,args=(filename,)).start() +def asyncCreateTranscript(filename): + mp.Process(target=createAndSaveTranscript, args=(filename,)).start() -def create_and_save_transcript(filename): - transcript = analyse(filename) - filesystem.save_transcript(filename, transcript) - #os.system("../permissions.sh") - -def analyse(filename): - ''' returns the transcripted audio, or None if the analysis fails ''' - try: - if USE_FREE: - recognizer = spr.Recognizer() - with spr.AudioFile(filename) as source: - audio = recognizer.record(source) - string = free_google_backend(recognizer, audio) - elif USE_PAID: - string = paid_google_backend(filename) - except spr.UnknownValueError: - log.log("Audio file is broken or not an audio file") - return "ERROR_AUDIO_FILE_INVALID" - except spr.RequestError as e: - log.log("Could not connect to google API: {}".format(e)) - return "ERROR_API_FAILURE" - return string - -def free_google_backend(recognizer, audio): - return recognizer.recognize_google(audio,language="de-DE") - -def paid_google_backend(filename): - return transcribe_async.transcribe_file(filename) +def createAndSaveTranscript(filename): + if no hasTranscript(filename): + try: + string = transcribe.transcribeFile(filename) + except spr.UnknownValueError: + log.log("Audio file is broken or not an audio file.") + raise e + except spr.RequestError as e: + log.log("Could not connect to google API: {}".format(e)) + raise e + filesystem.saveTranscript(filename, string) diff --git a/python-server/transcribe_async.py b/python-server/transcribe.py similarity index 100% rename from python-server/transcribe_async.py rename to python-server/transcribe.py