สร้าง Local Voice Memo to Action Agent: เปลี่ยนคลิปเสียงบันทึกไอเดียให้เป็น Action Items และบันทึกสรุปอัตโนมัติด้วย Whisper + Ollama

เปลี่ยนการอัดเสียงบ่นหรือบันทึกไอเดียระหว่างเดินทางให้กลายเป็น Daily Journal และรายการ To-Do ที่จัดหมวดหมู่อย่างเป็นระเบียบ ด้วยสคริปต์อัตโนมัติที่รัน Whisper และ Local LLM บนเครื่องของคุณแบบออฟไลน์ 100%

Share
สร้าง Local Voice Memo to Action Agent: เปลี่ยนคลิปเสียงบันทึกไอเดียให้เป็น Action Items และบันทึกสรุปอัตโนมัติด้วย Whisper +

เคยไหมที่ระหว่างขับรถ เดินออกกำลังกาย หรือทำกิจกรรมต่างๆ แล้วเกิดปิ๊งไอเดียสำคัญขึ้นมา วิธีที่เร็วที่สุดในตอนนั้นคือการหยิบสมาร์ตโฟนขึ้นมา กดอัดเสียง (Voice Memo) แล้วพูดทุกอย่างที่คิดออกมาอย่างรวดเร็ว

แต่ปัญหาที่แท้จริงจะตามมาหลังจากนั้น: ไฟล์เสียงความยาว 3-5 นาทีที่พูดตะกุกตะกัก มีคำสร้อย ไอเดียปะปนกับรายการสิ่งที่ต้องทำ และกระจัดกระจายอยู่ในโฟลเดอร์ สุดท้ายคลิปเสียงเหล่านั้นก็กลายเป็น "สุสานไฟล์เสียง" ที่ไม่มีใครย้อนกลับไปเปิดฟังอีกเลย

ในบทความนี้ เราจะมาสร้าง Local Voice Memo to Action Agent ซึ่งเป็นระบบ Cognitive Automation ส่วนบุคคล ที่จะคอยเฝ้าดูโฟลเดอร์ไฟล์เสียง นำคลิปเสียงมาถอดความด้วย faster-whisper แบบออฟไลน์ แล้วส่งต่อให้ Local LLM (ผ่าน Ollama) สกัดแยกเป็น 3 ส่วนชัดเจน: แก่นของไอเดีย (Core Insights), รายการที่ต้องทำทันที (Action Items), และ สรุปความเข้า Daily Journal พร้อมบันทึกเป็น Markdown ลงใน Second Brain ของคุณโดยอัตโนมัติ


สถาปัตยกรรมของ Local Voice Agent

กระบวนการทำงานทั้งหมดจะเกิดขึ้นภายในเครื่องของคุณ 100% โดยไม่ต้องส่งเสียงหรือข้อมูลส่วนตัวขึ้นคลาวด์:

  1. Audio Watcher: สคริปต์ Python ตรวจจับไฟล์เสียงใหม่ (เช่น .m4a, .mp3, .wav) ในโฟลเดอร์ที่กำหนด
  2. Local Speech-to-Text: ใช้โมเดล faster-whisper ในเครื่องเพื่อแปลงเสียงพูดภาษาไทย/อังกฤษเป็นข้อความดิบ
  3. Cognitive Synthesis (Ollama): ส่งข้อความดิบให้โมเดลภาษา (เช่น llama3 หรือ qwen2.5) จัดโครงสร้าง ไวยากรณ์ และแยกประเภทข้อมูล
  4. Markdown Export: บันทึกผลลัพธ์เป็นไฟล์ .md ที่พร้อมใช้งานใน Obsidian หรือโฟลเดอร์บันทึกส่วนตัว

ขั้นตอนที่ 1: เตรียมสภาพแวดล้อมและโมเดล AI

ติดตั้งไลบรารี Python สำหรับการถอดเสียงและติดต่อกับ Ollama:

pip install faster-whisper requests watchdog

ตรวจสอบว่าคุณมี Ollama ติดตั้งและเปิดใช้งานอยู่ จากนั้นดาวน์โหลดโมเดลที่รองรับภาษาไทยได้ดีเยี่ยม เช่น qwen2.5:7b หรือ llama3.1:8b:

ollama run qwen2.5:7b

ขั้นตอนที่ 2: เขียนสคริปต์ Voice to Action Agent

สร้างไฟล์สคริปต์ชื่อ voice_action_agent.py ดังนี้:

import os
import json
import requests
from datetime import datetime
from faster_whisper import WhisperModel

# ตั้งค่าเส้นทางโฟลเดอร์
INPUT_AUDIO_DIR = os.path.expanduser("~/VoiceMemos/Inbox")
PROCESSED_DIR = os.path.expanduser("~/VoiceMemos/Processed")
OUTPUT_NOTES_DIR = os.path.expanduser("~/Notes/DailyNotes")
OLLAMA_API_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "qwen2.5:7b"

os.makedirs(INPUT_AUDIO_DIR, exist_ok=True)
os.makedirs(PROCESSED_DIR, exist_ok=True)
os.makedirs(OUTPUT_NOTES_DIR, exist_ok=True)

# โหลด Whisper Model (ใช้ model ขนาด small หรือ base สำหรับความเร็ว)
print("[*] กำลังโหลด Whisper Model...")
whisper_model = WhisperModel("base", device="cpu", compute_type="int8")

def transcribe_audio(file_path: str) -> str:
    """ถอดเสียงเป็นข้อความด้วย Whisper แบบ Local"""
    print(f"[*] กำลังถอดเสียง: {os.path.basename(file_path)}")
    segments, _ = whisper_model.transcribe(file_path, language="th")
    full_text = " ".join([segment.text for segment in segments])
    return full_text.strip()

def synthesize_with_llm(raw_text: str) -> str:
    """ให้ Local LLM จัดระเบียบข้อความและแยก Action Items"""
    prompt = f"""คุณคือผู้ช่วยจัดการสมองส่วนตัว (Second Brain Assistant) 
ต่อไปนี้คือข้อความที่ถอดความมาจากการบันทึกเสียงพูดสด ซึ่งอาจมีความไม่ต่อเนื่องหรือเป็นภาษาพูด:

\"\"\"{raw_text}\"\"\"

ภารกิจของคุณ:
1. สรุปใจความสำคัญ (Summary) 2-3 บรรทัด
2. คัดแยกประเด็นไอเดียหลัก (Key Insights)
3. คัดแยกสิ่งที่ต้องทำ (Action Items / To-Dos) ในรูปแบบ markdown checklist `- [ ]`
4. แนะนำแท็ก (Tags) ที่เกี่ยวข้อง

โปรดจัดรูปแบบผลลัพธ์เป็น Markdown ภาษาไทยที่อ่านง่ายและกระชับ
"""
    payload = {
        "model": MODEL_NAME,
        "prompt": prompt,
        "stream": False
    }
    response = requests.post(OLLAMA_API_URL, json=payload)
    if response.status_code == 200:
        return response.json().get("response", "")
    return "เกิดข้อผิดพลาดในการประมวลผล LLM"

def process_voice_memo(file_path: str):
    raw_text = transcribe_audio(file_path)
    if not raw_text:
        print("[!] ไม่พบเสียงพูดในไฟล์")
        return

    print("[*] กำลังส่งต่อให้ LLM วิเคราะห์และจัดระเบียบ...")
    structured_note = synthesize_with_llm(raw_text)

    timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
    base_name = os.path.splitext(os.path.basename(file_path))[0]
    output_filename = f"voice-note-{timestamp}.md"
    output_path = os.path.join(OUTPUT_NOTES_DIR, output_filename)

    # ประกอบเนื้อหาไฟล์ Markdown
    markdown_content = f"""---
title: "Voice Memo: {base_name}"
date: "{datetime.now().strftime('%Y-%m-%d %H:%M')}"
type: "voice-memo"
source_file: "{os.path.basename(file_path)}"
---

### 📝 ข้อความถอดเสียงดิบ (Raw Transcript)
> {raw_text}

---

{structured_note}
"""

    with open(output_path, "w", encoding="utf-8") as f:
        f.write(markdown_content)

    # ย้ายไฟล์เสียงที่ประมวลผลแล้ว
    shutil_dest = os.path.join(PROCESSED_DIR, os.path.basename(file_path))
    os.rename(file_path, shutil_dest)
    print(f"[+] เสร็จสมบูรณ์! บันทึกโน้ตไว้ที่: {output_path}")

if __name__ == "__main__":
    audio_extensions = (".m4a", ".mp3", ".wav", ".aac")
    for file_name in os.listdir(INPUT_AUDIO_DIR):
        if file_name.lower().endswith(audio_extensions):
            full_path = os.path.join(INPUT_AUDIO_DIR, file_name)
            process_voice_memo(full_path)

ขั้นตอนที่ 3: เชื่อมต่อการอัปโหลดจากสมาร์ตโฟนด้วย Syncthing

เพื่อให้การทำงานเป็นไปอย่างราบรื่นไร้รอยต่อ คุณสามารถตั้งค่า Syncthing เพื่อซิงก์โฟลเดอร์อัดเสียงบนมือถือ (เช่น โฟลเดอร์ Audio Recorder ใน Android หรือ iOS ผ่านแอปที่รองรับ) ให้ซิงก์เข้ามายังโฟลเดอร์ ~/VoiceMemos/Inbox บนคอมพิวเตอร์ของคุณอัตโนมัติ

เมื่อใดก็ตามที่คุณอัดเสียงเสร็จขณะอยู่นอกบ้าน ทันทีที่อุปกรณ์เชื่อมต่อเครือข่ายเดียวกัน ไฟล์จะถูกส่งเข้าเครื่อง และระบบ Agent จะประมวลผลเป็นบันทึก To-Do รอไว้ในหน้าจอของคุณทันที


สรุปประโยชน์ของ Cognitive Automation สำหรับงานบันทึกเสียง

  • ลด Cognitive Load: คุณไม่ต้องกังวลเรื่องการเรียบเรียงประโยคขณะอัดเสียง แค่พูดทุกอย่างที่คิดออกมา ระบบจะจัดการคัดแยกข้อความให้เอง
  • ไม่มีหลุดหลงลืม: งานและ To-Do ที่เคยแฝงอยู่ในคลิปเสียงยาวๆ จะถูกดึงออกมาเป็น Checklist ให้คุณพร้อมติ๊กทำงานทันที
  • ความเป็นส่วนตัวสูงสุด (100% Local): เสียงความคิดและเรื่องงานที่เป็นความลับจะไม่ถูกส่งไปยังคลาวด์ภายนอก ปลอดภัยตามหลัก Local-first Second Brain

Read more

สร้าง AI Agent สำหรับการทำ Decision Log อัตโนมัติ: เปลี่ยนทุกการตัดสินใจสำคัญให้เป็นบทเรียนเพื่อการเติบโต

สร้าง AI Agent สำหรับการทำ Decision Log อัตโนมัติ: เปลี่ยนทุกการตัดสินใจสำคัญให้เป็นบทเรียนเพื่อการเติบโต

เรียนรู้วิธีใช้ AI Agent ช่วยบันทึกและวิเคราะห์การตัดสินใจสำคัญในชีวิตประจำวัน เพื่อเปลี่ยนทุกทางเลือกให้กลายเป็นฐานข้อมูลบทเรียนที่มีค่าสำหรับอนาคต

By Linn
คู่มือใช้งาน Obsidian Graph View: เปลี่ยนใยแมงมุมความรู้ให้เป็นเครื่องมือนำทางความคิดใน Second Brain

คู่มือใช้งาน Obsidian Graph View: เปลี่ยนใยแมงมุมความรู้ให้เป็นเครื่องมือนำทางความคิดใน Second Brain

Graph View ใน Obsidian ไม่ใช่แค่ภาพกราฟสวยๆ ไว้ดูเล่น มาเรียนรู้วิธีปรับแต่ง Local Graph, Color Groups และฟิลเตอร์ เพื่อเปลี่ยนเครือข่ายความรู้ให้กลายเป็นเครื่องมือนำทางความคิดจริง

By Linn
สร้าง Smart Clipboard Agent: ดักจับและคัดแยกข้อความที่คัดลอกระหว่างวัน บันทึกเข้า Obsidian อัตโนมัติด้วย Python + Ollama

สร้าง Smart Clipboard Agent: ดักจับและคัดแยกข้อความที่คัดลอกระหว่างวัน บันทึกเข้า Obsidian อัตโนมัติด้วย Python + Ollama

เปลี่ยนข้อความ โค้ด ลิงก์ และไอเดียที่คุณคัดลอกระหว่างวันให้กลายเป็นบันทึกความรู้ที่มีบริบทใน Second Brain โดยอัตโนมัติ ด้วยสคริปต์ Python คอยมอนิเตอร์คลิปบอร์ดคู่กับ Local LLM บน Ollama แบบออฟไลน์ 100%

By Linn
บอกลาคำสั่ง Docker CLI ที่ซับซ้อน: คู่มือติดตั้ง Dockge จัดการ Docker Compose บน Home Server อย่างมือโปร

บอกลาคำสั่ง Docker CLI ที่ซับซ้อน: คู่มือติดตั้ง Dockge จัดการ Docker Compose บน Home Server อย่างมือโปร

ยกระดับการจัดการคอนเทนเนอร์บน Home Server ให้ง่ายและเป็นระเบียบ ด้วย Dockge ตัวจัดการ Docker Compose สไตล์มินิมอลที่เน้นความโปร่งใส ควบคุมไฟล์ .yml ได้โดยตรง 100%

By Linn