diff --git a/app/app.py b/app/app.py index 13c5513..d6f2b16 100644 --- a/app/app.py +++ b/app/app.py @@ -5,7 +5,13 @@ from dotenv import load_dotenv load_dotenv(os.path.join(os.path.dirname(__file__), '..', '.env')) -ACTIVE_AGENTS = ["lex_chatgpt", "lex_llama"] +import whisper +from utils import MODEL_DIRECTORY + +transcriber = whisper.load_model("medium", download_root=MODEL_DIRECTORY) + + +ACTIVE_AGENTS = ["lex_chatgpt"]#, "lex_llama"] script_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(script_dir) @@ -27,7 +33,9 @@ app = Flask(__name__) app.secret_key = os.getenv('SECRET_KEY', 'supersecret') # Você precisa definir uma chave secreta para usar sessions -socketio = SocketIO(app, cors_allowed_origins="*", ping_timeout=120) +socketio = SocketIO(app, + cors_allowed_origins="*", + ping_timeout=120) @app.route('/') def index(): @@ -54,13 +62,26 @@ def handle_message(message): user_input = message.get('message') room = request.sid # Obtém o ID da sessão atual current_agent_name = session.get('current_agent') + socketio.emit('start_message', room=room) # Envia para o room especificado + socketio.start_background_task(message_task, current_agent_name, user_input, room) + +@socketio.on('audioMessage') +def handle_audioMessage(audio_blob): + room=request.sid + socketio.start_background_task(audio_task, audio_blob, room) + +def audio_task(audio_blob, room): # Carregar modelo e transcrever o áudio + # Salvar o blob de áudio como um arquivo temporário + with open("temp_audio.wav", "wb") as f: + f.write(audio_blob) + result = transcriber.transcribe("temp_audio.wav", verbose=True) + socketio.emit('transcription', {'result': result['text']}, room=room) + +def message_task(current_agent_name, user_input, room): current_agent = loaded_agents[current_agent_name] if not user_input: return None - - socketio.emit('start_message') # Envia para o room especificado - if user_input.startswith('!'): command, *args = user_input[1:].split() if command in loaded_commands: @@ -71,7 +92,7 @@ def handle_message(message): else: response = current_agent.run(human_input=user_input) - socketio.emit('message', response, room=room) # Envia para o room especificado + socketio.emit('message', {'result' : response}, room=room) # Envia para o room especificado socketio.emit('end_message', room=room) # Envia para o room especificado if __name__ == "__main__": diff --git a/app/requirements.txt b/app/requirements.txt index 95c8da3..e8ac241 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -28,4 +28,6 @@ flask_socketio gunicorn eventlet -huggingface-hub==0.17.3 \ No newline at end of file +huggingface-hub==0.17.3 + +openai-whisper \ No newline at end of file diff --git a/app/static/css/style.css b/app/static/css/style.css index a8be6e2..5f8a847 100644 --- a/app/static/css/style.css +++ b/app/static/css/style.css @@ -6,6 +6,8 @@ body { color: #00ff00; display: flex; flex-direction: column; + justify-content: center; /* Adicionado para centralizar verticalmente */ + align-items: center; /* Adicionado para centralizar horizontalmente */ height: 100vh; } @@ -15,10 +17,12 @@ h1 { text-align: center; } + #chat-box { flex: 1; background: rgba(0, 0, 0, 0.8); width: 100%; + max-width: 960px; /* Adicionado para limitar a largura do chat-box */ border: 2px solid #00ff00; overflow-y: auto; border-radius: 8px; @@ -42,35 +46,83 @@ h1 { background-color: #222222; } -input, button { - border: none; +.typing-indicator { + padding: 10px; + margin: 10px; + color: #00ff00; /* Mesma cor dos outros textos */ + font-style: italic; /* Um pouco de inclinação para destacar */ + animation: fadein 2s ease-in-out infinite; /* Adicionando uma animação de fade */ +} + +@keyframes fadein { + 0% { opacity: 0.5; } + 50% { opacity: 1; } + 100% { opacity: 0.5; } +} + +.dot-anim::before { + content: ' .'; + animation: dots 1s steps(5, end) infinite; + color: #00ff00; /* Mesma cor dos outros textos */ +} + +@keyframes dots { + 0%, 20% { + content: ' .'; + } + 40% { + content: ' . .'; + } + 60% { + content: ' . . .'; + } + 80%, 100% { + content: ''; + } +} + + +/* Estilizando o botão Limpar Histórico */ +.button-container { + display: flex; + align-items: center; +} + +.button-container button { background: rgba(0, 0, 0, 0.8); color: #00ff00; - border-bottom: 2px solid #00ff00; + border: 2px solid #00ff00; border-radius: 5px; + width: 60px; + height: 60px; + cursor: pointer; + margin-right: 0.5rem; + transition: background 0.3s ease; } +.button-container button:hover { + background: rgba(0, 255, 0, 0.2); +} + + input { + border: none; + background: rgba(0, 0, 0, 0.8); + color: #00ff00; + border-bottom: 2px solid #00ff00; + border-radius: 5px; flex: 1; height: 60px; margin-right: 0.5rem; } -button { - cursor: pointer; - height: 60px; - width: 80px; -} - -button:hover { - background: rgba(0, 255, 0, 0.2); -} .footer { display: flex; align-items: center; - justify-content: space-between; - width: 100%; + justify-content: center; + width: 95%; + max-width: 960px; background-color: rgba(0, 0, 0, 0.8); padding: 1rem; position: sticky; diff --git a/app/static/js/plugin-audioRecorder.js b/app/static/js/plugin-audioRecorder.js new file mode 100644 index 0000000..6ef220a --- /dev/null +++ b/app/static/js/plugin-audioRecorder.js @@ -0,0 +1,54 @@ +document.addEventListener("DOMContentLoaded", function() { + // Injetar o botão de gravação no container de botões + const buttonContainer = document.querySelector(".button-container"); + const recordButton = document.createElement("button"); + recordButton.id = "record-audio"; + recordButton.innerHTML = ''; + buttonContainer.appendChild(recordButton); + + var mediaRecorder; + var audioChunks = []; + + // Inicializar MediaRecorder + navigator.mediaDevices.getUserMedia({ audio: true }) + .then(stream => { + mediaRecorder = new MediaRecorder(stream); + mediaRecorder.ondataavailable = event => { + audioChunks.push(event.data); + }; + + mediaRecorder.onstop = () => { + var audioBlob = new Blob(audioChunks, { type: "audio/wav" }); + // Você pode enviar audioBlob para o servidor aqui + addIndicator('Lex esta transcrevendo seu audio...') + socket.emit('audioMessage', audioBlob); + var audioUrl = URL.createObjectURL(audioBlob); + var audio = new Audio(audioUrl); + audio.play(); + + audioChunks = []; + }; + }); + + // Função para começar a gravação + function startRecording() { + mediaRecorder.start(); + document.getElementById("record-audio").innerHTML = ''; + } + + // Função para parar a gravação + function stopRecording() { + setTimeout(() => { + mediaRecorder.stop(); + document.getElementById("record-audio").innerHTML = ''; + }, 300) + } + + document.getElementById("record-audio").addEventListener("mousedown", function() { + startRecording(); + }); + + document.getElementById("record-audio").addEventListener("mouseup", function() { + stopRecording(); + }); +}); diff --git a/app/templates/index.html b/app/templates/index.html index b151082..5de5974 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -7,17 +7,23 @@ - + +