Skip to content

feat(commands): add playback rate and media timestamp controls - #206

Merged
chhoumann merged 1 commit into
masterfrom
feat/92-playback-timestamp-command-surface
Jun 17, 2026
Merged

chhoumann merged 1 commit into
masterfrom
feat/92-playback-timestamp-command-surface

Conversation

@chhoumann

@chhoumann chhoumann commented Jun 16, 2026 •

Copy link
Copy Markdown
Owner

Adds command/API support for playback-rate control and makes timestamp capture available through both the mobile editor toolbar and Media Session controls.

This covers the command surface requested across the assigned issues:

  • playback-rate store/API methods plus Increase, Decrease, and Reset playback rate commands wired to the actual audio element
  • Capture Timestamp now registers with editorCallback, making it eligible for Obsidian's mobile editor toolbar
  • Media Session previoustrack handling captures the current timestamp from headset/media controls, inserting into the active editor when present and appending to the current episode note otherwise

I intentionally did not map ordinary play/pause headset events to timestamp capture. Those events fire for normal listening controls and would create timestamps on routine pauses; previoustrack gives a deliberate capture action while preserving playback controls.

Validation run after rebasing onto origin/master (d97e59e):

  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run build
  • npm run test (includes npm run check:a11y, 0 Svelte warnings)
  • PATH="/tmp/podnotes-docs-venv/bin:$PATH" npm run docs:build
  • isolated real Obsidian vault runtime: npx vitest run --config vitest.e2e.config.ts tests/e2e/podnotes-runtime.test.ts -t 'captures a linked segment|stops playback when a segment URI|playback-rate commands|previous-track Media Session action'
  • isolated mobile-emulation probe confirmed podnotes:capture-timestamp has editorCallback, no editorCheckCallback, and no runtime errors were captured

Runtime note: the Media Session behavior was validated in the real isolated Obsidian app by invoking the registered action handler. Physical iOS/Android headset button mapping was not validated on device in this worktree environment.

Adversarial review covered correctness/runtime behavior, API/settings persistence, mobile/MediaSession behavior, maintainability, and docs. Findings were fixed before the final validation pass.

Fixes #92
Fixes #95
Fixes #89

@chhoumann chhoumann linked an issue Jun 16, 2026 that may be closed by this pull request
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 16, 2026 •

Copy link
Copy Markdown

Deploying podnotes with  Cloudflare Pages  Cloudflare Pages

Latest commit: 56f8ed6
Status: ✅  Deploy successful!
Preview URL: https://5acafb84.podnotes.pages.dev
Branch Preview URL: https://feat-92-playback-timestamp-c.podnotes.pages.dev

View logs

@chhoumann
chhoumann force-pushed the feat/92-playback-timestamp-command-surface branch from bef5f41 to 56f8ed6 Compare June 16, 2026 20:29
@chhoumann
chhoumann marked this pull request as ready for review June 16, 2026 20:31
@chhoumann
chhoumann merged commit a8bb44a into master Jun 17, 2026
2 checks passed
@chhoumann
chhoumann deleted the feat/92-playback-timestamp-command-surface branch June 17, 2026 06:16
github-actions Bot pushed a commit that referenced this pull request Jun 22, 2026
# [2.17.0](2.16.0...2.17.0) (2026-06-22)

### Bug Fixes

* behavioral-audit logic and robustness fixes (back-end, 1/2) ([#213](#213)) ([4e2845d](4e2845d))
* **download:** default per-episode download path and migrate empty default ([#183](#183)) ([#186](#186)) ([46a6486](46a6486))
* **download:** prevent Android crash and create missing folders on download ([#178](#178)) ([ecd09d5](ecd09d5)), closes [#113](#113) [#86](#86) [#113](#113) [#86](#86)
* **lifecycle:** defer mobile podcast view startup ([#208](#208)) ([8bf9ce4](8bf9ce4))
* **notes:** cap note path length and harden folder creation ([#22](#22), [#87](#87)) ([#192](#192)) ([858e280](858e280)), closes [#87-class](#87)
* **playback:** persist listened time during playback ([#33](#33)) ([#190](#190)) ([e3433c2](e3433c2)), closes [#191](#191) [#108](#108) [#163](#163) [#183](#183)
* **playback:** play local files and downloads on iOS via resource path ([#100](#100)) ([#184](#184)) ([12c503a](12c503a))
* **player:** clear progress on episode switch to stop end-of-playback glitch ([#94](#94)) ([#194](#194)) ([59dccb3](59dccb3))
* **player:** reveal PodNotes view on Play with PodNotes so local files play ([#84](#84)) ([#198](#198)) ([5953625](5953625))
* **settings:** show labelled Add/Remove buttons in podcast search ([#109](#109)) ([#195](#195)) ([33399f5](33399f5))
* show downloaded episodes in the Local Files playlist ([#176](#176)) ([#177](#177)) ([184188c](184188c))
* **timestamps:** capture into the cursor's table cell without breaking the row ([#165](#165)) ([#203](#203)) ([964e342](964e342))
* **transcription:** always transcribe the currently playing episode ([#182](#182)) ([62b488a](62b488a)), closes [#107](#107)
* **uri:** preserve '+' in episode titles and paths for timestamp links ([#181](#181)) ([8ad7aa5](8ad7aa5)), closes [#164](#164)
* **view:** reliably reveal PodNotes view via command + ribbon icon ([#55](#55)) ([#199](#199)) ([fa1d708](fa1d708))

### Features

* add podcast segment links ([#205](#205)) ([d97e59e](d97e59e))
* **api:** expose generated episode transcripts ([e264465](e264465)), closes [#105](#105)
* behavioral-audit UI and interaction fixes (front-end, 2/2) ([#215](#215)) ([894d93d](894d93d))
* **commands:** add playback rate and media timestamp controls ([#206](#206)) ([a8bb44a](a8bb44a))
* **devx:** isolated per-worktree Obsidian E2E vault wrapper ([#188](#188)) ([a8b7a4a](a8b7a4a))
* **episodes:** add a setting to control the Latest Episodes list length ([#114](#114)) ([#200](#200)) ([7b3e3c6](7b3e3c6))
* **notes:** add {{episodelink}} template tag to resume an episode from its note ([#35](#35)) ([#193](#193)) ([8c1ddd6](8c1ddd6))
* **notes:** add podcast feed-level notes ([#163](#163)) ([#187](#187)) ([db0de47](db0de47)), closes [#161](#161) [#160](#160)
* **notes:** ship a Bases-friendly default episode note template ([#160](#160)) ([#201](#201)) ([209431d](209431d)), closes [#163](#163) [#183](#183)
* **player:** scale episode title font size to its length ([#81](#81)) ([#202](#202)) ([659b6b8](659b6b8))
* **player:** support video episode playback ([#209](#209)) ([f92a91f](f92a91f))
* **queue:** add setting to disable queue auto-population and auto-advance ([#108](#108)) ([#185](#185)) ([cf3d73c](cf3d73c))
* **queue:** allow reordering the playback queue ([#80](#80)) ([#179](#179)) ([d994d61](d994d61)), closes [#173](#173)
* **settings:** import/export settings & templates ([#180](#180)) ([a27d23d](a27d23d)), closes [#162](#162) [#162](#162)
* **templates:** add {{currentDate}}, {{episodeNumber}}, {{duration}} template variables ([#189](#189)) ([ec573eb](ec573eb)), closes [#75](#75) [#34](#34) [#88](#88) [163/#186](#186)
* **templates:** add episode chapters tag ([#207](#207)) ([9c98863](9c98863))
* **transcripts:** opt-in speaker diarization for transcripts ([#168](#168)) ([#204](#204)) ([a96e12f](a96e12f))
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.17.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FR: Timestamp with headphones (on mobile) [Feature request]: Hotkeys for playback rate adjustment Capture timestamp not showing up for toolbar

1 participant