import json import os import copy from pathlib import Path from datetime import datetime, timezone from breadbot_common import SQLite, MySQL, TranscriptableFile, mix_audio_with_ffmpeg from txtai.pipeline import Transcription MAX_FILES_PER_CYCLE=50 script_path = Path(__file__).resolve() config_path = Path(script_path.parent, "config.json") with open(config_path, 'r') as config_file: config_json = json.loads(config_file.read()) if config_json["db"]["type"].casefold() == "SQLITE".casefold(): db = SQLite(Path(script_path.parent.parent, config_json["db"]["db_path"])) else: db = MySQL( config_json["db"]["host"], config_json["db"]["user"], config_json["db"]["password"], config_json["db"]["db_name"] ) calls_needing_work = db.query( "SELECT * FROM db_call WHERE NOT call_end_time IS NULL AND call_consolidated = 0 AND call_transcribed = 0" ) if calls_needing_work[0] == 0: print("No work to do, exiting") transcriber = Transcription("openai/whisper-base") for call in calls_needing_work[1]: all_files = os.listdir(Path( config_json["media_voice_folder"], str(call[0]) )) transcriptable_files = [] for file in all_files: print(file) file_name_no_extension = file.split('.')[0] timestamp = int(file_name_no_extension.split('-')[0]) user_snowflake = file_name_no_extension.split('-')[1] file_stamp_as_datetime = datetime.fromtimestamp(timestamp / 1000, timezone.utc) print(file_stamp_as_datetime) print(type(call[1])) print(call[1]) time_diff = file_stamp_as_datetime - datetime.fromisoformat(call[1] + 'Z') print(time_diff) transcriptable_files.append(TranscriptableFile( file_path = str(Path(config_json["media_voice_folder"], str(call[0]), file)), real_date = file_stamp_as_datetime, milliseconds_from_start = int((time_diff.seconds * 1000) + (time_diff.microseconds / 1000)), user_snowflake = user_snowflake )) transcriptable_files.sort(key=lambda a: a.milliseconds_from_start) # TODO Possibly RAM abusive solution to wanting to keep the original list around ffmpeg_files = copy.deepcopy(transcriptable_files) for file in ffmpeg_files: print(file.file_path) print(file.real_date) print(file.milliseconds_from_start) # TODO Error handling for all ffmpeg operations while len(ffmpeg_files) > MAX_FILES_PER_CYCLE: ffmpeg_files = [ mix_audio_with_ffmpeg( ffmpeg_files[index:min(index + MAX_FILES_PER_CYCLE, len(ffmpeg_files))], config_json["media_voice_folder"], call[0], False ) for index in range(0, len(ffmpeg_files), MAX_FILES_PER_CYCLE) ] final_pass_file = mix_audio_with_ffmpeg( ffmpeg_files, config_json["media_voice_folder"], call[0], True ) db.update("db_call", ["call_consolidated"], [1, call[0]], [{ "name": "call_id", "compare": "=" }]) for file in os.listdir(Path(config_json["media_voice_folder"], str(call[0]))): if file.startswith("intermediate"): os.remove(Path(config_json["media_voice_folder"], str(call[0]), file)) for file in transcriptable_files: text = transcriber(file.file_path) db.insert( "db_call_transcriptions", ["speaking_start_time", "text", "callCallId", "userUserSnowflake"], [file.real_date, text, call[0], file.user_snowflake] ) db.update("db_call", ["call_transcribed"], [1, call[0]], [{ "name": "call_id", "compare": "=" }])