ข้ามไปยังเนื้อหา

การประชุมและการถอดเสียง

Control Center บันทึกการสนทนาและคืนบันทึกที่เรียบร้อยให้คุณได้ — สรุป รายการดำเนินการ และการตัดสินใจ — โดยที่การรู้จำเสียงพูดและการแยกผู้พูดทำงานบน ฮาร์ดแวร์ของคุณเอง ลองนึกถึง Granola แต่โฮสต์เองและเชื่อมเข้ากับเวิร์กสเปซ เดียวกับที่เอเจนต์ของคุณอยู่

การประชุม คือเซสชันที่บันทึกและถอดเสียงไว้ มัน ไม่ ใช่สิ่งเดียวกับ เหตุการณ์ในปฏิทิน: เหตุการณ์คือนัดหมายที่จัดตารางไว้ และซิงค์มาจาก Google ส่วนการประชุมคือสิ่งที่คุณบันทึกจริง ทั้งสองเชื่อมกันได้ เพราะคุณเริ่มบันทึกจากเหตุการณ์ได้ แต่ยังคงเป็นบันทึกคนละรายการ

การประชุมทุกครั้งผูกกับเวิร์กสเปซ เหมือนทุกอย่างอื่นใน Control Center การประชุมที่บันทึกในเวิร์กสเปซหนึ่งจะไม่ปรากฏในอีกเวิร์กสเปซเลย

“บนอุปกรณ์” เป็นสัญชาตญาณที่ถูกแต่ใช้คำผิด ไคลเอนต์เก็บเสียงและสตรีมเฟรม PCM16 16 kHz ไปยัง เครื่องที่รัน cc_server โฮสต์นั้นทำงานที่เหลือทั้งหมด: เขียนไฟล์ WAV แยกช่องสัญญาณไว้ใต้ <dataDir>/meetings/<meetingId>/ ถอดเสียงใน worker isolate กรองเสียงสะท้อน และแยกผู้พูดย้อนหลัง บนเดสก์ท็อปแบบสแตนด์อโลน โฮสต์นั้นคือเครื่องเดียวกัน เมื่อชี้ไปที่เซิร์ฟเวอร์ระยะไกล ก็ไม่ใช่ — ดังนั้น “ไม่มีอะไรออกจากแล็ปท็อปของฉัน” จึงจริงเฉพาะเมื่อเซิร์ฟเวอร์คือแล็ปท็อปของคุณ

ยังมีข้อยกเว้นอีกข้อหนึ่ง และมันคือข้อสำคัญ

ทุกอย่างก่อนขั้นตอนสรุป — การเก็บเสียง การถอดเสียง การตัดเสียงสะท้อน การแยกผู้พูด การจับคู่ลายเสียง — ทำงานบนเซิร์ฟเวอร์โดยไม่มีการเรียกผ่านเครือข่าย

โมเดล การฝังตัว การแยกผู้พูด และการพูด (ASR) ถูกบังคับติดตั้งตอนบูตครั้งแรก (ข้ามในโหมดเดโม) การแยกผู้พูดและการบันทึกจึงพร้อมใช้โดยไม่ต้องเข้าไปตั้งค่าใดๆ ASR ยังคง เลือกได้ — มีขนาดหลายร้อยเมกะไบต์ และมีสี่บิลด์ในตัวเลือก การพูดยังต้องรีสตาร์ตหนึ่งครั้งหลังดาวน์โหลดครั้งแรก เพราะตัวถอดเสียงแปลง โมเดลของมันก่อนที่การดึงข้อมูลจะเสร็จ

สี่รายการในตัวเลือก ซึ่งต่างกันที่ขนาด ความครอบคลุมภาษา และความแม่นยำ:

  • 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)

โมเดลเป็นอาร์ติแฟกต์เดียวที่เซิร์ฟเวอร์ดึงมาตอนรันไทม์ ไลบรารีเนทีฟทุกตัว มาพร้อมในบันเดิล

การประชุมบันทึก สองช่องสัญญาณเสียงพร้อมกัน:

  • คุณ (“me”): ไมโครโฟนของคุณ
  • ฝ่ายอื่น (“them”): เอาต์พุตเสียงของการประชุม เก็บผ่านลูปแบ็กที่ไม่ต้องใช้ ไดรเวอร์ — Core Audio process/device taps บน macOS, WASAPI loopback บน Windows, มอนิเตอร์ PipeWire / PulseAudio บน Linux

เนื่องจากสองช่องสัญญาณถูกเก็บแยกกัน ทรานสคริปต์จึงระบุผู้พูดได้ตั้งแต่ต้น คำของคุณถูกติดแท็ก me ทุกคนในสายถูกติดแท็ก them

เสียงของคุณเองรั่วจากเอาต์พุตระบบกลับเข้าไมโครโฟน และถ้าไม่จัดการก็จะถูกถอดเสียง ซ้ำสองครั้ง ตัวกรองสองชั้นหยุดเรื่องนี้ AEC3 ระดับสัญญาณทำงานกับการบันทึก โหมดระยะไกลทุกครั้งและเป็นสิ่งที่จำเป็น — หากไลบรารี AEC เนทีฟโหลดไม่ได้ การบันทึกจะปฏิเสธที่จะเริ่ม แทนที่จะสตรีมไมโครโฟนที่ปนเสียงสะท้อนอย่างเงียบๆ (โหมดพบปะกันต่อหน้าไม่มีสัญญาณปลายไกลให้ตัดออก AEC จึงเป็นทางผ่านเฉยๆ ในโหมดนั้น) เหนือจากนั้น ตัวกรองเสียงสะท้อนระดับข้อความฝั่งโฮสต์ยังทำงานบนทุกแพลตฟอร์ม

การประมวลผลไมโครโฟนระดับ OS ทั้งหมดถูกปิดโดยเจตนา การเปิดการตัดเสียงสะท้อน หรือออโต้เกนของแพลตฟอร์มเองบน macOS จะสลับไมโครโฟนไปเป็น Voice Processing I/O ซึ่งในบิลด์นี้ทำให้ทั้งไมโครโฟน และ ตัวดักเก็บเสียงระบบใช้ไม่ได้

ขณะที่คุณบันทึก เสียงจะถูกถอดรหัสเป็น หน้าต่างแบบเลื่อน — ตัดเมื่อมีช่วงเงียบ สั้นๆ ต่อท้าย หรือเมื่อถึงความยาวหน้าต่างสูงสุด — โดยไม่ใช้เธรด UI แต่ละหน้าต่าง กลายเป็นส่วนของทรานสคริปต์ที่ติดแท็กผู้พูด พร้อมออฟเซตระดับมิลลิวินาที

หน้าต่างที่ไม่เคยสูงเกินเกณฑ์ RMS จะถูกข้าม โดยไม่ถอดรหัสเลย เพราะโมเดล การพูดจะแสดงความเงียบออกมาเป็นโทเคนที่ไม่ใช่คำพูดแบบหลอนขึ้นมา และการถอดรหัส ก็เสีย CPU เปล่า ผลในทางปฏิบัติ: ผู้พูดที่เบามากสม่ำเสมอจะไม่เกิดทรานสคริปต์เลย หากมีใครได้ผลลัพธ์ว่างเปล่า ให้ตรวจระดับอินพุตของเขาก่อนจะโทษโมเดล

หลังจากคุณหยุด การแยกผู้พูด จะทำงานแบบออฟไลน์บนไฟล์บันทึก และแยกช่องสัญญาณ ระยะไกลออกเป็นผู้พูดแต่ละคน (Person 1, Person 2, …) ที่คุณเปลี่ยนชื่อได้ จำนวนผู้พูดอนุมานจากเกณฑ์การจัดกลุ่ม ไม่ใช่จากจำนวนที่คุณกำหนด — จึงเป็นผลจาก เกณฑ์ และผู้พูดที่เบาหรือพูดทับซ้อนอาจถูกรวมเข้ากับคนข้างเคียง ทรานสคริปต์ถูก แสดงเป็นบรรทัด [mm:ss] SPEAKER: text

การเปลี่ยนชื่อผู้พูดทำได้มากกว่าติดป้ายให้ทรานสคริปต์ครั้งเดียว Control Center บันทึกลายเสียงของผู้พูดเป็น โปรไฟล์เสียง ได้ จึงจดจำพวกเขาโดยอัตโนมัติใน การประชุมครั้งหน้า เมื่อคุณตั้งชื่อผู้พูดที่แยกไว้ ระบบจะถามว่าต้องการบันทึก ลายเสียงหรือไม่ หากบันทึก มันจะถูกผสมเข้าเป็นเซนทรอยด์ที่สะสมต่อเนื่องสำหรับ ชื่อนั้น และจับคู่กับผู้พูดใหม่ด้วยความคล้ายโคไซน์ คนเดิมจึงปรากฏพร้อมชื่อของเขา ในครั้งถัดไปโดยที่คุณไม่ต้องติดป้ายใหม่

โปรไฟล์เสียงผูกกับเวิร์กสเปซและไม่ข้ามขอบเขตเลย จัดการได้ที่ การตั้งค่า → เวิร์กสเปซ → การประชุม การเปลี่ยนชื่อผู้พูดที่เคยบันทึกไว้จะ ถอนการลงทะเบียนชื่อเก่าและเสนอให้ลงทะเบียนชื่อใหม่ ส่วนการลบโปรไฟล์จะลบ ลายเสียงที่เก็บไว้ แต่ชื่อที่ใช้กับการประชุมที่ผ่านมาแล้วยังคงอยู่

เมื่อการบันทึกหยุด เซิร์ฟเวอร์จะเผยแพร่เหตุการณ์โดเมน MeetingRecordingStopped เทมเพลตไปป์ไลน์ meeting_summary ในตัวจะถูก ทริกเกอร์โดยเหตุการณ์นั้น ตัวบันทึกไม่รอผลลัพธ์ การประชุมแค่เปลี่ยนสถานะ ตามวงจรชีวิตของมัน:

recording → processing → done

เอเจนต์สรุปจะได้รับชื่อเรื่อง โน้ตสดคร่าวๆ ของคุณ และทรานสคริปต์ แล้วคืน JSON แบบมีโครงสร้าง ว่าจะเขียนส่วนใดบ้างนั้นขึ้นอยู่กับ เทมเพลตบันทึก การประชุมที่ใช้งานอยู่ ของเวิร์กสเปซ (การตั้งค่า → เวิร์กสเปซ → การประชุม) เทมเพลตที่ใช้งานมีผลกับสรุปใหม่และสรุปที่รันใหม่ จากนั้นขั้นตอน persist ของ ไปป์ไลน์จะเขียน JSON นั้นลงเป็นแถวแยกกัน:

  • enhancedNotes และ summary → โน้ตของการประชุม
  • รายการดำเนินการแต่ละรายการ → แถว MeetingActionItem (เนื้อหา ผู้รับผิดชอบ ลิงก์ตั๋วงานแบบไม่บังคับ)
  • การตัดสินใจแต่ละรายการ → แถว MeetingDecision

รายการดำเนินการและการตัดสินใจ ไม่เคย ถูกแกะออกจากมาร์กดาวน์อิสระ แต่มาจาก อาร์เรย์แบบมีโครงสร้างของเอเจนต์เท่านั้น หากการรันไม่ให้เอาต์พุตแบบมีโครงสร้าง ขั้นตอน persist จะถูกข้ามและทรานสคริปต์ดิบจะถูกเก็บไว้เป็นทางเลือกสำรอง คุณจึงไม่สูญเสียบันทึก ไม่มีอะไรในไปป์ไลน์ที่ทำเครื่องหมายการประชุมว่า done — ตัวประสานตัวเดียวทำหน้าที่นั้นจากเหตุการณ์สิ้นสุดของการรัน ขั้นตอนพี่น้องที่ล้มเหลวจึงทิ้งการประชุมที่เขียนค้างไว้ซึ่งดูเหมือนเสร็จแล้วไม่ได้

พื้นผิว สิ่งที่แสดง
/meetings รายการการประชุม พร้อมจำนวนรายการดำเนินการและการตัดสินใจ
/meetings/record HUD การบันทึกสด: โน้ตของคุณด้านหนึ่ง ทรานสคริปต์ที่สตรีมอยู่อีกด้านหนึ่ง
/meetings/:meetingId รายละเอียดของการประชุม: แท็บโน้ต ทรานสคริปต์ รายการดำเนินการ และการตัดสินใจ
การตั้งค่า → เวิร์กสเปซ → การประชุม เทมเพลตบันทึกและโปรไฟล์เสียงที่บันทึกไว้สำหรับเวิร์กสเปซนี้

การเก็บเสียงไม่ต้องใช้ไดรเวอร์บนแพลตฟอร์มเดสก์ท็อปทั้งสาม (Core Audio taps บน macOS, WASAPI บน Windows, PipeWire บน Linux)

ไคลเอนต์เว็บบันทึกได้ด้วย ซึ่งกรอบแบบเดสก์ท็อปของหน้านี้ในส่วนที่เหลือ อาจทำให้มองไม่เห็น: เบราว์เซอร์รับไมโครโฟนของคุณผ่าน getUserMedia และเสียง ของการประชุมผ่าน getDisplayMedia (แชร์หน้าจอ) ดาวน์แซมเปิลเป็น PCM16 16 kHz แล้วสตรีมไปยังโฮสต์เดียวกัน มีข้อควรระวังสามข้อตรงนั้น:

  • พื้นผิวที่แชร์ ต้อง มีแทร็กเสียง Safari, Firefox และการแชร์เต็มจอของ macOS ไม่มีแทร็กเสียง และการบันทึกจะปฏิเสธที่จะเริ่ม
  • ไม่มี AEC3 เนทีฟ มีการขอใช้การตัดเสียงสะท้อนของเบราว์เซอร์เองบนไมโครโฟน ส่วนตัวกรองเสียงสะท้อนระดับข้อความฝั่งโฮสต์ยังทำงานอยู่ HUD แสดงมาตรวัด ระดับอินพุตที่ขับจาก PCM ของไมโครโฟน
  • รันสรุปใหม่และยกเลิกการประมวลผลใช้ได้เฉพาะเดสก์ท็อป

การกระทำ เริ่มบันทึกและลิงก์ ของปฏิทินใช้ได้เฉพาะเดสก์ท็อป และรายงานตรงๆ บนเว็บว่าใช้ไม่ได้ แม้ว่ากระบวนการบันทึกของหน้าจอการประชุมเองจะทำงานได้ที่นั่น