Skip to content

Commit 8f9dd3a

Browse files
authored
Merge pull request teng-lin#198 from teng-lin/release/v0.3.4
chore: release v0.3.4
2 parents b1220c8 + 77544a3 commit 8f9dd3a

23 files changed

+277
-94
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,8 @@ jobs:
2828
python -m pip install --upgrade pip
2929
pip install -e ".[all]"
3030
31-
- name: Run linting
32-
run: ruff check src/ tests/
33-
34-
- name: Check formatting
35-
run: ruff format --check src/ tests/
31+
- name: Run pre-commit checks
32+
run: pre-commit run --all-files
3633

3734
- name: Run type checking
3835
run: mypy src/notebooklm --ignore-missing-imports

CHANGELOG.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.3.4] - 2026-03-12
11+
12+
### Added
13+
- **Notebook metadata export** - Added notebook metadata APIs and CLI export with a simplified sources list
14+
- New `notebooklm metadata` command with human-readable and `--json` output
15+
- New `NotebookMetadata` and `SourceSummary` public types
16+
- New `client.notebooks.get_metadata()` helper
17+
- **Cinematic Video Overview support** - Added cinematic generation and download flows
18+
- `notebooklm generate video --format cinematic`
19+
- **Infographic styles** - Added CLI support for selecting infographic visual styles
20+
- **`source delete-by-title`** - Added explicit exact-title deletion command for sources
21+
22+
### Fixed
23+
- **Research imports on timeout** - CLI research imports now retry on timeout with backoff
24+
- **Metadata command behavior** - Aligned metadata output and implementation with current CLI patterns
25+
- **Regional login cookies** - Improved browser login handling for regional Google domains
26+
- **Notebook summary parsing** - Fixed notebook summary response parsing
27+
- **Source delete UX** - Improved source delete resolution, ambiguity handling, and title-vs-ID errors
28+
- **Empty downloads** - Raise an error instead of producing zero-byte files
29+
- **Module execution** - Added `python -m notebooklm` support
30+
31+
### Changed
32+
- **Documentation refresh** - Updated release, development, CLI, README, and Python API docs for current commands, APIs, and `uv` workflows
33+
- **Public API surface** - Exported `NotebookMetadata`, `SourceSummary`, and `InfographicStyle`
34+
1035
## [0.3.3] - 2026-03-03
1136

1237
### Added
@@ -319,7 +344,8 @@ This is the initial public release of `notebooklm-py`. While core functionality
319344
- **Authentication expiry**: CSRF tokens expire after some time. Re-run `notebooklm login` if you encounter auth errors.
320345
- **Large file uploads**: Files over 50MB may fail or timeout. Split large documents if needed.
321346

322-
[Unreleased]: https://github.com/teng-lin/notebooklm-py/compare/v0.3.3...HEAD
347+
[Unreleased]: https://github.com/teng-lin/notebooklm-py/compare/v0.3.4...HEAD
348+
[0.3.4]: https://github.com/teng-lin/notebooklm-py/compare/v0.3.3...v0.3.4
323349
[0.3.3]: https://github.com/teng-lin/notebooklm-py/compare/v0.3.2...v0.3.3
324350
[0.3.2]: https://github.com/teng-lin/notebooklm-py/compare/v0.3.1...v0.3.2
325351
[0.3.1]: https://github.com/teng-lin/notebooklm-py/compare/v0.3.0...v0.3.1

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
| Type | Options | Download Format |
6161
|------|---------|-----------------|
6262
| **Audio Overview** | 4 formats (deep-dive, brief, critique, debate), 3 lengths, 50+ languages | MP3/MP4 |
63-
| **Video Overview** | 2 formats, 9 visual styles (classic, whiteboard, kawaii, anime, etc.) | MP4 |
63+
| **Video Overview** | 3 formats (explainer, brief, cinematic), 9 visual styles, plus a dedicated `cinematic-video` CLI alias | MP4 |
6464
| **Slide Deck** | Detailed or presenter format, adjustable length; individual slide revision | PDF, PPTX |
6565
| **Infographic** | 3 orientations, 3 detail levels | PNG |
6666
| **Quiz** | Configurable quantity and difficulty | JSON, Markdown, HTML |
@@ -131,6 +131,7 @@ notebooklm ask "What are the key themes?"
131131
# 4. Generate content
132132
notebooklm generate audio "make it engaging" --wait
133133
notebooklm generate video --style whiteboard --wait
134+
notebooklm generate cinematic-video "documentary-style summary" --wait
134135
notebooklm generate quiz --difficulty hard
135136
notebooklm generate flashcards --quantity more
136137
notebooklm generate slide-deck
@@ -141,6 +142,7 @@ notebooklm generate data-table "compare key concepts"
141142
# 5. Download artifacts
142143
notebooklm download audio ./podcast.mp3
143144
notebooklm download video ./overview.mp4
145+
notebooklm download cinematic-video ./documentary.mp4
144146
notebooklm download quiz --format markdown ./quiz.md
145147
notebooklm download flashcards --format json ./cards.json
146148
notebooklm download slide-deck ./slides.pdf
@@ -149,6 +151,17 @@ notebooklm download mind-map ./mindmap.json
149151
notebooklm download data-table ./data.csv
150152
```
151153

154+
Other useful CLI commands:
155+
156+
```bash
157+
notebooklm auth check --test # Diagnose auth/cookie issues
158+
notebooklm language list # List supported output languages
159+
notebooklm metadata --json # Export notebook metadata and sources
160+
notebooklm share status # Inspect sharing state
161+
notebooklm source add-research "AI" # Start web research and import sources
162+
notebooklm skill status # Check Claude Code skill installation
163+
```
164+
152165
### Python API
153166

154167
```python
@@ -199,6 +212,7 @@ notebooklm skill install
199212
- **[CLI Reference](docs/cli-reference.md)** - Complete command documentation
200213
- **[Python API](docs/python-api.md)** - Full API reference
201214
- **[Configuration](docs/configuration.md)** - Storage and settings
215+
- **[Release Guide](docs/releasing.md)** - Release checklist and packaging verification
202216
- **[Troubleshooting](docs/troubleshooting.md)** - Common issues and solutions
203217
- **[API Stability](docs/stability.md)** - Versioning policy and stability guarantees
204218

docs/cli-reference.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# CLI Reference
22

33
**Status:** Active
4-
**Last Updated:** 2026-03-02
4+
**Last Updated:** 2026-03-12
55

66
Complete command reference for the `notebooklm` CLI—providing full programmatic access to all NotebookLM features, including capabilities not exposed in the web UI.
77

@@ -27,7 +27,8 @@ See [Configuration](configuration.md) for details on environment variables and C
2727
- **Session commands** - Authentication and context management
2828
- **Notebook commands** - CRUD operations on notebooks
2929
- **Chat commands** - Querying and conversation management
30-
- **Grouped commands** - `source`, `artifact`, `generate`, `download`, `note`
30+
- **Grouped commands** - `source`, `artifact`, `generate`, `download`, `note`, `share`, `research`, `language`, `skill`, `auth`
31+
- **Utility commands** - `metadata`
3132

3233
---
3334

@@ -67,7 +68,6 @@ See [Configuration](configuration.md) for details on environment variables and C
6768
| `create <title>` | Create notebook | `notebooklm create "Research"` |
6869
| `delete <id>` | Delete notebook | `notebooklm delete abc123` |
6970
| `rename <title>` | Rename current notebook | `notebooklm rename "New Title"` |
70-
| `share` | Toggle notebook sharing | `notebooklm share` or `notebooklm share --revoke` |
7171
| `summary` | Get AI summary | `notebooklm summary` |
7272

7373
### Chat Commands
@@ -125,7 +125,8 @@ All generate commands support:
125125
| Command | Options | Example |
126126
|---------|---------|---------|
127127
| `audio [description]` | `--format [deep-dive\|brief\|critique\|debate]`, `--length [short\|default\|long]`, `--wait` | `generate audio "Focus on history"` |
128-
| `video [description]` | `--format [explainer\|brief]`, `--style [auto\|classic\|whiteboard\|kawaii\|anime\|watercolor\|retro-print\|heritage\|paper-craft]`, `--wait` | `generate video "Explainer for kids"` |
128+
| `video [description]` | `--format [explainer\|brief\|cinematic]`, `--style [auto\|classic\|whiteboard\|kawaii\|anime\|watercolor\|retro-print\|heritage\|paper-craft]`, `--wait` | `generate video "Explainer for kids"` |
129+
| `cinematic-video [description]` | Alias for `video --format cinematic`; supports the same options | `generate cinematic-video "Documentary about quantum physics"` |
129130
| `slide-deck [description]` | `--format [detailed\|presenter]`, `--length [default\|short]`, `--wait` | `generate slide-deck` |
130131
| `revise-slide <description>` | `-a/--artifact <id>` (required), `--slide N` (required), `--wait` | `generate revise-slide "Move title up" --artifact <id> --slide 0` |
131132
| `quiz [description]` | `--difficulty [easy\|medium\|hard]`, `--quantity [fewer\|standard\|more]`, `--wait` | `generate quiz --difficulty hard` |
@@ -154,6 +155,7 @@ All generate commands support:
154155
|---------|-----------|---------|---------|
155156
| `audio [path]` | Output path | `-a/--artifact`, `--all`, `--latest`, `--name`, `--force`, `--dry-run` | `download audio --all` |
156157
| `video [path]` | Output path | `-a/--artifact`, `--all`, `--latest`, `--name`, `--force`, `--dry-run` | `download video --latest` |
158+
| `cinematic-video [path]` | Output path | Alias for `download video`; same options as `video` | `download cinematic-video ./documentary.mp4` |
157159
| `slide-deck [path]` | Output path | `-a/--artifact`, `--all`, `--latest`, `--name`, `--force`, `--dry-run`, `--format [pdf\|pptx]` | `download slide-deck ./slides.pdf` |
158160
| `infographic [path]` | Output path | `-a/--artifact`, `--all`, `--latest`, `--name`, `--force`, `--dry-run` | `download infographic ./info.png` |
159161
| `report [path]` | Output path | `-a/--artifact`, `--all`, `--latest`, `--name`, `--force`, `--dry-run` | `download report ./report.md` |
@@ -169,10 +171,28 @@ All generate commands support:
169171
| `list` | - | - | `note list` |
170172
| `create <content>` | Note content | - | `note create "My notes..."` |
171173
| `get <id>` | Note ID | - | `note get note123` |
172-
| `save <id>` | Note ID | - | `note save note123` |
174+
| `save <id>` | Note ID | `--title`, `--content` | `note save note123 --title "Updated title"` |
173175
| `rename <id> <title>` | Note ID, title | - | `note rename note123 "Title"` |
174176
| `delete <id>` | Note ID | - | `note delete note123` |
175177

178+
### Metadata Command
179+
180+
Export notebook metadata and a simplified source list.
181+
182+
```bash
183+
notebooklm metadata [OPTIONS]
184+
```
185+
186+
**Options:**
187+
- `-n, --notebook ID` - Specify notebook (uses current if not set)
188+
- `--json` - Output as JSON for scripts
189+
190+
**Examples:**
191+
```bash
192+
notebooklm metadata
193+
notebooklm metadata -n abc123 --json
194+
```
195+
176196
### Skill Commands (`notebooklm skill <cmd>`)
177197

178198
Manage Claude Code skill integration.
@@ -781,7 +801,7 @@ notebooklm summary
781801
# 4. Generate study materials
782802
notebooklm generate quiz --difficulty hard --wait
783803
notebooklm generate flashcards --wait
784-
notebooklm generate report --type study-guide --wait
804+
notebooklm generate report --format study-guide --wait
785805

786806
# 5. Ask specific questions
787807
notebooklm ask "Explain the key concepts in chapter 3"
@@ -806,7 +826,7 @@ notebooklm ask "What are the main points?"
806826
notebooklm ask "Create bullet point notes"
807827

808828
# 4. Generate a quick briefing doc
809-
notebooklm generate report --type briefing-doc --wait
829+
notebooklm generate report --format briefing-doc --wait
810830
```
811831

812832
### Bulk Import

docs/development.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Contributing Guide
22

33
**Status:** Active
4-
**Last Updated:** 2026-01-21
4+
**Last Updated:** 2026-03-12
55

66
This guide covers everything you need to contribute to `notebooklm-py`: architecture overview, testing, and releasing.
77

@@ -107,9 +107,12 @@ src/notebooklm/
107107

108108
1. **Install dependencies:**
109109
```bash
110-
uv pip install -e ".[dev]"
110+
uv sync --extra dev --extra browser
111+
uv run pre-commit install
111112
```
112113

114+
CI runs the same lint gate with `uv run pre-commit run --all-files`, so local hook results should match the `quality` job.
115+
113116
2. **Authenticate:**
114117
```bash
115118
notebooklm login
@@ -125,12 +128,12 @@ src/notebooklm/
125128

126129
```bash
127130
# Unit + integration tests (no auth needed)
128-
pytest
131+
uv run pytest
129132

130133
# E2E tests (requires auth + test notebook)
131-
pytest tests/e2e -m readonly # Read-only tests only
132-
pytest tests/e2e -m "not variants" # Skip parameter variants
133-
pytest tests/e2e --include-variants # All tests including variants
134+
uv run pytest tests/e2e -m readonly # Read-only tests only
135+
uv run pytest tests/e2e -m "not variants" # Skip parameter variants
136+
uv run pytest tests/e2e --include-variants # All tests including variants
134137
```
135138

136139
### Test Structure
@@ -159,13 +162,13 @@ VCR tests record HTTP interactions for offline, deterministic replay. We have tw
159162

160163
```bash
161164
# Run all VCR tests
162-
pytest tests/integration/
165+
uv run pytest tests/integration/
163166

164167
# Run only CLI VCR tests
165-
pytest tests/integration/cli_vcr/
168+
uv run pytest tests/integration/cli_vcr/
166169

167170
# Record new cassettes (sensitive data auto-scrubbed)
168-
NOTEBOOKLM_VCR_RECORD=1 pytest tests/integration/test_vcr_*.py -v
171+
NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/test_vcr_*.py -v
169172
```
170173

171174
Sensitive data (cookies, tokens, emails) is automatically scrubbed from cassettes.
@@ -181,7 +184,7 @@ Sensitive data (cookies, tokens, emails) is automatically scrubbed from cassette
181184
### Rate Limiting
182185

183186
NotebookLM has undocumented rate limits. Generation tests may be skipped when rate limited:
184-
- Use `pytest tests/e2e -m readonly` for quick validation
187+
- Use `uv run pytest tests/e2e -m readonly` for quick validation
185188
- Wait a few minutes between full test runs
186189
- `SKIPPED (Rate limited by API)` is expected behavior, not failure
187190

docs/python-api.md

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Python API Reference
22

33
**Status:** Active
4-
**Last Updated:** 2026-03-02
4+
**Last Updated:** 2026-03-12
55

66
Complete reference for the `notebooklm` Python library.
77

@@ -31,8 +31,9 @@ async def main():
3131

3232
# Generate a podcast
3333
status = await client.artifacts.generate_audio(nb.id)
34-
final = await client.artifacts.wait_for_completion(nb.id, status.task_id)
35-
print(f"Audio ready: {final.url}")
34+
await client.artifacts.wait_for_completion(nb.id, status.task_id)
35+
output_path = await client.artifacts.download_audio(nb.id, "podcast.mp3")
36+
print(f"Audio saved to: {output_path}")
3637

3738
asyncio.run(main())
3839
```
@@ -157,10 +158,15 @@ class NotebookLMClient:
157158
chat: ChatAPI # Conversations
158159
research: ResearchAPI # Web/Drive research
159160
notes: NotesAPI # User notes
161+
settings: SettingsAPI # User settings (language, etc.)
160162
sharing: SharingAPI # Notebook sharing
163+
auth: AuthTokens # Current authentication tokens
164+
is_connected: bool # Connection state
161165

162166
@classmethod
163-
async def from_storage(cls, path: str = None) -> "NotebookLMClient"
167+
async def from_storage(
168+
cls, path: str | None = None, timeout: float = 30.0
169+
) -> "NotebookLMClient"
164170

165171
async def refresh_auth(self) -> AuthTokens
166172
```
@@ -177,8 +183,10 @@ class NotebookLMClient:
177183
| `delete(notebook_id)` | `notebook_id: str` | `bool` | Delete a notebook |
178184
| `rename(notebook_id, new_title)` | `notebook_id: str, new_title: str` | `Notebook` | Rename a notebook |
179185
| `get_description(notebook_id)` | `notebook_id: str` | `NotebookDescription` | Get AI summary and topics |
186+
| `get_metadata(notebook_id)` | `notebook_id: str` | `NotebookMetadata` | Get notebook metadata and sources |
180187
| `get_summary(notebook_id)` | `notebook_id: str` | `str` | Get raw summary text |
181-
| `share(notebook_id, settings=None)` | `notebook_id: str, settings: dict` | `Any` | Share notebook with settings |
188+
| `share(notebook_id, public=True, artifact_id=None)` | `notebook_id: str, bool, str \| None` | `dict` | Create or update a share link |
189+
| `get_share_url(notebook_id, artifact_id=None)` | `notebook_id: str, str \| None` | `str` | Get a share URL |
182190
| `remove_from_recent(notebook_id)` | `notebook_id: str` | `None` | Remove from recently viewed |
183191
| `get_raw(notebook_id)` | `notebook_id: str` | `Any` | Get raw API response data |
184192

@@ -203,8 +211,14 @@ for topic in desc.suggested_topics:
203211
summary = await client.notebooks.get_summary(nb.id)
204212
print(summary)
205213

206-
# Share a notebook
207-
await client.notebooks.share(nb.id, settings={"public": True})
214+
# Get metadata for automation or exports
215+
metadata = await client.notebooks.get_metadata(nb.id)
216+
print(metadata.title)
217+
218+
# Enable public sharing and fetch the URL
219+
await client.notebooks.share(nb.id, public=True)
220+
url = await client.notebooks.get_share_url(nb.id)
221+
print(url)
208222
```
209223

210224
**get_summary vs get_description:**
@@ -440,21 +454,20 @@ status = await client.artifacts.generate_video(
440454
# Report
441455
status = await client.artifacts.generate_report(
442456
notebook_id,
457+
report_format=ReportFormat.STUDY_GUIDE, # BRIEFING_DOC, STUDY_GUIDE, BLOG_POST, CUSTOM
443458
source_ids=None,
444-
title="...",
445-
description="...",
446-
format=ReportFormat.STUDY_GUIDE, # BRIEFING_DOC, STUDY_GUIDE, BLOG_POST, CUSTOM
447-
language="en"
459+
language="en",
460+
custom_prompt=None, # Used with ReportFormat.CUSTOM
461+
extra_instructions="..." # Optional append for built-in formats
448462
)
449463

450464
# Quiz
451465
status = await client.artifacts.generate_quiz(
452466
notebook_id,
453467
source_ids=None,
454468
instructions="...",
455-
quantity=QuizQuantity.STANDARD, # FEWER, STANDARD
469+
quantity=QuizQuantity.MORE, # FEWER, STANDARD, MORE (MORE aliases STANDARD)
456470
difficulty=QuizDifficulty.MEDIUM, # EASY, MEDIUM, HARD
457-
language="en"
458471
)
459472
```
460473

@@ -473,7 +486,8 @@ final = await client.artifacts.wait_for_completion(
473486
)
474487

475488
if final.is_complete:
476-
print(f"Download URL: {final.url}")
489+
path = await client.artifacts.download_audio(nb_id, "podcast.mp3")
490+
print(f"Saved to: {path}")
477491
else:
478492
print(f"Failed or timed out: {final.status}")
479493
```
@@ -966,6 +980,7 @@ class VideoStyle(Enum):
966980
class QuizQuantity(Enum):
967981
FEWER = 1
968982
STANDARD = 2
983+
MORE = 2 # Alias of STANDARD used by the CLI/web UI
969984

970985
class QuizDifficulty(Enum):
971986
EASY = 1
@@ -1050,6 +1065,8 @@ class SourceType(str, Enum):
10501065
PDF = "pdf"
10511066
PASTED_TEXT = "pasted_text"
10521067
WEB_PAGE = "web_page"
1068+
GOOGLE_DRIVE_AUDIO = "google_drive_audio"
1069+
GOOGLE_DRIVE_VIDEO = "google_drive_video"
10531070
YOUTUBE = "youtube"
10541071
MARKDOWN = "markdown"
10551072
DOCX = "docx"

0 commit comments

Comments
 (0)