Μετάβαση στο περιεχόμενο

Συσκέψεις και μεταγραφή

Το Control Center μπορεί να καταγράψει μια κλήση και να σου επιστρέψει ένα καθαρό κείμενο — σύνοψη, στοιχεία ενέργειας και αποφάσεις — με την αναγνώριση ομιλίας και τον διαχωρισμό ομιλητών να εκτελούνται στο δικό σου υλικό. Σκέψου το Granola, αλλά φιλοξενημένο από εσένα και συνδεδεμένο στον ίδιο χώρο εργασίας όπου ζουν οι πράκτορές σου.

Μια σύσκεψη είναι μια καταγεγραμμένη, μεταγραμμένη συνεδρία. Δεν είναι το ίδιο πράγμα με ένα συμβάν ημερολογίου: ένα συμβάν είναι μια προγραμματισμένη δέσμευση που συγχρονίζεται από τη Google, ενώ μια σύσκεψη είναι κάτι που κατέγραψες πραγματικά. Τα δύο μπορούν να συνδεθούν, αφού μπορείς να ξεκινήσεις μια εγγραφή από ένα συμβάν, αλλά παραμένουν ξεχωριστές καταγραφές.

Κάθε σύσκεψη έχει εμβέλεια χώρου εργασίας, όπως όλα τα άλλα στο Control Center. Συσκέψεις που καταγράφηκαν σε έναν χώρο εργασίας δεν εμφανίζονται ποτέ σε άλλον.

Το «στη συσκευή» είναι το σωστό ένστικτο αλλά η λάθος λέξη. Ο πελάτης συλλαμβάνει τον ήχο και μεταδίδει ροή πλαισίων PCM16 των 16 kHz στο μηχάνημα που εκτελεί το cc_server. Αυτός ο κεντρικός υπολογιστής κάνει όλα τα υπόλοιπα: γράφει τα WAV ανά κανάλι κάτω από το <dataDir>/meetings/<meetingId>/, μεταγράφει σε isolate εργάτη, φιλτράρει την ηχώ και κάνει διαχωρισμό ομιλητών εκ των υστέρων. Σε έναν αυτόνομο υπολογιστή, αυτός ο κεντρικός υπολογιστής είναι το ίδιο μηχάνημα. Όταν δείχνει σε απομακρυσμένο διακομιστή, δεν είναι — οπότε το «τίποτα δεν φεύγει από τον φορητό μου» ισχύει μόνο όταν ο διακομιστής είναι ο φορητός σου.

Υπάρχει μια ακόμη εξαίρεση και είναι η σημαντική.

Όλα πριν από τη σύνοψη — καταγραφή, μεταγραφή, ακύρωση ηχούς, διαχωρισμός ομιλητών, αντιστοίχιση ηχητικών αποτυπωμάτων — εκτελούνται στον διακομιστή χωρίς καμία κλήση δικτύου.

Τα μοντέλα embedding, διαχωρισμού ομιλητών και ομιλίας (ASR) εγκαθίστανται αναγκαστικά στην πρώτη εκκίνηση (παραλείπονται σε ένα demo), ώστε ο διαχωρισμός ομιλητών και η εγγραφή να υπάρχουν χωρίς επίσκεψη στις ρυθμίσεις. Το ASR εξακολουθεί να είναι επιλέξιμο — είναι αρκετές εκατοντάδες megabyte και τέσσερις εκδόσεις περιλαμβάνονται στον επιλογέα. Η ομιλία χρειάζεται ακόμη μία επανεκκίνηση μετά την πρώτη λήψη, επειδή ο μεταγραφέας προσδιορίζει το μοντέλο του πριν προλάβει να ολοκληρωθεί η λήψη.

Οι τέσσερις καταχωρίσεις του επιλογέα, που διαφέρουν σε μέγεθος, κάλυψη γλωσσών και ακρίβεια:

  • Parakeet TDT 0.6B v3 — πολύγλωσσο, η προτεινόμενη προεπιλογή (~600 MB)
  • Parakeet TDT 0.6B v2 — αγγλικά (~480 MB)
  • Whisper large-v3-turbo — πολύγλωσσο (~626 MB)
  • Whisper base.en — μόνο αγγλικά, η μικρή ιστορική προεπιλογή (~198 MB)

Τα μοντέλα είναι τα μόνα αρχεία που λαμβάνει ο διακομιστής κατά την εκτέλεση· κάθε εγγενής βιβλιοθήκη περιλαμβάνεται στο πακέτο.

Μια σύσκεψη καταγράφει δύο κανάλια ήχου ταυτόχρονα:

  • Εσύ («εγώ»): το μικρόφωνό σου.
  • Οι άλλοι («αυτοί»): η έξοδος ήχου της σύσκεψης, που συλλαμβάνεται από loopback χωρίς οδηγό — taps διεργασίας/συσκευής Core Audio σε macOS, loopback WASAPI σε Windows, monitor PipeWire / PulseAudio σε Linux.

Επειδή τα δύο κανάλια καταγράφονται ξεχωριστά, η απομαγνητοφώνηση αποδίδεται σε ομιλητές από την αρχή: τα λόγια σου φέρουν την ετικέτα me, όλοι στη σύνδεση φέρουν την ετικέτα them.

Η φωνή σου διαρρέει από την έξοδο του συστήματος πίσω στο μικρόφωνο και, χωρίς άλλο, θα μεταγραφόταν δύο φορές. Δύο φίλτρα το εμποδίζουν. Σε επίπεδο σήματος, το AEC3 εκτελείται σε κάθε εγγραφή απομακρυσμένης λειτουργίας και είναι υποχρεωτικό — αν η εγγενής βιβλιοθήκη AEC δεν μπορεί να φορτωθεί, η εγγραφή αρνείται να ξεκινήσει αντί να μεταδίδει σιωπηλά ένα μικρόφωνο γεμάτο ηχώ. (Η λειτουργία αυτοπρόσωπης παρουσίας δεν έχει αναφορά απομακρυσμένου άκρου για ακύρωση, οπότε το AEC εκεί είναι πέρασμα ταυτότητας.) Πάνω από αυτό, ένα φίλτρο ηχούς σε επίπεδο κειμένου στην πλευρά του κεντρικού υπολογιστή εκτελείται σε κάθε πλατφόρμα.

Όλη η επεξεργασία μικροφώνου σε επίπεδο λειτουργικού συστήματος είναι σκόπιμα απενεργοποιημένη. Η ενεργοποίηση της ακύρωσης ηχούς ή της αυτόματης ενίσχυσης της ίδιας της πλατφόρμας σε macOS αλλάζει το μικρόφωνο σε Voice Processing I/O, το οποίο σε αυτή την έκδοση σκότωνε και το μικρόφωνο και το tap του ήχου συστήματος.

Κατά την εγγραφή, ο ήχος αποκωδικοποιείται σε κυλιόμενα παράθυρα — κομμένα σε μια σύντομη σιωπή στο τέλος ή σε ένα μέγιστο μήκος παραθύρου — εκτός του νήματος του UI. Κάθε παράθυρο γίνεται ένα τμήμα απομαγνητοφώνησης με ετικέτα ομιλητή και μετατοπίσεις σε χιλιοστά του δευτερολέπτου.

Παράθυρα που δεν ξεπέρασαν ποτέ ένα κατώφλι RMS παραλείπονται χωρίς να αποκωδικοποιηθούν καθόλου, επειδή ένα μοντέλο ομιλίας αποδίδει τη σιωπή ως παραισθησιακά διακριτικά που δεν είναι ομιλία και η αποκωδικοποίηση είναι χαμένος χρόνος CPU. Η πρακτική συνέπεια: ένας σταθερά πολύ χαμηλόφωνος ομιλητής δεν παράγει απομαγνητοφώνηση. Αν κάποιος βγει κενός, έλεγξε τη στάθμη εισόδου του πριν κατηγορήσεις το μοντέλο.

Αφού σταματήσεις, ο διαχωρισμός ομιλητών εκτελείται εκτός σύνδεσης πάνω στην εγγραφή και χωρίζει το απομακρυσμένο κανάλι σε μεμονωμένους ομιλητές (Person 1, Person 2, …) που μπορείς να μετονομάσεις. Ο αριθμός των ομιλητών συνάγεται από ένα κατώφλι ομαδοποίησης, όχι από ένα πλήθος που ορίζεις — άρα είναι τεχνούργημα του κατωφλίου και ένας χαμηλόφωνος ή αλληλοεπικαλυπτόμενος ομιλητής μπορεί να συγχωνευθεί με έναν γείτονα. Η απομαγνητοφώνηση αποδίδεται ως γραμμές [mm:ss] SPEAKER: text.

Η μετονομασία ενός ομιλητή κάνει κάτι περισσότερο από το να επισημάνει μία απομαγνητοφώνηση. Το Control Center μπορεί να αποθηκεύσει το ηχητικό αποτύπωμα του ομιλητή ως προφίλ φωνής, ώστε να τον αναγνωρίζει αυτόματα σε μελλοντικές συσκέψεις. Όταν ονομάζεις έναν ομιλητή που προέκυψε από διαχωρισμό, σου ζητείται αν θέλεις να αποθηκευτεί το ηχητικό αποτύπωμα· αν το κάνεις, αυτό συνδυάζεται σε ένα κινούμενο centroid για αυτό το όνομα και αντιστοιχίζεται με νέους ομιλητές με συνημίτονο ομοιότητας, ώστε το ίδιο άτομο να εμφανίζεται με το όνομά του την επόμενη φορά χωρίς να χρειάζεται να το επισημάνεις ξανά.

Τα προφίλ φωνής έχουν εμβέλεια χώρου εργασίας και δεν περνούν ποτέ τα όρια. Διαχειρίσου τα στις Ρυθμίσεις → Χώρος εργασίας → Συσκέψεις. Η μετονομασία ενός ομιλητή που είχε αποθηκευτεί προηγουμένως αφαιρεί το παλιό όνομα από το μητρώο και προσφέρει να καταχωρίσει το νέο· η διαγραφή ενός προφίλ αφαιρεί το αποθηκευμένο ηχητικό αποτύπωμα αλλά αφήνει άθικτα τυχόν ονόματα που έχουν ήδη εφαρμοστεί σε παλιές συσκέψεις.

Όταν σταματήσει μια εγγραφή, ο διακομιστής δημοσιεύει ένα γεγονός τομέα MeetingRecordingStopped. Το ενσωματωμένο πρότυπο pipeline meeting_summary ενεργοποιείται από αυτό το γεγονός. Η εγγραφή δεν περιμένει αυτό· η σύσκεψη απλώς περνά από τον κύκλο ζωής της κατάστασής της:

recording → processing → done

Ο πράκτορας σύνοψης λαμβάνει τον τίτλο, τις πρόχειρες ζωντανές σημειώσεις σου και την απομαγνητοφώνηση και επιστρέφει δομημένο JSON. Το ποιες ενότητες γράφει καθορίζεται από το ενεργό πρότυπο σημειώσεων σύσκεψης του χώρου εργασίας (Ρυθμίσεις → Χώρος εργασίας → Συσκέψεις)· το ενεργό πρότυπο εφαρμόζεται σε νέες συνόψεις και σε όσες εκτελούνται ξανά. Τα βήματα persist του pipeline γράφουν έπειτα αυτό το JSON σε διακριτές γραμμές:

  • enhancedNotes και summary → οι σημειώσεις της σύσκεψης
  • κάθε στοιχείο ενέργειας → μια γραμμή MeetingActionItem (content, owner, προαιρετικός σύνδεσμος εισιτηρίου)
  • κάθε απόφαση → μια γραμμή MeetingDecision

Τα στοιχεία ενέργειας και οι αποφάσεις δεν εξάγονται ποτέ από ελεύθερο markdown, μόνο από τους δομημένους πίνακες του πράκτορα. Αν μια εκτέλεση δεν παράγει δομημένη έξοδο, τα βήματα persist παραλείπονται και η ακατέργαστη απομαγνητοφώνηση κρατείται ως εφεδρική, ώστε να μη χάνεις ποτέ την καταγραφή. Τίποτα στο pipeline δεν σημαδεύει τη σύσκεψη ως done — ένας μόνο reconciler το κάνει αυτό από το τελικό γεγονός της εκτέλεσης, ώστε η αποτυχία ενός παράλληλου βήματος να μην αφήνει μισογραμμένη μια σύσκεψη που μοιάζει ήδη ολοκληρωμένη.

Επιφάνεια Τι εμφανίζει
/meetings Η λίστα συσκέψεων, με πλήθη στοιχείων ενέργειας και αποφάσεων
/meetings/record Το HUD ζωντανής εγγραφής: οι σημειώσεις σου στη μία πλευρά, η απομαγνητοφώνηση σε ροή στην άλλη
/meetings/:meetingId Οι λεπτομέρειες μιας σύσκεψης: καρτέλες Σημειώσεις, Πρακτικό, Στοιχεία ενέργειας και Αποφάσεις
Ρυθμίσεις → Χώρος εργασίας → Συσκέψεις Πρότυπα σημειώσεων και αποθηκευμένα προφίλ φωνής για αυτόν τον χώρο εργασίας

Η καταγραφή είναι χωρίς οδηγούς και στις τρεις πλατφόρμες επιφάνειας εργασίας (taps Core Audio σε macOS, WASAPI σε Windows, PipeWire σε Linux).

Και ο πελάτης web καταγράφει, κάτι που μπορεί να κρύψει η υπόλοιπη εστίαση αυτής της σελίδας στην επιφάνεια εργασίας: ο περιηγητής παίρνει το μικρόφωνό σου μέσω getUserMedia και τον ήχο της σύσκεψης μέσω getDisplayMedia (κοινή χρήση οθόνης), κάνει υποδειγματοληψία σε PCM16 16 kHz και μεταδίδει ροή στον ίδιο κεντρικό υπολογιστή. Ισχύουν τρεις επιφυλάξεις εκεί:

  • Η κοινόχρηστη επιφάνεια πρέπει να φέρει κομμάτι ήχου. Ο Safari, ο Firefox και η κοινή χρήση πλήρους οθόνης του macOS δεν παρέχουν κανένα και η εγγραφή αρνείται να ξεκινήσει.
  • Δεν υπάρχει εγγενές AEC3. Η ακύρωση ηχούς του ίδιου του περιηγητή ζητείται στο μικρόφωνο· το φίλτρο ηχούς κειμένου στην πλευρά του κεντρικού υπολογιστή εκτελείται ακόμη. Το HUD δείχνει ένα όργανο στάθμης εισόδου που τροφοδοτείται από το PCM του μικροφώνου.
  • Η εκ νέου εκτέλεση σύνοψης και η ακύρωση επεξεργασίας είναι μόνο για επιφάνεια εργασίας.

Η ενέργεια Έναρξη εγγραφής και σύνδεση του ημερολογίου είναι μόνο για επιφάνεια εργασίας και το αναφέρει καθαρά στο web, παρόλο που η δική της ροή εγγραφής της οθόνης συσκέψεων λειτουργεί εκεί.