การประชุมและการถอดเสียง
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 ของไมโครโฟน
- รันสรุปใหม่และยกเลิกการประมวลผลใช้ได้เฉพาะเดสก์ท็อป
การกระทำ เริ่มบันทึกและลิงก์ ของปฏิทินใช้ได้เฉพาะเดสก์ท็อป และรายงานตรงๆ บนเว็บว่าใช้ไม่ได้ แม้ว่ากระบวนการบันทึกของหน้าจอการประชุมเองจะทำงานได้ที่นั่น
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- ปฏิทินและการจัดตาราง: บันทึกการประชุมตรงจากเหตุการณ์ในปฏิทิน
- ไปป์ไลน์และระบบอัตโนมัติ: เอนจินที่อยู่เบื้องหลัง
meeting_summary - ตั๋วงานและการมอบหมาย: เชื่อมรายการดำเนินการของการประชุมกับตั๋วงาน
- เหตุการณ์โดเมน:
MeetingRecordingStoppedและMeetingStartingSoon - บันทึกและสรุปการประชุม