7.1 KiB
7.1 KiB
notebooklm-api
REST + WebSocket API server điều khiển Google NotebookLM qua Puppeteer — giả lập thao tác người dùng thật trong Chrome.
Dùng để tích hợp NotebookLM vào chatbot, n8n, Make, Python scripts, ERP, hoặc bất kỳ hệ thống nào cần xử lý tài liệu bằng AI.
Tính năng
- Xác thực — Mở Google login một lần, session lưu vĩnh viễn
- Notebooks — Tạo, liệt kê, xoá notebooks
- Sources — Thêm nguồn từ URL website, file local (.pdf, .docx, .txt, ...) hoặc văn bản paste
- Chat đồng bộ — Gửi câu hỏi, nhận câu trả lời đầy đủ (
POST) - Chat streaming — Nhận câu trả lời theo từng chunk realtime (
WebSocket) - Queue tự động — Các request song song được xếp hàng, không race condition
- Swagger UI — Tài liệu API tương tác tại
/docs
Cài đặt nhanh
git clone <repo>
cd notebooklm-api
bash setup.sh
Hoặc thủ công:
npm install
cp .env.example .env # tuỳ chỉnh nếu cần
npm start
Server khởi động tại http://localhost:3456
Swagger UI tại http://localhost:3456/docs
Đăng nhập lần đầu
# Mở browser để đăng nhập Google
curl -X POST http://localhost:3456/api/auth/login
Chrome sẽ mở → đăng nhập Google → API tự trả về khi xong. Session lưu trong ./chrome-profile/ — các lần sau tự động đăng nhập.
Dừng server: luôn dùng Ctrl+C (không dùng kill -9 để tránh mất cookies).
Biến môi trường
| Biến | Mặc định | Mô tả |
|---|---|---|
PORT |
3456 |
Cổng HTTP/WebSocket |
HEADLESS |
false |
true = ẩn cửa sổ Chrome |
CHROME_PATH |
tự phát hiện | Đường dẫn Chrome tuỳ chỉnh |
API_KEY |
(trống) | Nếu đặt, request phải có header x-api-key |
API nhanh
Auth
GET /api/auth/status Kiểm tra đăng nhập
POST /api/auth/login Mở browser đăng nhập Google
Notebooks
GET /api/notebooks Danh sách notebooks
POST /api/notebooks Tạo notebook { "title": "..." }
DELETE /api/notebooks/:id Xoá notebook
Sources
GET /api/notebooks/:id/sources Danh sách sources
POST /api/notebooks/:id/sources Thêm source
Body thêm source:
{ "type": "url", "content": "https://...", "title": "Tuỳ chọn" }
{ "type": "text", "content": "Nội dung...", "title": "Tên tài liệu" }
{ "type": "file", "content": "/đường/dẫn/tuyệt/đối/file.pdf" }
Định dạng file hỗ trợ: .pdf .txt .md .docx .doc .pptx .ppt .xlsx .xls .mp3 .mp4 .jpg .png
Chat
POST /api/notebooks/:id/chat Hỏi đồng bộ { "message": "..." }
GET /api/notebooks/:id/chat/history Lịch sử hội thoại
WS /api/notebooks/:id/chat/stream Chat streaming (WebSocket)
Tiện ích
GET /health Trạng thái server + queue
GET /docs Swagger UI
Ví dụ sử dụng
curl
NB=<notebook-id>
# Tạo notebook
curl -X POST http://localhost:3456/api/notebooks \
-H "Content-Type: application/json" \
-d '{"title": "Dự án Q3"}'
# Thêm URL
curl -X POST http://localhost:3456/api/notebooks/$NB/sources \
-H "Content-Type: application/json" \
-d '{"type":"url","content":"https://example.com/bai-viet"}'
# Thêm file local
curl -X POST http://localhost:3456/api/notebooks/$NB/sources \
-H "Content-Type: application/json" \
-d '{"type":"file","content":"/Users/me/Documents/report.pdf"}' \
--max-time 90
# Hỏi
curl -X POST http://localhost:3456/api/notebooks/$NB/chat \
-H "Content-Type: application/json" \
-d '{"message":"Tóm tắt nội dung chính"}' --max-time 120
Python
import requests
BASE = "http://localhost:3456"
NB_ID = "<notebook-id>"
# Thêm file
requests.post(f"{BASE}/api/notebooks/{NB_ID}/sources",
json={"type": "file", "content": "/path/to/file.pdf"},
timeout=90)
# Hỏi
answer = requests.post(f"{BASE}/api/notebooks/{NB_ID}/chat",
json={"message": "Tóm tắt tài liệu"},
timeout=120).json()["answer"]
print(answer)
WebSocket streaming
const ws = new WebSocket('ws://localhost:3456/api/notebooks/<NB_ID>/chat/stream');
ws.onopen = () => ws.send(JSON.stringify({ message: 'Tóm tắt nội dung' }));
ws.onmessage = ({ data }) => {
const msg = JSON.parse(data);
if (msg.type === 'chunk') process.stdout.write(msg.data);
if (msg.type === 'done') console.log('\n[Xong]');
if (msg.type === 'error') console.error('[Lỗi]', msg.data);
};
Cấu trúc dự án
notebooklm-api/
├── src/
│ ├── server.js Express app + debug routes
│ ├── browser.js Puppeteer BrowserManager (singleton)
│ ├── nlm.js Logic automation NotebookLM (core)
│ ├── queue.js AsyncQueue — tuần tự hoá thao tác browser
│ ├── selectors.js CSS selectors đã xác nhận trên DOM thực
│ ├── swagger.js OpenAPI spec
│ └── routes/
│ ├── auth.js /api/auth/*
│ ├── notebooks.js /api/notebooks/*
│ └── chat-ws.js WebSocket streaming
├── chrome-profile/ Session Chrome (KHÔNG xoá)
├── .env Biến môi trường
├── setup.sh Script cài đặt nhanh
└── API.md Tài liệu API đầy đủ
Debug endpoints
Dùng khi selector bị hỏng sau khi Google cập nhật UI:
GET /debug/screenshot Chụp ảnh Chrome hiện tại (base64 PNG)
GET /debug/home Liệt kê buttons trên trang chủ
GET /debug/notebook-btns/:id Liệt kê buttons trên trang notebook
GET /debug/notebook-menu/:id Hover card + click "..." menu, trả về menu items
GET /debug/sources/:id Inspect DOM source panel
GET /debug/source-items/:id HTML đầy đủ của từng source item
GET /debug/add-source-dialog/:id Click "Thêm nguồn", snapshot dialog
GET /debug/add-url-flow/:id Trace từng bước flow thêm URL
GET /debug/add-file-flow/:id Trace từng bước flow upload file
GET /debug/chat/:id Liệt kê textarea/input trên trang notebook
GET /debug/page-state/:id Trạng thái overlay trước/sau click
Lưu ý
- 1 thao tác tại 1 thời điểm — queue tự xếp hàng, không cần lo concurrency
- Upload file có thể mất 30–60 giây — đặt
--max-time 90khi dùng curl - Chat timeout mặc định 90 giây — câu hỏi phức tạp có thể cần tăng lên
- Chrome crash? Xoá
chrome-profile/SingletonLockrồi restart - Google có thể giới hạn automation — nếu bị chặn, đợi vài phút rồi thử lại
Scripts
npm start # Production
npm run dev # Development (auto-restart khi thay đổi file)