M1-14: Assemble the final transcript at stop, and after a crash #22

Closed
opened 2026-08-07 09:45:27 -04:00 by agent · 0 comments
Member

Assemble the transcript parts into one .vtt next to the audio when a recording stops.

Issue #9 writes parts and says assembly is done by hand. It should not be — the vault expects a
capture to arrive as a pair, and right now only half of it does:

2026-08-06-090139-tjgcaz_audio.m4a
2026-08-06-090139-tjgcaz_transcription.vtt   <- this, and it is not written
2026-08-06-090139-tjgcaz.parts/              <- only this

Wes, in a voice memo on 2026-08-07: "does the phone automate, is it automatically piecing
together those transcripts, the parts, or is that the next phase? I feel like it was supposed to
be in issue number nine, but I don't recall exactly."
Confirmed as wanted the same morning:
"the final transcription should be written after all stop."

Scope

  • At stop, after the last part is written, assemble every part into
    <base>_transcription.vtt in the documents directory, beside the audio.
  • One WEBVTT header, then every cue block in order. Nothing else has to change: cue numbers
    are already continuous across parts and timestamps are already absolute, so assembly is
    concatenation of cue blocks and not arithmetic. That was the point of #9's design.
  • Atomic, like the parts. Half a transcript appearing next to a finished recording is worse
    than none, because a consumer cannot tell.
  • Assemble by reading the parts back off disk, not from the cues held in memory. The recovery
    case below needs a path that works with no process state, and one path that is always exercised
    beats a second one that only runs after a crash.

The case that makes this more than a convenience

A recording that ends because the app was killed never reaches stop(). #7 established that this
happens — a route change with the phone locked terminated the app repeatedly, and the fragmented
.m4a design is what saved the audio. The parts survive the same way; the assembled file does
not, because nothing ran to write it.

So a capture with a .parts folder and no _transcription.vtt beside it is a recording that
died. On the next launch, assemble it. That is the check, and it is cheap.

Open decision — does .parts survive assembly?

Once the assembled file exists the parts are redundant, and leaving both means the same words are
on disk twice with nothing saying which a consumer should read.

Removing the folder is the tidier end state and makes "a .parts folder exists" mean exactly
"this capture is unfinished", which is what the recovery check above wants to key on. Against it:
the parts are the only artifact if assembly itself is what fails, and deleting them turns one bad
write into lost text.

Recommendation is to remove it only after the assembled file is confirmed on disk. Wes to confirm.

Not in scope

Anything that touches the audio. One memo is still one continuous .m4a and nothing here changes
that.

Done when

  • Stopping a recording leaves <base>_audio.m4a and <base>_transcription.vtt side by side, and
    the .vtt opens in a subtitle player against the audio.
  • The assembled file is byte-identical in cue content to concatenating the parts by hand.
  • Killing the app mid-recording and relaunching produces the assembled file for that capture.
  • A recording during which nobody speaks produces no .vtt and no empty file to explain.
Assemble the transcript parts into one `.vtt` next to the audio when a recording stops. Issue #9 writes parts and says assembly is done by hand. It should not be — the vault expects a capture to arrive as a pair, and right now only half of it does: ``` 2026-08-06-090139-tjgcaz_audio.m4a 2026-08-06-090139-tjgcaz_transcription.vtt <- this, and it is not written 2026-08-06-090139-tjgcaz.parts/ <- only this ``` Wes, in a voice memo on 2026-08-07: *"does the phone automate, is it automatically piecing together those transcripts, the parts, or is that the next phase? I feel like it was supposed to be in issue number nine, but I don't recall exactly."* Confirmed as wanted the same morning: *"the final transcription should be written after all stop."* ## Scope - At stop, after the last part is written, assemble every part into `<base>_transcription.vtt` in the documents directory, beside the audio. - **One `WEBVTT` header**, then every cue block in order. Nothing else has to change: cue numbers are already continuous across parts and timestamps are already absolute, so assembly is concatenation of cue blocks and not arithmetic. That was the point of #9's design. - **Atomic**, like the parts. Half a transcript appearing next to a finished recording is worse than none, because a consumer cannot tell. - **Assemble by reading the parts back off disk**, not from the cues held in memory. The recovery case below needs a path that works with no process state, and one path that is always exercised beats a second one that only runs after a crash. ## The case that makes this more than a convenience A recording that ends because the app was killed never reaches `stop()`. #7 established that this happens — a route change with the phone locked terminated the app repeatedly, and the fragmented `.m4a` design is what saved the audio. The parts survive the same way; the assembled file does not, because nothing ran to write it. So a capture with a `.parts` folder and no `_transcription.vtt` beside it is a recording that died. On the next launch, assemble it. That is the check, and it is cheap. ## Open decision — does `.parts` survive assembly? Once the assembled file exists the parts are redundant, and leaving both means the same words are on disk twice with nothing saying which a consumer should read. Removing the folder is the tidier end state and makes "a `.parts` folder exists" mean exactly "this capture is unfinished", which is what the recovery check above wants to key on. Against it: the parts are the only artifact if assembly itself is what fails, and deleting them turns one bad write into lost text. Recommendation is to remove it only after the assembled file is confirmed on disk. Wes to confirm. ## Not in scope Anything that touches the audio. One memo is still one continuous `.m4a` and nothing here changes that. ## Done when - Stopping a recording leaves `<base>_audio.m4a` and `<base>_transcription.vtt` side by side, and the `.vtt` opens in a subtitle player against the audio. - The assembled file is byte-identical in cue content to concatenating the parts by hand. - Killing the app mid-recording and relaunching produces the assembled file for that capture. - A recording during which nobody speaks produces no `.vtt` and no empty file to explain.
wk closed this issue 2026-08-08 12:33:09 -04:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Stash/stash-ios#22
No description provided.