github teng-lin/notebooklm-py v0.8.6

2 hours ago

Added

  • Deferred audio generation (#2506). Queue audio overviews with later=True
    in Python or --later in the CLI on Web and Android.

  • Deferred Studio generation (#2519). Queue videos, reports (including study
    guides), quizzes, flashcards, infographics and slide decks with later=True
    in Python or --later in the CLI on Web and Android. Scheduled jobs return
    scheduled; combining --later with --wait is rejected. Cinematic video
    remains unsupported for deferred generation.

  • Experimental Android Live Voice (#2509). Android clients can open
    notebook-bound client.live.connect(...) sessions with audio input/output,
    transcripts, interruption events and bounded lifecycle cleanup. Recording,
    playback and codecs remain application-owned; automatic reconnection is not enabled.

Changed

  • The Windows CLI runs on asyncio's default event loop (#2485). The
    notebooklm CLI no longer installs WindowsSelectorEventLoopPolicy at
    startup (#79). On CPython 3.12–3.14 that loop could drop chunks of large file
    uploads (AssertionError: Data should not be empty, then NETWORK_ERROR … (upload_finalize)), and it had already broken Playwright login (#89, #2011).
    Commands now use the Proactor loop, like notebooklm-mcp,
    notebooklm-server and the Python API. If commands hang inside a sandbox
    such as Sandboxie-Plus (#75), set NOTEBOOKLM_WINDOWS_EVENT_LOOP=selector;
    an unknown value fails before the command starts. On Python 3.11+ the CLI no
    longer uses the event-loop policy API that Python 3.16 removes,
    login --master-token now runs through the same loop selection, and the CLI
    hides curl_cffi's Proactor warning, whose advice to install the selector
    policy no longer applies.

Fixed

  • Android owned notebooks can be removed from recent views without an error.
    Google now returns INVALID_ARGUMENT for this no-op. The client verifies
    explicit ownership before accepting that response; failures for shared,
    missing, or unreadable notebooks still raise an error.

  • Fresh installs include typing_extensions (#2500). Declare the runtime
    dependency used by public type exports.

  • Synchronous cookie recovery honors the selected transport (#2504).
    Curl-backed recovery uses the supported curl_cffi runtime.

  • Updated locked dependencies to address reported vulnerabilities (#2513).

  • An uppercase full UUID now reaches the right notebook, source, note or
    artifact.
    The CLI and MCP resolvers passed a full UUID through in the case
    it was typed, but Google matches ids case-sensitively and its ids are always
    lowercase. Reads by an uppercase id failed with a misleading NOT_FOUND, and
    notebook_delete by one reported deleted while the notebook stayed. The
    resolvers now lowercase a full UUID before any backend call. The REST server,
    which takes ids as given in the path, is unchanged.

  • Windows CLI uploads on the selector loop no longer lose data (#2485). On
    Python 3.12–3.14, asyncio's selector loop drops a chunk of the request body
    when a Windows socket send would block, so multi-megabyte uploads failed
    with a flood of AssertionError: Data should not be empty and left the
    source stuck in preparing. When NOTEBOOKLM_WINDOWS_EVENT_LOOP=selector
    selects that loop, the CLI now installs the fix from Python 3.15, only on
    interpreters that have the bug. The default Proactor loop, the Python API,
    notebooklm-mcp and notebooklm-server leave asyncio unpatched.

  • Android audio and video downloads no longer crawl at playback speed. The
    media host, googlevideo.com, throttles a whole-file download to about
    32 KiB/s, so a 23-minute audio overview took roughly 12 minutes and often
    failed with Android transfer failed (code=transport …). The Android backend
    now fetches that host in contiguous 8 MiB ranges, which arrive at full
    speed: the same 22.8 MB file downloads in about a second. Each range is
    checked against the previous one and the declared total, and a server that
    ignores the range is still read in full.

  • Title lookups now find İstanbul from istanbul (#2476). MCP name
    resolution (notebooks, sources, notes, artifacts and Studio items) matches
    in tiers. Tier 1 is Unicode canonical caseless matching, so composed and
    decomposed spellings now agree. Only when tier 1 finds nothing does an
    accent-insensitive tier 2 run, and it raises an ambiguity error rather than
    pick between several titles. The near-miss hints and the download --name
    filter use the accent-insensitive key directly. Studio item refs gain the
    title-prefix matching the other resolvers already had for lookups and
    previews; studio_rename and a confirmed single-item studio_delete still
    need an exact title or an id, and a complete Studio listing for a title. Dotless ı still
    never matches i. The confirmation previews of share_set_access,
    share_set_user and share_remove_user now include the resolved notebook
    title, as notebook_delete already did, so a tier-2 match is visible
    before anything changes; if the notebook list cannot be read, the preview
    shows title: null instead of failing. These previews, and those of
    notebook_delete and a single-source source_delete, reuse the list read
    to resolve a name instead of listing again; the two delete previews also
    show title: null when a full-id preview cannot read the list (with a
    name, resolution fails first). Preview titles are now also found when the
    ref is a full id in uppercase. Tools that change data (renames,
    saves, adds, generation, research, chat settings, sharing changes, and
    confirmed deletes) use tier 1 only: a ref that only the accent-insensitive
    tier would match returns a VALIDATION error naming the candidates, where
    it was NOT_FOUND with a "Did you mean" hint before. Read-only tools and
    confirmation previews keep both tiers.

Don't miss a new notebooklm-py release

NewReleases is sending notifications on new releases.