Δεν θέλω να ανοίγω browser (ναι μπορεί να μην το έχω ανοιχτό εκείνη τη στιγμή) όταν ας πούμε διαβάζω στα αγγλικά ένα txt αρχείο ή ένα μυνημα στο viber ή οτιδήποτε. Θέλει κάποια κλικ παραπάνω.
Ενώ αυτό που έχω είναι κολλημένο στην Επιφάνεια εργασίας και δέχεται είτε πληκτρολόγηση, είτε drag and drop, είτε φωνητική εισαγωγή κειμένου.
Για να μου δουλέψει χρειάται τα API της Google, για τη μετάφραση και για το speech to text.
Τα έχω όλα ρυθμισμένα και εντάξει. Διαπιστευτήρια, κλειδιά κλπ από την Google.
Το πρόβλημα μου είναι στον κώδικα.
Ας δείξω πρώτα μία εικόνα για το widget
Είναι ανάμεσα σε άλλα widget και το έχω μόνιμα στην Επιφάνεια εργασίας.
Δουλεύει μια χαρά. Κρατάει ιστορικό και το χειρίζομαι με τα βελάκια του πληκτρολογίου (όπως κάνουμε και στο τερματικό μας για τις προηγούμενες εντολές), δέχεται εναπόθεση κειμένου πέραν από την πληκτρολόγηση, αντιδρά και με το κουμπί "Μετάφραση" αλλά και με το ENTER και επίσης αναγνωρίζει αυτόματα τι γλώσσα του εισάγω ώστε να μεταφράσει στην άλλη.
κι όταν πατήσω το ENTER το κείμενο που βλέπετε στα ελληνικά θα σβήσει και θα τεθεί ο δρομέας σε κατάσταση focus, ενώ στο πλαίσιο εξόδου, θα φαίνεται η μετάφραση
Ενώ αν εισάγω αγγλικό κείμενο
(το κείμενο το μεταφρασμένο έχει μείνει από την τελευταία φορά που είχε τυπώσει κάτι.)
και με το ENTER ή το "Μετάφραση"
Όλα καλά λοιπόν. Με έχει βολέψει καθώς εναποθέτω με σύρσιμο και μεγάλα κείμενα.
Όταν όμως πατήσω το μικρόφωνο συμβαίνει κάτι περίεργο. Έχει ακούσει κανονικά το κείμενο και μια χαρά δουλεύει το speech to text. Όμως δεν βλέπω στο πεδίο εισαγωγής κειμένου (Το QLineEdit στον κώδικα), αυτά που έχω πει με τη φωνή μου. Για να συμβεί αυτό, πρέπει να κάνω mute τη συσκευή εισόδου ήχου (το μικρόφωνό μου) από τις ρυθμίσεις ήχου του συστήματος. Ή όταν κάνω κλικ σε ένα σκριπτάκι που κάνει αυτό το πράγμα (κάνει mute και unmute το μικρόφωνό μου)
- Κώδικας: Επιλογή όλων
#!/bin/bash
amixer -q -D pulse sset Capture toggle
Έχω δηλαδή το σκριπτάκι αυτό εκτελέσιμο, του κάνω κλικ και τότε μόνο βλέπω στο widget μου να εμφανίζεται το κείμενο όπως το είπα, στο πεδίο εισόδου. Καθαρα και μια χαρά κι ας είναι και πάρα πολλές λέξεις.
Δεν μπορώ να το λύσω αυτό το πρόβλημα.
Εν τω μεταξύ, όταν πατάω το κουμπί-εικονίδιο του μικροφώνου κάτω δεξιά όπως βλέπετε στο widget, μου βγάζει μηνύματα λάθους το τερματικό, ενώ μέχρι εκείνη τη στιγμή απλά ο δρομέας είναι απασχολημένος; σαν να λέει ότι τρέχει κανονικά το πρόγραμμα, χωρίς καμία λέξη λάθους.
- Κώδικας: Επιλογή όλων
$ python3 pirama.py
ALSA lib pcm_dsnoop.c:566:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:999:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp
ALSA lib pcm_a52.c:1001:(_snd_pcm_a52_open) a52 is only for playback
ALSA lib confmisc.c:160:(snd_config_get_card) Invalid field card
ALSA lib pcm_usb_stream.c:482:(_snd_pcm_usb_stream_open) Invalid card 'card'
ALSA lib confmisc.c:160:(snd_config_get_card) Invalid field card
ALSA lib pcm_usb_stream.c:482:(_snd_pcm_usb_stream_open) Invalid card 'card'
ALSA lib pcm_dmix.c:999:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm_dsnoop.c:566:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:999:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp
ALSA lib pcm_a52.c:1001:(_snd_pcm_a52_open) a52 is only for playback
ALSA lib confmisc.c:160:(snd_config_get_card) Invalid field card
ALSA lib pcm_usb_stream.c:482:(_snd_pcm_usb_stream_open) Invalid card 'card'
ALSA lib confmisc.c:160:(snd_config_get_card) Invalid field card
ALSA lib pcm_usb_stream.c:482:(_snd_pcm_usb_stream_open) Invalid card 'card'
ALSA lib pcm_dmix.c:999:(snd_pcm_dmix_open) unable to open slave
Αυτό είναι το πρόβλημα που αντιμετωπίζω και αυτός είναι ο κώδικας
- Κώδικας: Επιλογή όλων
#!/usr/bin/env python3
import sys
import speech_recognition as sr
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLineEdit, QTextEdit
from PyQt5.QtCore import Qt
from google.cloud import translate_v2 as translate
from google.oauth2 import service_account
from google.cloud import speech_v1p1beta1 as speech
from PyQt5.QtGui import QIcon, QPixmap
class TranslucentTranslationWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowFlag(Qt.FramelessWindowHint)
self.setGeometry(1220, 460, 450, 310)
self.setFixedSize(450, 310)
self.setWindowFlag(Qt.WindowStaysOnBottomHint)
self.setAcceptDrops(True)
self.setStyleSheet("background-color: #ffdad3;")
credentials = service_account.Credentials.from_service_account_file('/home/user/scripts/translate/token.json', scopes=['https://www.googleapis.com/auth/cloud-translation'])
self.translator = translate.Client(credentials=credentials)
vbox = QVBoxLayout(self)
vbox.setContentsMargins(0, 0, 0, 0) # Ορίζει το περιθώριο για το vbox
self.text_input = QLineEdit(self)
self.text_input.setPlaceholderText("Γράψε εδώ το κείμενο να μεταφράσω")
self.text_input.setStyleSheet("border: 1px dashed #00FF00; background-color: #d0aa7c;")
self.text_input.setFixedHeight(40) # Ορίζει το ύψος του πεδίου εισαγωγής σε 40 pixels
self.text_output = QTextEdit(self)
self.text_output.setStyleSheet("color: white; background-color: rgba(0, 0, 0, 255); font-weight: bold;")
vbox.addWidget(self.text_input, stretch=5)
vbox.addWidget(self.text_output, stretch=5) # Αλλαγή εδώ σε stretch=5
vbox_input = QVBoxLayout()
vbox_input.setContentsMargins(0, 0, 0, 2)
self.translate_button = QPushButton("Μετάφραση", self)
self.translate_button.setStyleSheet("background-color: #aed08b;") # Κίτρινο
self.translate_button.clicked.connect(self.translate_text)
self.start_recognition_button = QPushButton(self)
pixmap = QPixmap("microphone.png")
icon = QIcon(pixmap)
self.start_recognition_button.setIcon(icon)
self.start_recognition_button.setIconSize(pixmap.rect().size())
self.start_recognition_button.setMaximumSize(40, 40) # Ορίζει το μέγιστο πλάτος και ύψος
vbox_input.addWidget(self.translate_button)
vbox_input.addWidget(self.start_recognition_button, alignment=Qt.AlignRight | Qt.AlignBottom)
# Ορίζει το περιθώριο για την περιοχή του vbox_input
vbox_input.setContentsMargins(0, 0, 0, 0)
self.start_recognition_button.clicked.connect(self.start_recognition)
vbox.addLayout(vbox_input)
self.text_input.returnPressed.connect(self.translate_text)
self.text_input.installEventFilter(self)
# Όνομα αρχείου ιστορικού
self.history_file = "history.txt"
# Αρχικοποίηση ιστορικού
self.load_history()
def translate_text(self):
text = self.text_input.text()
translation = self.translator.translate(text, target_language='en' if self.is_greek(text) else 'el')
self.text_output.setPlainText(translation['translatedText'])
self.text_input.clear()
self.text_input.setSelection(0, len(translation['translatedText']))
# Προσθήκη στο ιστορικό
self.add_to_history(text)
def is_greek(self, text):
for char in text:
if 'α' <= char <= 'ω' or 'Α' <= char <= 'Ω':
return True
return False
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls():
url = event.mimeData().urls()[0]
with open(url.toLocalFile(), "r") as f:
self.text_input.setText(f.read())
event.accept()
else:
event.ignore()
def add_to_history(self, text):
# Προσθήκη κειμένου στο τέλος του ιστορικού
self.history_list.append(text)
# Ενημέρωση του αρχείου ιστορικού
with open(self.history_file, "a") as file:
file.write(text + "\n")
def load_history(self):
# Φόρτωση ιστορικού από το αρχείο
try:
with open(self.history_file, "r") as file:
self.history_list = file.read().splitlines()
self.history_index = len(self.history_list)
except FileNotFoundError:
# Το αρχείο δεν υπάρχει ακόμα
self.history_list = []
self.history_index = 0
def retrieve_from_history(self, forward=True):
# Ανάκτηση κειμένου από το ιστορικό
if forward:
# Προς τα εμπρός
if self.history_index < len(self.history_list) - 1:
self.history_index += 1
else:
# Προς τα πίσω
if self.history_index > 0:
self.history_index -= 1
if 0 <= self.history_index < len(self.history_list):
self.text_input.setText(self.history_list[self.history_index])
else:
self.text_input.clear()
def eventFilter(self, obj, event):
if obj is self.text_input and event.type() == event.KeyPress:
if event.key() == Qt.Key_Up:
self.retrieve_from_history(forward=False)
return False # Επιστροφή False για την αποφυγή περαιτέρω επεξεργασίας του event
elif event.key() == Qt.Key_Down:
self.retrieve_from_history(forward=True)
return False # Επιστροφή False για την αποφυγή περαιτέρω επεξεργασίας του event
return super().eventFilter(obj, event)
# Προσθήκη συνάρτησης για έναρξη φωνητικής αναγνώρισης
def start_recognition(self):
recognizer = sr.Recognizer()
with sr.Microphone() as source:
audio = recognizer.listen(source)
try:
text = recognizer.recognize_google(audio, language="el-GR")
self.text_input.setText(text)
self.text_input.repaint() # Ανανέωση του πεδίου εισόδου
except sr.UnknownValueError:
print("Google Speech Recognition could not understand audio")
except sr.RequestError as e:
print(f"Could not request results from Google Speech Recognition service; {e}")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TranslucentTranslationWindow()
window.show()
sys.exit(app.exec_())