Gå til innholdet

Møter og transkripsjon

Control Center kan ta opp en samtale og gi deg et ryddig referat — et sammendrag, tiltak og beslutninger — med talegjenkjenning og talerseparering som kjører på din egen maskinvare. Tenk Granola, men selvhostet og koblet til det samme arbeidsområdet som agentene dine lever i.

Et møte er en økt som er tatt opp og transkribert. Det er ikke det samme som en kalenderhendelse: en hendelse er en planlagt forpliktelse som synkroniseres fra Google, mens et møte er noe du faktisk har tatt opp. De to kan kobles sammen, siden du kan starte et opptak fra en hendelse, men de forblir separate oppføringer.

Hvert møte er knyttet til et arbeidsområde, som alt annet i Control Center. Møter som tas opp i ett arbeidsområde, dukker aldri opp i et annet.

«På enheten» er riktig instinkt, men feil betegnelse. Klienten fanger opp lyd og strømmer 16 kHz PCM16-rammer til maskinen som kjører cc_server. Den verten gjør alt annet: skriver WAV-filene per kanal under <dataDir>/meetings/<meetingId>/, transkriberer i et worker-isolat, filtrerer ekko og diariserer i etterkant. På en frittstående skrivebordsmaskin er den verten den samme maskinen. Pekes klienten mot en ekstern server, er den ikke det — så «ingenting forlater laptopen min» er bare sant når serveren er laptopen din.

Det finnes ett unntak til, og det er det viktige.

Alt før sammendraget — opptak, transkripsjon, ekkoutligning, diarisering, sammenligning av stemmeavtrykk — kjører på serveren uten nettverkskall.

Modellene for innbygging, diarisering og tale (ASR) tvangsinstalleres ved første oppstart (hoppes over i en demo), slik at talerseparering og opptak finnes uten et besøk i innstillingene. ASR er fortsatt valgbart — det er flere hundre megabyte, og fire bygg følger med i velgeren. Tale trenger fortsatt én omstart etter den første nedlastingen, fordi transkribereren løser opp modellen sin før hentingen kan bli ferdig.

De fire oppføringene i velgeren, som skiller seg i størrelse, språkdekning og nøyaktighet:

  • Parakeet TDT 0.6B v3 — flerspråklig, anbefalt standard (~600 MB)
  • Parakeet TDT 0.6B v2 — engelsk (~480 MB)
  • Whisper large-v3-turbo — flerspråklig (~626 MB)
  • Whisper base.en — bare engelsk, den lille historiske standarden (~198 MB)

Modeller er de eneste artefaktene serveren henter under kjøring; hvert native bibliotek følger med i pakken.

Et møte tar opp to lydkanaler samtidig:

  • Du («me»): mikrofonen din.
  • De andre («them»): møtets lydutgang, fanget opp av en driverfri loopback — Core Audio-taps på prosess og enhet på macOS, WASAPI-loopback på Windows, en PipeWire-/PulseAudio-monitor på Linux.

Fordi de to kanalene fanges opp hver for seg, er transkriptet tilordnet talere fra starten: ordene dine merkes med me, alle andre i samtalen merkes med them.

Din egen stemme lekker fra systemutgangen tilbake til mikrofonen og ville ellers bli transkribert to ganger. To filtre hindrer det. AEC3 på signalnivå kjører ved hvert opptak i fjernmodus og er påkrevd — hvis det native AEC-biblioteket ikke kan lastes, nekter opptaket å starte i stedet for å strømme en ekkoforurenset mikrofon i stillhet. (I fysisk møte finnes det ingen referanse fra den andre enden å kansellere mot, så AEC er en uendret gjennomgang der.) På toppen av det kjører et tekstbasert ekkofilter på vertssiden på alle plattformer.

All mikrofonlydbehandling på OS-nivå er bevisst slått av. Slår du på plattformens egen ekkoutligning eller automatiske forsterkning på macOS, bytter mikrofonen til Voice Processing I/O, noe som i dette bygget slo ut både mikrofonen og systemlydtappen.

Mens du tar opp, dekodes lyden i rullende vinduer — kuttet ved en kort stillhet på slutten eller ved en maksimal vinduslengde — utenfor UI-tråden. Hvert vindu blir et transkriptsegment merket med taler og med forskyvninger i millisekunder.

Vinduer som aldri kom over en RMS-terskel, hoppes over uten å bli dekodet i det hele tatt, fordi en talemodell gjengir stillhet som hallusinerte ikke-tale-tokens, og dekodingen er bortkastet CPU. Den praktiske konsekvensen: en taler som er gjennomgående svært stille, gir ingen transkripsjon. Får noen tomt resultat, sjekk inngangsnivået deres før du gir modellen skylden.

Etter at du stopper, kjører diariseringen frakoblet over opptaket og deler fjernkanalen inn i enkelttalere (Person 1, Person 2, …) som du kan gi nytt navn. Antallet talere utledes fra en klyngeterskel, ikke fra et antall du angir — så det er et artefakt av terskelen, og en stille eller overlappende taler kan bli slått sammen med en nabo. Transkriptet gjengis som linjer av formen [mm:ss] SPEAKER: text.

Å gi en taler nytt navn gjør mer enn å merke ett transkript. Control Center kan lagre stemmeavtrykket til taleren som en stemmeprofil, slik at den gjenkjenner vedkommende automatisk i senere møter. Når du navngir en diarisert taler, blir du spurt om stemmeavtrykket skal lagres. Gjør du det, blandes det inn i et løpende sentroid for det navnet og matches mot nye talere med cosinuslikhet, slik at den samme personen dukker opp med navnet sitt neste gang uten at du merker dem på nytt.

Stemmeprofiler er knyttet til arbeidsområdet og krysser aldri grensen. Du administrerer dem under Innstillinger → Arbeidsområde → Møter. Gir du nytt navn til en taler som tidligere er lagret, meldes det gamle navnet ut, og du tilbys å melde inn det nye; sletter du en profil, fjernes det lagrede stemmeavtrykket, men navn som allerede er brukt på tidligere møter, beholdes intakt.

Når et opptak stopper, publiserer serveren en MeetingRecordingStopped domenehendelse. Den innebygde pipeline-malen meeting_summary utløses av den hendelsen. Opptakeren venter ikke på den; møtet går ganske enkelt gjennom livssyklusen for statusen sin:

recording → processing → done

Sammendragsagenten mottar tittelen, de grove live-notatene dine og transkriptet, og returnerer strukturert JSON. Hvilke seksjoner den skriver, formes av arbeidsområdets aktive mal for møtenotater (Innstillinger → Arbeidsområde → Møter); den aktive malen gjelder for nye sammendrag og for sammendrag som kjøres på nytt. Persisteringstrinnene i pipelinen skriver deretter denne JSON-en til enkelte rader:

  • enhancedNotes og summary → møtets notater
  • hvert tiltak → en MeetingActionItem-rad (innhold, eier, valgfri sakskobling)
  • hver beslutning → en MeetingDecision-rad

Tiltak og beslutninger trekkes aldri ut av frihåndsmarkdown, bare fra agentens strukturerte arrayer. Hvis en kjøring ikke gir strukturert utdata, hoppes persisteringstrinnene over, og det rå transkriptet beholdes som reserve, slik at du aldri mister oppføringen. Ingenting i pipelinen markerer møtet som done — det gjør en enkelt avstemmer, ut fra kjøringens avsluttende hendelse, slik at et søskentrinn som feiler, ikke kan etterlate et halvskrevet møte som allerede ser ferdig ut.

Flate Hva den viser
/meetings Listen over møter, med antall tiltak og beslutninger
/meetings/record HUD-en for det pågående opptaket: notatene dine på den ene siden, transkriptet som strømmer inn på den andre
/meetings/:meetingId Detaljvisningen for et møte: fanene Notater, Transkript, Tiltak og Beslutninger
Innstillinger → Arbeidsområde → Møter Notatmaler og lagrede stemmeprofiler for dette arbeidsområdet

Opptaket er driverfritt på alle tre skrivebordsplattformer (Core Audio-taps på macOS, WASAPI på Windows, PipeWire på Linux).

Nettklienten tar også opp, noe resten av denne sidens skrivebordsvinkling kan skjule: nettleseren henter mikrofonen din gjennom getUserMedia og møtelyden gjennom getDisplayMedia (skjermdeling), sampler ned til 16 kHz PCM16 og strømmer til den samme verten. Tre forbehold gjelder der:

  • Flaten som deles, må ha et lydspor. Safari, Firefox og fullskjermdeling på macOS gir ingen, og opptaket nekter å starte.
  • Det finnes ingen nativ AEC3. Nettleserens egen ekkoutligning forespørres for mikrofonen; det tekstbaserte ekkofilteret på vertssiden kjører fortsatt. HUD-en viser en måler for inngangsnivå drevet av PCM-en fra mikrofonen.
  • Å kjøre sammendraget på nytt og å avbryte behandlingen finnes bare på skrivebordet.

Kalenderhandlingen Start opptak og knytt finnes bare på skrivebordet og sier det rett ut i nettklienten, selv om møteskjermens egen opptaksflyt faktisk fungerer der.