Skip to content

Video memories show "Untitled memory" when no transcript

Metadata

  • Date: 2026-05-22
  • Status: fixed
  • Severity: high
  • Related issue/ticket: N/A
  • Owner: N/A

About

Overview: - Video memories captured without audio (or with inaudible audio that produces an empty transcript) are saved with title=None and display as "Untitled memory" in the feed. Audio-only memories work correctly because they always have a transcript. Visual memories generate a caption from frames, but the caption is never used as a fallback source for title generation. - This affects every video session recorded in a quiet environment or where the microphone captures no usable audio. All resulting memories land in the feed as "Untitled memory", making them indistinguishable and unsearchable.

Technical Questions: - The title generation block at step 5 of lambda_handler only runs when transcript is truthy. After the GPU generates a caption (line ~686), title is still None if transcript was absent. The update_segment call at the end of the visual enrichment path passes title=title — still None. - The caption is a rich description of the visual content (e.g. "Person typing on laptop in a coffee shop") and is 20+ characters, so generate_title would produce a valid title from it. - The generate_title guard len(transcript.strip()) < 20 exists in title_generator.py — captions easily exceed this threshold. - Bug is present since title generation was first introduced. It was latent as long as all test sessions had audio.

Resources: - main/server/worldmm/pipeline/ingest_window.pylambda_handler, step 5 title block (line ~630) and visual enrichment update_segment call (line ~767) - main/server/worldmm/llm/title_generator.pygenerate_title function - CloudWatch log group: /aws/lambda/server-IngestWindowFunction-44v8BXyEGwOz

Steps to cause failure

flowchart LR
    Start["Video session\n(no/empty audio)"] --> NoAudio["transcript = ''"]
    NoAudio --> TitleSkip["if transcript: False\ntitle = None"]
    TitleSkip --> CaptionGen["GPU generates caption\n(frames only)"]
    CaptionGen --> UpdateSegment["update_segment(title=None)"]
    UpdateSegment --> Feed["Feed shows\n'Untitled memory'"]

System

flowchart TD
    S3Frames["S3 frames"] --> IngestWindow["IngestWindow\nlambda_handler"]
    S3Audio["S3 audio (optional)"] --> IngestWindow
    IngestWindow --> Transcribe["Whisper transcription\n(if audio present)"]
    Transcribe --> TitleGen["Title generation\n(if transcript)"]
    IngestWindow --> GPU["GPU worker\ncaption()"]
    GPU --> Caption["caption string"]
    TitleGen --> UpdateDB["update_segment(title=...)"]
    Caption --> UpdateDB

caption is generated after title generation and is never used as a title source.

Reproduction Details

  1. Invoke lambda_handler with frameCount > 0 and no audio bytes (or audio that produces an empty transcript).
  2. GPU generates a non-empty caption.
  3. update_segment is called with title=None.
  4. Segment in DB has title=None.

Reproduction test: main/server/tests/integration/test_ingest_window_titles.py::TestTitleGenerationHappyPath::test_title_generated_from_caption_when_no_transcript

Notes for PR

Root cause: title generation (step 5) only uses transcript. For video sessions without audio, transcript="" so the if transcript: guard is False and title stays None. The GPU later produces a descriptive caption that could be used as the title source, but the code never attempts this fallback.

Fix: after caption is produced by gpu_worker.caption(...), add a caption-fallback block — if title is None and caption is non-empty, call generate_title(caption, ...). This mirrors the identical try/except pattern used for the transcript-based path.

Audit Log

ID Action Note Context
1 Create audit log Initialize bug investigation visual memories show "Untitled memory" in feed
2 Read source files Confirmed ingest_window.py lines 629-639 and 767-773 step 5 only runs when transcript is truthy
3 Read title_generator.py Confirmed generate_title accepts any 20+ char string caption would pass the length guard
4 Identified root cause title is never updated from caption after GPU enrichment no fallback path exists
5 Write failing test test_title_generated_from_caption_when_no_transcript confirms title is None before fix
6 Confirm test fails pytest red before patch baseline confirmed
7 Apply fix Add caption fallback block after caption_generated log line ingest_window.py ~line 694
8 Confirm test passes pytest green after patch fix verified

Verification

  • [x] Reproduced failure before fix
  • [x] Reproduction test fails before fix
  • [x] Root cause identified with evidence
  • [x] Fix applied at source (no workaround-only patch)
  • [x] Reproduction test passes after fix
  • [x] Reproduction path now passes
  • [x] Regression test added/updated
  • [x] Verified no duplicate solved-bug log exists for same root cause