Câu chuyện về người Thư ký AI — Meeting Minutes *, *::before, *::after { box-sizing: border-box; } body { margin: 0; background: #f9f8f6; color: #1c1c1e; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; font-size: 17px; line-height: 1.75; } /* ── Hero ── */ .hero { background: linear-gradient(135deg, #0f2027, #203a43, #2c5364); color: #fff !important; padding: 72px 24px 60px; text-align: center; } .hero .kicker { display: inline-block; background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.25); border-radius: 100px; font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase; padding: 4px 14px; margin-bottom: 20px; color: #fff !important; } .hero h1, .hero h1 * { font-size: clamp(1.8rem, 5vw, 3rem); font-weight: 800; margin: 0 0 16px; line-height: 1.2; color: #fff !important; } .hero .sub { max-width: 660px; margin: 0 auto; color: rgba(255,255,255,0.75) !important; font-size: 1rem; } /* ── Page layout: sidebar + article ── */ .page-layout { display: grid; grid-template-columns: 240px minmax(0, 750px); max-width: 1020px; margin: 0 auto; align-items: start; padding: 0 24px; } @media (max-width: 860px) { .page-layout { grid-template-columns: 1fr; padding: 0; } } /* ── TOC Sidebar ── */ .toc-sidebar { position: sticky; top: 32px; padding: 48px 20px 48px 0; align-self: start; } @media (max-width: 860px) { .toc-sidebar { display: none; } } .toc-label { font-size: 10px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: #999; margin-bottom: 12px; } .toc-list { list-style: none; padding: 0; margin: 0; } .toc-list li { margin-bottom: 2px; } .toc-list a { display: block; font-size: 0.85rem; color: #888; text-decoration: none; padding: 5px 10px 5px 12px; border-left: 2px solid transparent; border-radius: 0 4px 4px 0; transition: color 0.15s, border-color 0.15s, background 0.15s; line-height: 1.35; } .toc-list a:hover { color: #1c1c1e; background: rgba(0,0,0,0.04); } .toc-list a.active { color: #0077cc; border-left-color: #0077cc; font-weight: 600; background: rgba(0,119,204,0.06); } .toc-num { display: inline-block; font-size: 9px; font-weight: 700; letter-spacing: 0.5px; color: #bbb; margin-right: 4px; vertical-align: middle; } .toc-list a.active .toc-num { color: #0077cc; } /* ── Article layout ── */ article { padding: 48px 24px 80px; min-width: 0; } /* ── Chapter divider ── */ .chapter { display: flex; align-items: center; gap: 12px; margin: 56px 0 20px; } .chapter:first-child { margin-top: 0; } .chapter-num { background: #1c1c1e; color: #fff; font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; padding: 4px 10px; border-radius: 4px; white-space: nowrap; } .chapter-line { flex: 1; height: 1px; background: #e0ddd8; } .chapter h2 { font-size: 1.5rem; font-weight: 700; margin: 0; } h2.section-title { font-size: 1.5rem; font-weight: 700; margin: 0 0 20px; color: #1c1c1e; } h3 { font-size: 1.1rem; font-weight: 700; margin: 32px 0 8px; color: #1c1c1e; } p { margin: 0 0 1.1em; } /* ── Scene / pull-quote ── */ .scene { background: #fff; border-left: 4px solid #ff9500; border-radius: 0 8px 8px 0; padding: 20px 24px; margin: 28px 0; font-style: italic; color: #444; font-size: 1.05rem; } .callout { background: #fff3cd; border-left: 4px solid #f5a623; border-radius: 0 8px 8px 0; padding: 16px 20px; margin: 24px 0; font-size: 0.95rem; color: #5a4000; } .callout strong { color: #3a2800; } .insight { background: #eaf4ff; border-left: 4px solid #0077cc; border-radius: 0 8px 8px 0; padding: 16px 20px; margin: 24px 0; font-size: 0.95rem; color: #003a66; } /* ── Code block ── */ pre { background: #1e1e2e; color: #cdd6f4; border-radius: 8px; padding: 18px 20px; overflow-x: auto; font-size: 0.85rem; line-height: 1.6; margin: 20px 0; } code { font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; } p code, li code { background: #f0ede8; padding: 2px 6px; border-radius: 4px; font-size: 0.88em; color: #c0392b; } /* ── Mode cards ── */ .mode-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 24px 0; } @media (max-width: 520px) { .mode-cards { grid-template-columns: 1fr; } } .mode-card { background: #fff; border: 1px solid #e0ddd8; border-radius: 10px; padding: 20px; } .mode-card .icon-header { font-size: 1.8rem; margin-bottom: 12px; } .mode-card h4 { margin: 0 0 8px; font-size: 1rem; color: #1c1c1e;} .mode-card p { margin: 0; font-size: 0.88rem; color: #555; } /* ── Finding card ── */ .finding { background: #fff; border: 1px solid #e8e4de; border-radius: 10px; padding: 24px 24px 20px; margin: 28px 0; } .finding h4 { font-size: 1.05rem; font-weight: 700; margin: 0 0 10px; color: #1a6fa8; } .finding p { margin: 0; font-size: 0.95rem; color: #444; } .finding-tag { display: inline-block; margin-bottom: 10px; border-radius: 999px; padding: 3px 9px; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase; } .tag-high { background: #ffe8e5; color: #a32714; } .tag-insight { background: #eaf4ff; color: #005fa3; } .tag-note { background: #f0ede8; color: #5a4a36; } /* ── Mock minutes output ── */ .minutes-preview { overflow: hidden; background: #fff; border: 1px solid #d9e1eb; border-radius: 10px; box-shadow: 0 14px 38px rgba(25,48,80,0.10); margin: 28px 0; } .preview-hero { background: linear-gradient(120deg, #193050, #155f7a 62%, #097b74); color: #fff; padding: 24px; } .preview-eyebrow { font-size: 0.72rem; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; color: rgba(255,255,255,0.72); margin-bottom: 8px; } .preview-hero h3 { color: #fff; font-size: 1.35rem; line-height: 1.25; margin: 0 0 8px; } .preview-hero p { color: rgba(255,255,255,0.76); font-size: 0.92rem; margin: 0; } .preview-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; padding: 14px; background: #f5f7fa; } @media (max-width: 640px) { .preview-metrics { grid-template-columns: 1fr 1fr; } } .preview-metric { background: #fff; border: 1px solid #d9e1eb; border-radius: 8px; padding: 12px; } .preview-metric span { display: block; color: #627084; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; } .preview-metric strong { display: block; color: #193050; font-size: 1.25rem; line-height: 1.1; margin-top: 4px; } .preview-body { display: grid; gap: 14px; padding: 16px; } .preview-panel { border: 1px solid #e2e9f1; border-radius: 8px; padding: 16px; background: #fbfcfe; } .preview-panel h4 { color: #193050; font-size: 1rem; margin: 0 0 10px; } .preview-panel ol, .preview-panel ul { margin-bottom: 0; } .preview-table { width: 100%; border-collapse: collapse; overflow-wrap: anywhere; font-size: 0.86rem; } .preview-table th, .preview-table td { border-bottom: 1px solid #e2e9f1; padding: 9px 8px; text-align: left; vertical-align: top; } .preview-table th { color: #627084; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.5px; } .preview-table tr.high td { background: #fff4f2; } .priority-pill { display: inline-block; border-radius: 999px; padding: 2px 8px; background: #ffe1dc; color: #a32714; font-weight: 800; } .source-note { border-top: 1px solid #e2e9f1; color: #627084; font-size: 0.82rem; padding: 12px 16px 16px; background: #fff; } /* ── Image ── */ .story-img { width: 100%; border-radius: 10px; margin: 28px 0; box-shadow: 0 4px 24px rgba(0,0,0,0.12); } .img-caption { text-align: center; font-size: 0.82rem; color: #888; margin: -18px 0 28px; } /* ── CTA / Start block ── */ .cta-block { background: linear-gradient(135deg, #0f2027, #2c5364); color: #fff; border-radius: 12px; padding: 36px 28px; margin: 48px 0 0; text-align: center; } .cta-block h2 { margin: 0 0 8px; font-size: 1.4rem; } .cta-block p { color: rgba(255,255,255,0.75); margin: 0 0 20px; font-size: 0.95rem; } .cta-button { display: inline-block; background: #0077cc; color: #fff; text-decoration: none; font-weight: 700; padding: 12px 24px; border-radius: 8px; margin-top: 10px; transition: background 0.2s; } .cta-button:hover { background: #005fa3; } ul, ol { padding-left: 1.4rem; margin: 0 0 1em; } li { margin-bottom: 4px; } strong { font-weight: 700; } em { font-style: italic; } hr.divider { border: none; border-top: 1px solid #e0ddd8; margin: 40px 0; } .workflow-title { margin-top: 40px; color: #1a6fa8; } .closing-quote { text-align: center; font-style: italic; color: #666; font-size: 1.1rem; margin-top: 40px; } document.addEventListener('DOMContentLoaded', () => { const observer = new IntersectionObserver(entries => { entries.forEach(entry => { const id = entry.target.getAttribute('id'); if (entry.intersectionRatio > 0) { document.querySelectorAll(`.toc-list a`).forEach(a => a.classList.remove('active')); document.querySelector(`.toc-list a[href="#${id}"]`)?.classList.add('active'); } }); }, { rootMargin: '0px 0px -80% 0px' }); document.querySelectorAll('section[id]').forEach(section => { observer.observe(section); }); }); Meeting Minutes Assistant · Câu chuyện thực tế Một Action Item bị bỏ quên, nỗi khổ của Salesvà giải pháp từ người "Thư ký AI" mẫn cán Từ những cuộc họp khách hàng không được ghi chép đầy đủ — đến ý tưởng dùng AI làm thư ký chuyên nghiệp — đến những giá trị bất ngờ trong việc quản lý dự án, giải phóng sức lao động cho Sales và nâng cao uy tín với khách hàng. Mục lục 01Khách hàng hỏi: "Task đó đến đâu rồi?" 02Nỗi khổ của Sales: "Nút thắt cổ chai" 03Không phải lỗi người 04Khai sinh "Thư ký AI" 05Thư ký AI làm được gì? 06Quy trình mới 07Output HTML minutes 08Những giá trị vô hình Chương 1 Khách hàng hỏi: "Task đó đến đâu rồi?" nhưng không ai nhớ deadline Đó là một buổi sáng thứ Hai bình thường của đội Sản xuất (Production). Mọi người vừa bắt đầu tuần mới thì khách hàng nhắn tin hỏi tiến độ của một task quan trọng. Cả team ngớ người. Rõ ràng trong buổi họp dài 2 tiếng chiều thứ Sáu tuần trước, hai bên đã thảo luận sôi nổi và thống nhất về task này. Nhưng... deadline chính xác là ngày nào? Ai là người chịu trách nhiệm chính (PIC)? Người thì nhớ mang máng là "trong tuần này", người lại bảo "hình như khách nói không gấp". Mở folder dự án tìm file Biên bản cuộc họp (Meeting Minutes)... một sự thật phũ phàng: Không có file nào cả. Buổi họp hôm đó quá căng thẳng, ai cũng mải mê nghe, mải trình bày màn hình, trả lời câu hỏi của khách, không một ai kịp "take note" đàng hoàng. "Hôm đó họp cuốn quá, anh tưởng em ghi chép rồi?" Cả team "chết lặng" vì không ai nhớ được deadline của một task quan trọng. Kết quả: Team phải email hỏi lại khách hàng một cách khéo léo để confirm. Khách hàng dù trả lời nhưng chắc chắn sẽ có chút cấn cá vì cảm thấy chúng ta thiếu sự chuyên nghiệp và sát sao. Chương 2 Nỗi khổ của Sales: "Nút thắt cổ chai" mang tên Meeting Minutes Câu chuyện không chỉ dừng lại ở đội Sản xuất. Nhìn sang đội ngũ Sales (Kinh doanh), vấn đề còn nhức nhối hơn nhiều. Một ngày của Sales là chuỗi những cuộc họp liên tiếp với các khách hàng khác nhau. Họp để chốt requirement, họp để lấy ý kiến phản hồi, họp để cross-sell/up-sell. Khổ nỗi, sau mỗi cuộc họp, Sales phải "đóng vai" người phiên dịch và truyền đạt lại (transfer) toàn bộ ngữ cảnh, yêu cầu của khách hàng về cho đội Sản xuất. Việc ngồi gõ lại một biên bản họp (Meeting Minutes) đầy đủ, chính xác tiêu tốn của Sales hàng giờ đồng hồ mỗi ngày. Nếu ghi ngắn gọn quá: Đội Sản xuất không hiểu bối cảnh (context), làm sai ý khách. Nếu không ghi: Thông tin bị rơi rụng, những "sắc thái kinh doanh" (business nuance), mối lo ngại (concern) ẩn ý của khách hàng rất dễ mất đi khi truyền đạt miệng. Sales rơi vào tình thế tiến thoái lưỡng nan: Dành thời gian gõ biên bản thì không còn thời gian đi tìm khách hàng mới. Nhưng truyền đạt không kỹ thì Sản xuất làm sai, cuối cùng Sales lại là người phải đi xin lỗi khách hàng. Việc ghi biên bản trở thành một công việc cực kỳ tốn thời gian mà lại không mang lại hiệu quả truyền đạt cao. Một ngày "kinh hoàng" của Sales khi phải liên tục họp và take note thủ công. Chương 3 Không phải lỗi người — là giới hạn của việc vừa họp vừa ghi chép Chúng tôi ngồi lại nhìn nhận sự cố. Không ai muốn đổ lỗi cho ai, vì thực tế: Vấn đề là: Trong một cuộc họp quan trọng (nhất là với khách hàng Nhật), bạn phải tập trung 100% để nghe hiểu, phân tích logic business, suy nghĩ giải pháp và giao tiếp. Việc đòi hỏi một người (dù là Dev, PM hay Sales) vừa làm tốt ngần ấy việc, vừa đóng vai trò thư ký ghi chép chi tiết, không sót chữ nào là điều gần như bất khả thi. Vậy giải pháp là gì? Cử thêm một người chỉ để ngồi dự thính và ghi biên bản? Lãng phí resource, và chưa chắc người đó đã hiểu hết context kỹ thuật để ghi chính xác. Chúng tôi nhận ra: Hầu hết các cuộc họp đều được Record (ghi âm/ghi hình) lại. Tại sao chúng ta không dùng AI để nghe lại và làm thư ký? Từ suy nghĩ đó, ý tưởng được hiện thực hóa — và Skill meeting-minutes-from-recording ra đời. Chương 4 Khai sinh "Thư ký AI" chuyên nghiệp Mục tiêu của chúng tôi không chỉ là làm ra một công cụ "Speech-to-Text" (chuyển giọng nói thành văn bản) đơn thuần. Một file text dài ngoằng hàng ngàn chữ không có giá trị quản lý. Mục tiêu là tạo ra một Biên bản cuộc họp đạt chuẩn "Account-ready" — chuyên nghiệp, sạch sẽ, đủ cấu trúc để Sales/PM review nhanh trước khi gửi khách hàng, và là cầu nối thông tin đáng tin cậy giữa Sales và Sản xuất. Điểm hay nhất của "Thư ký AI" không nằm ở việc chuyển audio thành text. Nếu chỉ có transcript, ta mới biết ai đã nói gì. Nhưng trong meeting khách hàng, rất nhiều quyết định thật sự lại nằm trên màn hình: một con số trong bảng giá, một dòng highlight trên slide, một trạng thái ticket, một timeline bị kéo qua rất nhanh, hoặc câu "phần này như trên màn hình" mà transcript không thể tự giải thích. Vì vậy, AI không chỉ "nghe" cuộc họp. Nó còn bóc tách các frame quan trọng từ video, soi context trên màn hình, đối chiếu lời nói với thứ đang được share, phân biệt tài liệu khách hàng đưa ra với tài liệu nội bộ, rồi mới tổng hợp thành biên bản có bằng chứng. Khác biệt nằm ở bằng chứng: Audio giúp ghi lại lời nói; hình ảnh giúp xác thực điều mọi người đang cùng nhìn vào. Khi hai nguồn này được đối chiếu, biên bản không còn là "transcript được viết lại cho đẹp", mà trở thành một tài liệu quản lý có thể trace lại. AI tự động phân tích âm thanh, trích xuất frame từ video, đối chiếu màn hình share và chuyển đổi thành tài liệu chuẩn chỉnh. Chương 5 Thư ký AI này làm được những gì? Không chỉ là ghi chép, "Thư ký AI" được trang bị bộ kỹ năng (Skill) cực kỳ mạnh mẽ: 🔒 Bóc băng chính xác & kiểm soát dữ liệu Tự động trích xuất âm thanh từ file video/audio (mp4, m4a, wav...), ưu tiên xử lý local khi có thể để giảm rủi ro lộ dữ liệu. Hỗ trợ các cuộc họp Nhật - Việt - Anh và luôn ghi chú khi transcript có điểm chưa chắc chắn. 🧠 Phân tách ngữ cảnh thông minh Nhận biết được đâu là "bằng chứng/lời nói từ cuộc họp", đâu là "tài liệu nội bộ", và đâu là "tài liệu khách hàng chia sẻ". Tránh nhầm lẫn thông tin. 🖼️ Bóc tách hình ảnh từ video Tự động lấy representative frames/contact sheet từ video để xác thực nội dung được share trên màn hình: slide, bảng giá, ticket list, backlog, timeline, số liệu hoặc trạng thái UI. Đây là phần giúp AI hiểu được những câu như "chốt theo phương án này", "deadline như trên bảng", hoặc "scope nằm ở dòng này". 🎯 Truy vết Quyết định & Action Items Tự động nhặt ra các quyết định, rủi ro, và Action Items. Nếu một task chưa chốt deadline rõ ràng, AI đề xuất deadline suy luận (inferred) và đánh dấu cẩn thận để team confirm lại. 📊 Báo cáo chuẩn Executive Output không phải text khô khan. AI tự động sinh ra file HTML chuẩn format: Layout dashboard, section gập/mở gọn gàng, và tự động bôi đỏ những Action Item mang tính "High Priority". Chương 6 Quy trình mới: Đơn giản đến bất ngờ Bây giờ, nỗi ám ảnh mang tên "Viết Meeting Minutes" nhẹ đi rất nhiều. Sau mỗi cuộc họp, quy trình của chúng tôi chỉ gói gọn trong vài thao tác: Step 1: Kéo thả file ghi âm/video (mp4, m4a...) vào thư mục. Step 2: Gõ lệnh yêu cầu AI: "Hãy viết meeting minutes cho file recording này". Step 3: AI tách audio để transcribe, đồng thời trích frame/contact sheet từ video. Step 4: AI đối chiếu lời nói với nội dung share trên màn hình. Step 5: Trở lại bàn làm việc và nhận một file HTML Meeting Minutes chi tiết. Step 6: Review các điểm inferred/uncertain, rồi gửi khách hàng hoặc forward cho Sản xuất. 3 Workflow (Use case) ứng dụng thực tế hiệu quả: Use case 1: Họp qua MS Teams có tích hợp sẵn Thao tác: Bật tính năng Recording có sẵn trên MS Teams ngay khi bắt đầu họp. Đầu vào: Sau cuộc họp, tải file Video (.mp4) và Transcript (.vtt) từ Teams về máy. Thực thi: Gọi Skill trên AI Assistant để xử lý 2 file này. Kết quả: Nhận file HTML Meeting Minutes đẹp, có cấu trúc rõ và đáng tin cậy hơn nhờ có transcript chất lượng cao, đồng thời có frame video để xác thực các slide/bảng được share. Use case 2: Họp trên nền tảng khác / Khách hàng không cho phép Record Thao tác: Sử dụng công cụ Meeting Master nội bộ của công ty để vừa hiển thị dịch live (translation) vừa bóc băng (transcript) trực tiếp. Đầu vào: Tải script/text thô từ Meeting Master về máy tính sau cuộc họp. Thực thi: Cung cấp script đó cho AI và gọi Skill để xử lý. Kết quả: Biên bản họp đầy đủ Action Items được tự động tổng hợp chuẩn format từ bản nháp thô. Use case 3: Workflow chắc tay với OBS + Meeting Master (Dành cho trường hợp họp bảo mật, không dùng được công cụ Record của hệ thống nhưng team vẫn cần giữ lại context hình ảnh) Thao tác: Bật phần mềm OBS Studio (Open source, miễn phí và rất mạnh mẽ) trên máy cá nhân để chủ động quay lại màn hình và âm thanh. Đồng thời bật Meeting Master để lấy script dự phòng. Đầu vào: Lấy file Video từ OBS kết hợp với Script từ Meeting Master. Thực thi: Đẩy cả video và script vào AI Assistant + Skill; AI trích các frame đại diện để kiểm tra màn hình share. Kết quả: Có thêm bằng chứng hình ảnh để đối chiếu slide khách hàng share và giảm mạnh rủi ro bỏ sót sắc thái kinh doanh. Đây là workflow phù hợp khi cuộc họp có nhiều context trên màn hình. Chương 7 Một output HTML minutes trông như thế nào? Nói "AI tạo Meeting Minutes" thì nghe vẫn hơi trừu tượng. Giá trị thật nằm ở chỗ: sau cuộc họp, team nhận được một dossier có thể đọc trong vài phút, nhìn thấy ngay quyết định, action items, rủi ro, buying signals và các điểm cần confirm. Dưới đây là một mô phỏng đã ẩn danh, lấy cảm hứng từ format biên bản thực tế. Tên khách hàng, dự án, người tham dự, file nội bộ và số liệu nhạy cảm đã được thay bằng nhãn trung tính. Ẩn danh · Meeting Dossier Meeting: Khách hàng A - Review phương án dịch vụ, ROI material và feedback hearing - YYYY-MM-DD Generated from recording, transcript và các frame màn hình đã đối chiếu. Nội dung này là bản nháp account-ready để PM/Sales review trước khi gửi hoặc forward nội bộ. Duration58m Decisions8 Action Items7 High Priority3 Frames Checked12 Executive Snapshot Hai bên thống nhất dùng POC để kiểm chứng giả định về scope, effort và ticket definition trước khi chốt mô hình production. Khách hàng phản ứng tích cực với hướng dịch vụ, nhưng decision maker cần ROI rõ và tài liệu giải thích dễ hiểu hơn. Monthly report được xem là điểm tạo giá trị: không chỉ báo cáo ticket, mà còn chỉ ra bottleneck và improvement proposal. Focus For Next Review Chốt entry plan cho POC để khách hàng dễ ra quyết định. Làm rõ phần monitoring: phạm vi, thời gian phản hồi, giới hạn ngoài support time. Polish ROI material thành bản customer-facing, tránh dùng số liệu chưa kiểm chứng nguồn. Visual Evidence From Recording Frame 00:03:40 xác nhận bảng phương án A/B/C được share trên màn hình, trong đó phương án B được đánh dấu recommended. Frame 00:18:30 xác nhận cấu trúc monthly report gồm ticket trend, bottleneck và improvement proposal. Frame 00:31:00 xác nhận số liệu ROI trên slide là draft, cần kiểm tra nguồn trước khi dùng customer-facing. Quyết định # Quyết định Ảnh hưởng 1 POC sẽ dùng để refine ticket definition và scope boundary. POC operation, proposal 2 Monthly report là deliverable customer-facing, không phải ghi chú nội bộ. Service menu, communication 3 Phần tư vấn/dedicated operation cần tách khỏi standard package để tránh scope creep. Pricing, contract expectation Action Items Action Item Owner Deadline Priority Status Gửi lại tài liệu dịch vụ và ROI đã trình bày trong meeting. Sales/PM Sau meeting Cao Đang thực hiện Bổ sung entry plan POC và mô tả rõ monitoring scope. Production Lead Trước review tiếp theo; inferred Cao Chưa xử lý Review nội bộ tài liệu và phản hồi comment/câu hỏi. Khách hàng A Tuần sau; inferred Trung bình Chưa xử lý Insights & Observations 温度感: tích cực nhưng thực tế; khách hàng không hỏi "có cần không" nữa, mà chuyển sang "bán thế nào, ngân sách nào, scope nào". Buying signal: pain vận hành đã rõ ở người phụ trách trực tiếp; ROI là chìa khóa để thuyết phục decision maker. Risk: nếu không tách rõ standard support và consulting/add-on, scope có thể phình ra sau POC. Source được ghi rõ nhưng đã ẩn danh: Teams VTT, recording, cleaned transcript, representative frames/contact sheet. Các deadline ghi "inferred" là suy luận vận hành, không phải cam kết chính thức nếu meeting chưa nói rõ. Insight Không chỉ ghi lại lời nói, mà biến cuộc họp thành dữ liệu quản lý Một meeting dài gần một giờ được nén thành snapshot, quyết định, action items và risk/opportunity. Sales nhìn thấy điểm cần follow-up; Production nhìn thấy việc phải làm; Management nhìn thấy tín hiệu kinh doanh. High Priority Những dòng cần hành động được kéo ra khỏi transcript Các action có priority cao được highlight riêng, có owner, deadline, status. Nếu deadline chỉ được suy luận từ ngữ cảnh, biên bản đánh dấu rõ là inferred để người phụ trách confirm lại. Visual Evidence Những gì hiện trên màn hình cũng được đưa vào quá trình xác thực Khi video có screen share, AI trích các frame đại diện để kiểm tra slide, bảng số liệu, ticket list, timeline hoặc UI state. Nhờ đó biên bản không chỉ dựa vào câu nói "như trên màn hình", mà có thêm bằng chứng hình ảnh để trace lại. Quality Note Biên bản không giả vờ transcript là hoàn hảo Phần Notes ghi rõ nguồn, chất lượng transcript, tên/thuật ngữ chưa chắc chắn và các giới hạn khi dùng mic chung hoặc ASR Nhật - Việt - Anh. Đây là điểm giúp biên bản đáng tin hơn, không phải màu mè hơn. Chương 8 Những giá trị vô hình đã được chứng minh Kể từ khi áp dụng Skill meeting-minutes-from-recording, hiệu quả công việc thay đổi rõ rệt: 1. Giải phóng sức lao động cho Sales & PM Thay vì mất hàng giờ mỗi ngày để ngồi nhớ lại và hì hục gõ biên bản, giờ đây team chỉ mất 5 phút để review lại file HTML do AI tạo ra. 2. Cầu nối thông tin đáng tin cậy Đội Sản xuất nhận được bối cảnh có cấu trúc, kèm quyết định, action items và ghi chú nguồn. Tình trạng "tam sao thất bản" giảm đi rõ rệt vì mọi người cùng nhìn vào một tài liệu chung. 3. Giữ trọn vẹn "sắc thái kinh doanh" (Business Nuance) Những chi tiết nhỏ như sự lo ngại (concern), sự tin tưởng, hay các "tín hiệu mua hàng" (buying signals) từ khách hàng Nhật đều được AI tinh ý nhận ra và note lại. 4. Uy tín tăng cao trong mắt khách hàng Gửi biên bản cuộc họp đẹp, chi tiết, có Action Items rõ ràng ngay sau buổi họp khiến khách hàng cảm nhận được sự chuyên nghiệp và mức độ sát sao của team. 5. Ít missed tasks hơn, ít tranh cãi hơn Thay vì hỏi lại "Hôm trước khách nói gì nhỉ?", team có thể mở biên bản, trace lại quyết định, owner, deadline và các điểm inferred cần confirm. Sẵn sàng để giải phóng sức lao động? Cài đặt ngay skill Meeting Minutes From Recording cho AI Assistant của bạn. Tải Skill tại KARI "Khi máy móc làm thay phần việc ghi chép nặng nhọc, con người được giải phóng để tập trung vào thứ quan trọng nhất: Giải quyết vấn đề và mang lại giá trị cho khách hàng." (()=>{const __name=(target)=>target;(function runEngagementClient(config3) { const root = globalThis; const endpoint = "/api/analytics/engagement"; const sessionTimeout = 18e5; const idleTimeout = 6e4; const checkpointInterval = 3e4; const storageKey = `kshare.engagement.${config3.fileId}.${config3.version}`; const uuidV4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; function newSessionId() { if (root.crypto.randomUUID) return root.crypto.randomUUID(); const bytes = root.crypto.getRandomValues(new Uint8Array(16)); bytes[6] = (bytes[6] ?? 0) & 15 | 64; bytes[8] = (bytes[8] ?? 0) & 63 | 128; const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join(""); return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; } __name(newSessionId, "newSessionId"); function restore() { try { const raw2 = root.sessionStorage.getItem(storageKey); if (!raw2) return null; const value = JSON.parse(raw2); if (typeof value.id !== "string" || !uuidV4.test(value.id) || typeof value.lastSeen !== "number" || Date.now() - value.lastSeen > sessionTimeout) { return null; } return { id: value.id, engagedMs: Number.isFinite(value.engagedMs) ? Math.max(0, value.engagedMs ?? 0) : 0, maxScroll: Number.isFinite(value.maxScroll) ? Math.max(0, value.maxScroll ?? 0) : 0, interactionCount: Number.isFinite(value.interactionCount) ? Math.max(0, value.interactionCount ?? 0) : 0, lastSeen: value.lastSeen }; } catch { return null; } } __name(restore, "restore"); const restored = restore(); const session = restored ?? { id: newSessionId(), engagedMs: 0, maxScroll: 0, interactionCount: 0, lastSeen: Date.now() }; let lastTick = Date.now(); let lastActivity = Date.now(); let lastInteractionAt = 0; let lastFlush = 0; function persist() { session.lastSeen = Date.now(); try { root.sessionStorage.setItem(storageKey, JSON.stringify(session)); } catch { } } __name(persist, "persist"); function tick() { const now = Date.now(); if (root.document.visibilityState === "visible") { const activeEnd = Math.min(now, lastActivity + idleTimeout); if (activeEnd > lastTick) session.engagedMs += activeEnd - lastTick; } lastTick = now; } __name(tick, "tick"); function updateScroll() { const doc = root.document.documentElement; const body = root.document.body; const height = Math.max( doc.scrollHeight, doc.offsetHeight, doc.clientHeight, body?.scrollHeight ?? 0, body?.offsetHeight ?? 0, root.window.innerHeight ); const depth = Math.max( 0, Math.min(100, Math.round((root.window.scrollY + root.window.innerHeight) / height * 100)) ); session.maxScroll = Math.max(session.maxScroll, depth); } __name(updateScroll, "updateScroll"); function markActivity() { tick(); const now = Date.now(); lastActivity = now; if (now - lastInteractionAt >= 1e3) { session.interactionCount += 1; lastInteractionAt = now; } updateScroll(); persist(); } __name(markActivity, "markActivity"); function flush() { tick(); updateScroll(); persist(); lastFlush = Date.now(); const body = JSON.stringify({ token: config3.token, session_id: session.id, engaged_ms: Math.round(session.engagedMs), max_scroll: Math.round(session.maxScroll), interaction_count: Math.round(session.interactionCount) }); let sent = false; try { sent = root.navigator.sendBeacon?.( endpoint, new root.Blob([body], { type: "application/json" }) ) ?? false; } catch { sent = false; } if (!sent) { void root.fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json" }, body, credentials: "same-origin", keepalive: true }).catch(() => void 0); } } __name(flush, "flush"); updateScroll(); root.document.addEventListener("pointerdown", markActivity, { passive: true }); root.document.addEventListener("touchstart", markActivity, { passive: true }); root.document.addEventListener("keydown", markActivity); root.window.addEventListener("scroll", markActivity, { passive: true }); root.document.addEventListener("visibilitychange", () => { if (root.document.visibilityState === "hidden") { flush(); } else { lastTick = Date.now(); lastActivity = Date.now(); } }); root.window.addEventListener("pagehide", flush); root.setInterval(() => { tick(); updateScroll(); if (Date.now() - lastFlush >= checkpointInterval) flush(); }, 1e3); flush(); })({"token":"eyJmaWxlSWQiOjUxMSwidmVyc2lvbiI6MiwiZXhwIjoxNzg0Nzg2NjkyOTI4fQ.fc72e9946366ddda99bfa013fdc13e66667fc270c0f10390fbc88e250fb37c59","fileId":511,"version":2});})();