# Table of Contents - [PodNotes](#podnotes) - [Commands - PodNotes](#commands-podnotes) - [Import & Export - PodNotes](#import-export-podnotes) - [Podcasts - PodNotes](#podcasts-podnotes) - [Local files - PodNotes](#local-files-podnotes) - [Transcripts - PodNotes](#transcripts-podnotes) - [Timestamps - PodNotes](#timestamps-podnotes) - [API - PodNotes](#api-podnotes) - [Templates - PodNotes](#templates-podnotes) - [Usage with QuickAdd - PodNotes](#usage-with-quickadd-podnotes) --- # PodNotes [Skip to content](https://podnotes.obsidian.guide/#podnotes) PodNotes ======== The one goal for PodNotes is to make it easier to write notes on podcasts. Here are the features that will help you do that πŸ‘‡. Features -------- * Mobile friendly β€” works on iOS and Android, including offline playback of local files and downloads * Podcast player built into Obsidian, for both audio and video episodes * Add any publicly available podcast through search, or custom feeds by URL * Track played episodes & playback progress, with continuous resume * Create podcast notes from templates with rich metadata about episodes * Bases-friendly default notes you can sort, filter, and group with [Obsidian Bases](https://help.obsidian.md/bases) * Create a feed note for an entire podcast that every episode note links back to * Capture timestamps & link directly to the time in the episode * [Transcribe episodes](https://podnotes.obsidian.guide/transcripts/) , with optional speaker labels (diarization) * Download episodes for offline playback * Support for non-podcast local audio and video files * API that can be used by plugins like [QuickAdd](https://github.com/chhoumann/QuickAdd) or [Templater](https://github.com/silentvoid13/Templater) for custom workflows Installation ------------ This plugin is in the Obsidian community plugin store. You can find it by searching in the store, or by clicking [here](obsidian://show-plugin?id=podnotes) . ### Installation with BRAT BRAT is an Obsidian plugin that helps you test beta plugins and themes. Click [here](obsidian://show-plugin?id=obsidian42-brat) to install it in Obsidian. Add `chhoumann/PodNotes` to BRAT with the `Add a beta plugin for testing` command. Now follow the appropriate instructions, which most likely will have you go and enable the plugin once it has finished installing. ### Manual installation Go to the [releases](https://github.com/chhoumann/podnotes/releases/latest) page. Download `main.js` and `manifest.json`. Create a new directory in your Obsidian vaults `.obsidian/plugins/` folder called `podnotes` and place the downloaded files there. Now refresh the plugins in Obsidian and enable PodNotes. Screenshots ----------- ### Demo ![Demo](https://podnotes.obsidian.guide/resources/demo.gif) ### Podcast Grid ![Podcast Grid](https://podnotes.obsidian.guide/resources/podcast_grid.png) ### Episode List ![Episode List](https://podnotes.obsidian.guide/resources/episode_list.png) ### Player Play audio and video episodes, adjust the speed, and pick up exactly where you left off. ![Player](https://podnotes.obsidian.guide/resources/player.png) ### Episode notes Notes are created from a template with structured, [Bases](https://help.obsidian.md/bases) \-friendly frontmatter. ![Episode note](https://podnotes.obsidian.guide/resources/podcast_note.png) ### Timestamps Capture the moment you're listening to as a clickable link straight into your notes. ![Timestamps](https://podnotes.obsidian.guide/resources/timestamps.png) ### Transcripts with speaker labels Transcribe an episode and, optionally, label who said what. ![Transcript with speaker labels](https://podnotes.obsidian.guide/resources/transcript_diarization.png) ### Browse your library with Bases Because episode notes carry structured metadata, you can query them with Obsidian Bases. ![Bases view of episode notes](https://podnotes.obsidian.guide/resources/bases_view.png) ### Podcast search ![Podcast Search](https://podnotes.obsidian.guide/resources/podcast_search.png) --- # Commands - PodNotes [Skip to content](https://podnotes.obsidian.guide/commands/#show-player) Commands ======== Show player ----------- Opens the PodNotes pane and brings it into focus. If the pane already exists but is hidden - for example in a collapsed sidebar or out of view because the right sidebar has too many icons - this command reveals it. If it does not exist yet, the command creates it in the right sidebar. You can run it from the command palette or bind it to a hotkey. PodNotes also adds a **podcast icon to the left ribbon** as a reliable way to reopen the pane. On mobile it appears in the ribbon menu, and you can hide it via Obsidian's _Manage ribbon actions_ if you prefer to use the command instead. If you are having issues with PodNotes not being shown, feel free to create an [issue](https://github.com/chhoumann/PodNotes/issues/new) . Play Podcast ------------ This will start playback if the current episode is paused. Stop Podcast ------------ This will stop playback if the current episode is playing. Toggle playback --------------- This will toggle playback between playing and paused. Skip Backward ------------- This will skip the current episode back by the amount of seconds specified in the settings. Skip Forward ------------ This will skip the current episode forward by the amount of seconds specified in the settings. Download Playing Episode ------------------------ This will download the currently playing episode. Downloads are stored in the location specified by the **Episode download path** setting. This path is a template and **must include a per-episode token** such as `{{title}}` (the default is `PodNotes/{{podcast}}/{{title}}`). A path without `{{title}}` makes every episode resolve to the same file, so downloads overwrite each other or fail. The file extension is added automatically - do not include one. Capture Timestamp ----------------- This will capture the current timestamp of the currently playing episode. See [timestamps](https://podnotes.obsidian.guide/timestamps/) for more information on timestamp templates. Capture Last 10 Seconds / Capture Last 20 Seconds ------------------------------------------------- These commands capture a linked start-end segment ending at the current playback time. When opened, the link seeks to the segment start and pauses playback at the segment end. See [timestamps](https://podnotes.obsidian.guide/timestamps/#capturing-segments) for more information on segment templates and behavior. On mobile, this command can be added to Obsidian's editor toolbar. PodNotes also registers the Media Session `previous track` action for headphone controls: when your headphones send that action, PodNotes captures the current timestamp. If a markdown editor is active, the timestamp is inserted at the cursor; otherwise it is appended to the current episode note. PodNotes does not capture timestamps on ordinary pause/play events, because that would create unwanted timestamps every time playback is paused. Increase playback rate ---------------------- This increases the current episode's playback speed by `0.1x`. Decrease playback rate ---------------------- This decreases the current episode's playback speed by `0.1x`. Reset playback rate ------------------- This resets the current episode's playback speed to the default playback rate from PodNotes settings. Create episode note ------------------- This will create a note for the currently playing episode. (This command was previously named "Create Podcast Note". The name was changed to distinguish it from the feed-level command below; existing hotkeys are unaffected.) See [templates](https://podnotes.obsidian.guide/templates/) for more information on note templates. Create podcast feed note ------------------------ This creates a note for a whole podcast (the feed as a whole), not a single episode. It does **not** require playing anything: running the command opens a picker of your saved podcasts, and choosing one creates (or opens) that podcast's note. You can also create a feed note from an episode's right-click menu ("Create feed note"). See [templates](https://podnotes.obsidian.guide/templates/#podcast-feed-notes) for the feed note template and its available tags. Copy universal episode link to clipboard ---------------------------------------- This will copy the universal episode link to the clipboard. First, it checks for the episode on iTunes to get its ID. Then, it asks pod.link for an episode ID, after which it constructs the universal episode link and copies it to your clipboard. Episode links look like this: [https://pod.link/1138055739/episode/1732808e781cc64a30d7feba0467b63a](https://pod.link/1138055739/episode/1732808e781cc64a30d7feba0467b63a) . They can be used to share the episode with others, no matter what podcast app they use. Transcribe current episode -------------------------- This command transcribes the currently playing audio episode and saves the result at the path configured in **Transcript settings**. Plain Whisper transcription and OpenAI speaker diarization require an available OpenAI secret on the current device. Deepgram speaker diarization requires an available Deepgram secret instead. In **Settings -> PodNotes -> Transcript settings**, select an existing Obsidian secret or create one for the provider you use. The command remains available when a required secret is missing so PodNotes can tell you which provider needs to be configured. If a selected secret is not available on this device, open PodNotes settings and select or create it again. --- # Import & Export - PodNotes [Skip to content](https://podnotes.obsidian.guide/import_export/#importing) Import & Export =============== In the settings panel, you will find functionality to import and export podcasts. This feature lets you import your saved podcasts from other apps, e.g. Pocket Casts. Similarly, you can also export your podcasts from PodNotes to such apps. Importing --------- To import podcasts, follow these steps: 1. Go to the PodNotes settings in Obsidian. 2. Find the "Import" section. 3. Click the "Import OPML" button. 4. A file selection dialog will open. Choose your OPML file. 5. The selected podcasts will be imported into PodNotes. Exporting --------- You can export your saved feeds to `opml` format. First designate a file path to save to (or use the default), and click _Export_. Settings & templates -------------------- Under the **Settings & templates** heading, you can move your PodNotes configuration between vaults or back it up. This covers your preferences, note/timestamp/transcript templates, file paths, saved feeds, and playlists. ![Settings & templates import/export](https://podnotes.obsidian.guide/resources/settings_import_export.png) Playback progress, downloaded-episode bookkeeping, the currently playing episode, and the episode-to-note mapping are **not** included, because they are specific to a single vault. PodNotes settings exports use format v2. API key values and the names of the Obsidian secrets selected in PodNotes are omitted by default. This keeps a destination vault's existing OpenAI and Deepgram selections unchanged when you import the file. ### Exporting settings 1. Leave **Include API keys** off for a normal settings export. To transfer the OpenAI and Deepgram keys that are available on this device, enable it explicitly. 2. Set a file name (or keep the default `PodNotes_Settings.json`). 3. Click **Export**. The settings file is written to your vault. When **Include API keys** is enabled, available values are added in plaintext under a separate top-level `secrets` payload: { "type": "podnotes-settings", "version": 2, "settings": {}, "secrets": { "openAI": "your OpenAI API key", "deepgram": "your Deepgram API key" } } Only configured keys are included. If a selected secret name exists in PodNotes settings but its value is unavailable on this device, the export stops instead of silently creating an incomplete credential backup. Open **Transcript settings**, select or create the missing secret on this device, and export again. An export containing `secrets` is sensitive. The values are plaintext in a file inside your vault, where they may sync to other devices or be read by other plugins. Keep the file private and delete it when it is no longer needed. ### Importing settings 1. Click **Import** next to **Import settings** and choose a settings file. PodNotes accepts current v2 exports, legacy v1 exports, and a raw PodNotes `data.json`. 2. Confirm the import. Your current preferences, templates, feeds, and playlists are replaced with the imported values; playback progress and downloads are kept. An import without API key values preserves the OpenAI and Deepgram secret names already selected in the destination vault. For a legacy v1 export or raw `data.json`, PodNotes recognizes the old plaintext `openAIApiKey` and `diarizationApiKey` fields and imports them as secrets instead of putting them back into plugin settings. When an import contains API keys, the confirmation names the affected providers. PodNotes stores each value under a PodNotes-owned name in Obsidian's vault-local secret storage, then updates PodNotes to reference it. Existing Obsidian secrets are never overwritten. If a PodNotes-owned name already holds a different value, the imported key is stored under a new suffixed name. Imported secret values are available only in the current vault on the current device. Repeat the import or select/create the appropriate secrets separately on another device. A file exported by a newer version of PodNotes is rejected until you update the plugin. If an episode is already open when you import, a changed default playback rate applies to the next episode you open. --- # Podcasts - PodNotes [Skip to content](https://podnotes.obsidian.guide/podcasts/#adding-podcasts) Podcasts ======== Adding podcasts --------------- You can add podcasts by searching for them in the podcast search box in settings. This searches the iTunes podcast repository. It is also possible to add custom podcast feeds by pasting the feed URL in the search box. PodNotes will try to parse the feed, and if successful, will prompt you to add it to your saved feeds. Playlists --------- PodNotes can create playlists, which are lists of episodes. For each playlist, you can specify a name and an icon. The playlists are shown in the episode grid, represented by their icons. By default, you will have a queue playlist and a favorites playlist. The queue plays from top to bottom: the episode at the top is played next. See [Reordering the queue](https://podnotes.obsidian.guide/podcasts/#reordering-the-queue) to resequence it. PodNotes also shows a Played playlist in the episode grid. It is a virtual playlist that lists episodes marked as played across all podcasts. Episodes still available in your feeds can be played or managed like normal episodes. Older played-history entries that can no longer be found in current feeds remain visible so you can mark them as unplayed. You can delete playlists by pressing the trash bin icon next to the playlist name. The icon will change to a checkmark, which should be pressed within a short duration to confirm the deletion. Episode list ------------ The episode list is a dynamic view, which will change depending on your selection. If you have no podcast selected, the episode list will show the latest episodes of all your saved feeds. If you have a podcast selected, the episode list will show all episodes of that podcast. And lastly, if you select a playlist, the episode list shows all episodes in that playlist. ### How many latest episodes are shown The "Latest Episodes" list keeps a limited number of the most recent episodes from each saved podcast. This same set is what the search box filters when no podcast is selected, so episodes older than the limit will not appear in those search results. You can change this with the **Latest episodes per podcast** setting in the PodNotes settings tab. It defaults to 10 and can be raised up to 75. Raise it to surface more of each feed's history in the Latest Episodes list and to search further back; lower it for a shorter list. Selecting an individual podcast still shows all of that podcast's episodes regardless of this setting, so the full back catalogue of any one show always remains searchable from its own view. Context menu ------------ You can right-click (desktop) or long-press (mobile) on an episode in the episode list to open the context menu. The context menu will let you * Play the episode * Mark the episode as played * Download / remove the episode * Add / remove the episode to favorites * Add / remove the episode to queue * Add / remove the episode to a playlist When you open the context menu on an episode in the queue list (shown in the player), it also offers **Move to top / up / down / bottom of queue** so you can resequence without leaving the player. Reordering the queue -------------------- The queue plays from the top down, so its order is its play order. There are two ways to change it: * **From the player's queue list:** right-click (desktop) or long-press (mobile) a queued episode and choose **Move to top**, **Move up**, **Move down**, or **Move to bottom of queue**. * **From the command palette:** run **PodNotes: Reorder Queue** to open a dedicated window listing the whole queue, where each episode has move-up / move-down / move-to-top / move-to-bottom buttons (and a remove button). This works the same on desktop and mobile and is the easiest way to resequence a long queue. The new order is saved automatically and restored the next time you open Obsidian. Episodes in the queue are kept unique by title, so adding an episode that is already queued will not create a duplicate. Turning off the queue --------------------- By default the queue fills itself: when you switch to a new episode, the one you were listening to is kept at the top of the queue, and playback continues with the next queued episode when the current one ends. If you would rather manage the queue yourself, turn off **Keep a queue of episodes you switch away from** in PodNotes settings. With it off: * episodes are no longer added to the queue automatically when you switch, and * playback no longer advances to the next queued episode on its own. You can still add, remove, and reorder episodes in the queue manually from the episode context menu. While the queue is empty in this mode, its tile in the podcast grid and its list in the player are hidden. Player ------ The player will automatically load and play the current episode. Clicking on the epsiode image will toggle episode playback. The player also features a progress bar, which you can use to seek to a specific time in the episode. You can also press the buttons on the player to skip backwards or forwards in the episode. Episode playback rate can be controlled by using the playback rate slider. This is, by default, what you have set in the settings. --- # Local files - PodNotes Local files =========== PodNotes supports local media files. You can right-click any audio or video file and click `Play with PodNotes`. In the podcast grid, you will see a playlist with a folder icon. This is a playlist of every episode you have available offline: both local media files you have played with `Play with PodNotes` and episodes you have downloaded. Removing a downloaded file also removes it from this playlist. PodNotes will attempt to treat all local files as podcast episodes. This means all standard features are available, such as timestamps, note creation, and persisting playback time. Any exceptions will be added here. Local files and downloaded episodes are played through Obsidian's native media resource path (the same mechanism Obsidian uses for embedded media), so they work on mobile (iOS and Android) as well as desktop. --- # Transcripts - PodNotes [Skip to content](https://podnotes.obsidian.guide/transcripts/#transcripts) Transcripts =========== PodNotes can create transcript notes from podcast episodes. Plain transcription uses OpenAI's Whisper model, while optional speaker diarization can use OpenAI or Deepgram. Setting Up ---------- Before you can use transcription, set up the following: 1. **OpenAI API key**: Create a key at [OpenAI's website](https://openai.com/) . In **Settings -> PodNotes -> Transcript settings**, use **OpenAI API key** to select an existing Obsidian secret or create one. Plain Whisper transcription and OpenAI diarization both use this secret. 2. **Transcript file path**: Choose where transcript files are saved. You can use placeholders such as `{{podcast}}` and `{{title}}` in the path. 3. **Transcript template**: Customize how the transcript note is formatted. ### How API keys are stored PodNotes uses Obsidian's native secret picker. The API key value is kept in Obsidian's vault-local secret storage; PodNotes stores only a provider-specific, PodNotes-owned secret name in its `data.json`, through the `openAISecretId` and `deepgramSecretId` references. If you explicitly select a shared Obsidian secret, PodNotes copies its value into a collision-safe name owned by the chosen provider. Persisted OpenAI references therefore cannot read Deepgram or foreign secrets, and persisted Deepgram references cannot read OpenAI or foreign secrets. PodNotes requires Obsidian 1.11.5 or newer because that release encrypts secret storage on disk using encryption provided by the operating system. Secret storage keeps keys out of PodNotes files and normal settings exports, but it is shared infrastructure rather than plugin isolation: other installed plugins can access the same vault-local secret collection. Secret values are local to the current vault on the current device. A selected secret name can sync with the rest of the vault configuration while its value does not. If PodNotes says that a selected secret is unavailable on this device, open **Transcript settings** on that device and select or create the secret again. When upgrading from a version that stored API keys directly in `data.json`, PodNotes moves existing OpenAI and Deepgram keys into Obsidian's secret storage before rewriting the settings file. The plaintext fields are then removed. If that migration cannot be completed and verified, PodNotes leaves the existing settings file unchanged and shows a persistent notice so you can restart the plugin and retry. The migration cannot erase copies that already exist in backups, Obsidian Sync version history, filesystem snapshots, or old plaintext settings exports. If a key may have reached an untrusted device or backup, rotate it with the provider and remove any old export files you no longer need. Creating a Transcript --------------------- To create a transcript: 1. Start playing the audio episode you want to transcribe. 2. Run **PodNotes: Transcribe current episode** from the command palette. 3. PodNotes fetches the currently playing episode's audio, reusing an existing download when available. Plain Whisper and OpenAI diarization split large audio into chunks; Deepgram diarization sends the episode in one request. 4. When transcription finishes, PodNotes creates a note at the configured transcript path. The command always uses the currently playing episode's own audio, regardless of your episode download path setting. It remains available when a required secret is missing so it can tell you which provider must be configured on the current device. Generated transcript notes are also available to workflow plugins through the [PodNotes API](https://podnotes.obsidian.guide/api/#transcript) , so tools such as QuickAdd or Templater can read the text and send it to the AI provider configured in your own macro. Transcript Template ------------------- The transcript template works similarly to the [note template](https://podnotes.obsidian.guide/templates/#note-template) , with the additional `{{transcript}}` placeholder. Speaker Diarization ------------------- By default, transcription uses OpenAI's Whisper model, which produces plain text with **no speaker labels**. Speaker diarization is an opt-in setting that labels each transcript segment by speaker: ![Transcript with speaker labels](https://podnotes.obsidian.guide/resources/transcript_diarization.png) ### Enabling it In the **Transcript settings** section, turn on **Speaker diarization** and choose a provider: ![Speaker diarization settings](https://podnotes.obsidian.guide/resources/diarization_settings.png) * **OpenAI** (`gpt-4o-transcribe-diarize`) reuses the OpenAI secret selected above. Because each request is capped at about 20 MB, a conservative margin under OpenAI's 25 MB request cap, a long episode is diarized in independent chunks. Speaker labels can therefore reset across chunk boundaries. A typical episode fits in one request and keeps consistent labels. * **Deepgram** sends the whole episode in one request, so speaker labels remain consistent throughout the episode. Create a separate key at [deepgram.com](https://deepgram.com/) , then select an existing Obsidian secret or create one under **Deepgram API key**. The Deepgram secret is used only for Deepgram diarization and is local to the current vault and device. Diarization is off by default, so existing transcripts and the plain-Whisper workflow are unchanged unless you enable it. ### Speaker label format The **Speaker label format** setting controls the prefix added before each speaker's turn. Use the `{{speaker}}` placeholder for the speaker's label: * OpenAI labels speakers `A`, `B`, `C`, … * Deepgram labels speakers `1`, `2`, `3`, … The default is `**{{speaker}}:**`, which renders as an `**A:**`\-style bold prefix. To spell out the word "Speaker", use `**Speaker {{speaker}}:**`. To put each turn in a blockquote, use `> {{speaker}}:`. The labelled transcript replaces the usual `{{transcript}}` value in your [transcript template](https://podnotes.obsidian.guide/transcripts/#transcript-template) , so you don't need to change your template to use diarization. ### Cost Diarization providers bill per minute/hour of audio (separately from any plain-Whisper usage). As of mid-2026, OpenAI's diarize model is roughly $0.006 per minute, and Deepgram's diarized pre-recorded transcription is roughly $0.0068 per minute. Check each provider's current pricing before transcribing long back-catalogues. --- # Timestamps - PodNotes [Skip to content](https://podnotes.obsidian.guide/timestamps/#settings) Timestamps ========== Timestamps can be created with the `Capture Timestamp` Obsidian command. This will make PodNotes capture the current playback time to the active note, in the format given in the plugin settings. PodNotes can also capture recent playback segments with the `Capture Last 10 Seconds` and `Capture Last 20 Seconds` commands. With the default `{{linktime}}` format, each captured timestamp becomes a clickable link that reopens the episode at that exact moment. If the feed later rearranges the episode title (for example moving a guest name), the link still resolves as long as the new title keeps the same distinctive words: ![Notes with clickable timestamp links](https://podnotes.obsidian.guide/resources/timestamps.png) Settings -------- For timestamps, you can use the following format strings: * `{{time}}`: The current playback time. Default format is `HH:mm:ss`. * `{{linktime}}`: The current playback time, formatted as a link to the current episode. Default format is `HH:mm:ss`. * `{{segment}}`: A start-end range for a captured segment. Default format is `HH:mm:ss`. * `{{linksegment}}`: A start-end range, formatted as a link that opens the current episode at the segment start and pauses at the segment end. Default format is `HH:mm:ss`. These allow for custom formatting. By using `{{time:format}}`, `{{linktime:format}}`, `{{segment:format}}`, or `{{linksegment:format}}`, you can specify a custom [Moment.js](https://momentjs.com/) format. For example, you might use `{{time:H\h mm\m ss\s}}` to get the time in the format `0h 20m 37s`. Capturing timestamps -------------------- You can use the `Capture Timestamp` command by using the `PodNotes: Capture Timestamp` command in the command palette. The timestamp is inserted at your cursor. When the cursor is inside a markdown table cell, the captured text stays on that row: any pipes are escaped and newlines are collapsed to spaces so the table is not broken. **On desktop**, it is possible to bind this command to a hotkey, which makes it faster to use while writing. You can bind hotkeys in the `Hotkeys` tab of the Obsidian settings. **On mobile**, you can bind the `Capture Timestamp` command to a button in the editor toolbar. That is the toolbar which appears when you are editing text on mobile devices. You can set this up by going to the `Mobile` tab of the Obsidian settings. When there, you can add the `PodNotes: Capture Timestamp` command to the editor toolbar. If it hasn't already been added as an option, it is either under `More toolbar options`, or you can add it manully by entering `PodNotes: Capture Timestamp` in the `Add global command` field. You can change the order of the buttons in the editor toolbar by dragging them up and down. The further up they are, the more to the left they will be. Capturing segments ------------------ You can use the `PodNotes: Capture Last 10 Seconds` and `PodNotes: Capture Last 20 Seconds` commands to insert a link for the recent playback range ending at the current playback time. Segment capture uses the same timestamp template setting. If your template uses `{{time}}` or `{{linktime}}`, PodNotes automatically uses the segment equivalent for these commands, so the default `- {{linktime}}` template inserts a linked range such as `00:01:55-00:02:05`. Clicking a segment link reopens the episode, seeks to the segment start, starts playback, and pauses when the segment end is reached. Segment links do not extract or save separate audio clips, so they work without ffmpeg or other external dependencies. --- # API - PodNotes [Skip to content](https://podnotes.obsidian.guide/api/#api) API === export interface IAPI { readonly podcast: Episode; readonly transcript: Promise; readonly isPlaying: boolean; readonly length: number; currentTime: number; playbackRate: number; volume: number; getPodcastTimeFormatted( format: string, linkify?: boolean, offsetSeconds?: number, ): string; getPodcastSegmentFormatted( format: string, startTime: number, endTime: number, linkify?: boolean, ): string; getTranscript(episode?: Episode): Promise; start(): void; stop(): void; togglePlayback(): void; skipBackward(): void; skipForward(): void; increasePlaybackRate(): void; decreasePlaybackRate(): void; resetPlaybackRate(): void; } The above functions are all accessible through `app.plugins.plugins.podnotes.api`. `podcast` --------- This returns the currently playing episode. export interface Episode { title: string, streamUrl: string url: string, description: string, content: string, podcastName: string, feedUrl?: string, artworkUrl?: string; episodeDate?: Date; } `transcript` ------------ This is a convenience getter for `getTranscript()`: const transcript = await app.plugins.plugins.podnotes.api.transcript; It returns the generated transcript note for the current episode, or `null` if no episode is loaded or no transcript file exists yet. It does not call OpenAI or create a new transcript. Generate the transcript first with PodNotes' **Transcribe current episode** command. If your transcript template includes metadata such as the title and date, that metadata is included in the returned text. Set the transcript template to `{{transcript}}` if your macro should receive only the transcript body. `getTranscript(episode?: Episode)` ---------------------------------- This reads the generated transcript note for the provided episode. If no episode is provided, it reads the current episode's transcript. const api = app.plugins.plugins.podnotes.api; const transcript = await api.getTranscript(); ### QuickAdd AI prompt example PodNotes exposes the transcript text; the AI summarization is done by your QuickAdd macro or whichever AI service/plugin your macro calls. module.exports = async (params) => { const podnotes = params.app.plugins.plugins.podnotes?.api; if (!podnotes) throw new Error("PodNotes is not enabled."); const transcript = await podnotes.transcript; if (!transcript) { throw new Error( "Generate a transcript for the current PodNotes episode first.", ); } const prompt = `Summarize this podcast transcript in five bullet points. Transcript: ${transcript}`; // Send `prompt` to the AI action/provider used by your QuickAdd macro. return prompt; }; `getPodcastTimeFormatted(format: string, linkify?: boolean, offsetSeconds?: number)` ------------------------------------------------------------------------------------ This function will return the current playback time formatted according to the given (moment) format. If `linkify` is true, the time will be linked to the current episode at the given time. This is used by PodNotes to play from the recorded time. `offsetSeconds` is optional (default 0), subtracted from the current playback time before formatting/linking, floored at 0, and also applies to the linkified timestamp. `getPodcastSegmentFormatted(format: string, startTime: number, endTime: number, linkify?: boolean)` --------------------------------------------------------------------------------------------------- This function returns a formatted `start-end` playback range. If `linkify` is true, the range links to the current episode with both `time` and `endTime` parameters so PodNotes starts at `startTime` and pauses at `endTime`. `playbackRate` -------------- Gets or sets the current player playback speed. Values are clamped to the player range. Playback controls ----------------- `start()`, `stop()`, and `togglePlayback()` control the current episode. `skipBackward()` and `skipForward()` use the skip lengths configured in PodNotes settings. `increasePlaybackRate()` and `decreasePlaybackRate()` adjust the current playback speed in `0.1x` steps. `resetPlaybackRate()` returns playback to the default playback rate configured in settings. --- # Templates - PodNotes [Skip to content](https://podnotes.obsidian.guide/templates/#file-path) Templates ========= PodNotes can create notes from templates. These templates can contain certain syntax, which will be expanded to metadata about the podcast episode you are listening to. To use templates, you can use the `Create episode note` Obsidian command (previously named `Create podcast note`). This requires you to have defined a template for both the file path and note text. PodNotes ships a sensible default for both, so the command works out of the box on a fresh install. The default note template uses structured frontmatter properties that [Obsidian Bases](https://help.obsidian.md/bases) can sort, filter, and group on (see [Using the default template with Bases](https://podnotes.obsidian.guide/templates/#using-the-default-template-with-bases) below). You can customize either template under PodNotes settings at any time, and your customizations are always preserved across updates. PodNotes can also create a note for a whole podcast (the feed). See [Podcast feed notes](https://podnotes.obsidian.guide/templates/#podcast-feed-notes) below. File path --------- This template will be used to create the file path for the note. You can use the following syntax: * `{{title}}`: The title of the podcast episode. You can add a format, e.g. `{{title:_}}` to replace spaces with underscores. * `{{podcast}}`: The name of the podcast. You can add a format, e.g. `{{podcast:_}}` to replace spaces with underscores. * `{{date}}`: The publish date of the podcast episode. Please note that this is not always available, and will be empty if it is not. * You can use `{{date:format}}` to specify a custom [Moment.js](https://momentjs.com/) format. E.g. `{{date:YYYY-MM-DD}}`. * `{{currentDate}}`: The current date (when the note is created), as opposed to `{{date}}` (the episode publish date). Supports the same format argument, e.g. `{{currentDate:YYYY-MM-DD}}`. * `{{episodeNumber}}`: The episode number (see the [note template](https://podnotes.obsidian.guide/templates/#note-template) section for how it is sourced). Use an all-zeros width to zero-pad for sortable file names, e.g. `{{episodeNumber:000}}` β†’ `042`. Empty when the number is unknown. `{{title}}` and `{{podcast}}` are sanitized so they are safe to use in a file path: the following characters are removed: `\ , # % & / { } * < > $ ' " : @ β€£ | ?`. `{{episodeNumber}}` is always file-safe. `{{date}}` and `{{currentDate}}` are inserted as-is, so when using them in a path, avoid format strings that contain path-illegal characters (e.g. `{{currentDate:HH:mm}}`). New notes are always created at the current sanitized path. When opening an existing note, PodNotes also checks the older filename sanitizer (used through 2.16, which stripped dots) and, if needed, a unique same-folder title match. Notes created before that sanitizer change, or after a feed retitles an episode, stay linked to the player. Note template ------------- This template will be used to create the note text. You can use the following syntax: * `{{title}}`: The title of the podcast episode. * `{{safeTitle}}`: The title of the podcast episode, but with all special characters removed (like `{{title}}` in file path templates). * `{{description}}`: The description of the podcast episode. * You can use `{{description:> }}` to prepend each new line with a `>` (to put the entire description in a blockquote). * `{{content}}`: The content of the podcast episode from ``. Show notes will sometimes land here. * You can use `{{content:> }}` to prepend each new line with a `>` (to put the entire content in a blockquote). * `{{podcast}}`: The name of the podcast. * `{{url}}`: The URL of the podcast episode. For a local-file episode this is a link to the file rather than a web URL. Tag values are inserted verbatim, so when you place one in a quoted YAML property (e.g. `url: "{{url}}"`) it stays valid for well-formed feed URLs and ordinary file names (a URL or file name containing a literal `"` would need escaping). * `{{stream}}`: The direct URL of the episode's media file β€” the RSS `` URL for podcast feeds, or the underlying media source for Pocket Casts and local-file episodes. Handy for embedding the raw audio/video or linking to the source. An empty string is used in the rare case no media URL is available. Available in episode note templates only. * `{{date}}`: The publish date of the podcast episode. * You can use `{{date:format}}` to specify a custom [Moment.js](https://momentjs.com/) format. E.g. `{{date:YYYY-MM-DD}}`. * `{{currentDate}}`: The current date β€” i.e. when the note is created β€” as opposed to `{{date}}`, which is the episode's publish date. Useful for a "captured on" metadata field. * Supports the same format argument, e.g. `{{currentDate:YYYY-MM-DD}}`. * `{{episodeNumber}}`: The episode number. PodNotes uses the feed's `` tag when present. If it is missing or not a number, PodNotes makes a **best-effort** guess from the start of the episode title β€” a leading marker (`#12 ...`, `Ep 12 ...`, `Ep. 12 ...`, `Ep #12 ...`, `Episode 12 ...`, `E12 ...`) or a leading number followed by a separator (`12: ...`, `12 - ...`, `12. ...`, `12) ...`). This guess can be wrong for titles that simply begin with an unrelated number (e.g. `2024: A Year in Review`), so for feeds without `` treat it as approximate. The tag is empty when no number can be determined. * You can zero-pad with an all-zeros width, e.g. `{{episodeNumber:000}}` β†’ `042` (handy for sortable file names). Any other argument is ignored and the bare number is returned. * `{{duration}}`: The episode's duration, from the feed's `` tag. Empty when the feed doesn't provide one. Not available in file-path/download-path templates β€” even though `{{duration:seconds}}`/`{{duration:minutes}}` would be file-safe, the tag is excluded from path templates entirely so the default colon-containing clock output can't accidentally end up in a file name. Note: an episode that was already the _current_ episode before you upgraded PodNotes may show an empty duration until you re-open it from its feed (older saved episodes predate this field). * With no argument it renders a human clock: `4:05` (under an hour) or `1:02:03` (an hour or more). * `{{duration:minutes}}` β†’ total whole minutes (e.g. `62`); `{{duration:seconds}}` β†’ total seconds (e.g. `3723`). * Any other argument is treated as a clock format using the tokens `H`/`HH`, `h`/`hh`, `m`/`mm`, `s`/`ss`, `A`/`a` β€” e.g. `{{duration:HH:mm:ss}}` β†’ `01:02:03`. (Unlike `{{date}}`, `[literal]` bracket escaping is not supported here.) * `{{chapters}}`: A Markdown list of the episode's chapters, using Podcasting 2.0 `` data when the feed provides an HTTP(S) chapters URL. Each line renders as `- 0:00 Chapter title`, sorted by start time. Hidden chapters (`toc: false`) are skipped, and chapter titles are inserted as escaped plain text. Empty when the episode has no chapters URL, the chapters request fails, or the chapters file contains no visible chapters. * You can use `{{chapters:> }}` to prepend each rendered chapter line with `>` (to put the chapter list in a blockquote). * `{{artwork}}`: The URL of the podcast artwork. If no artwork is found, an empty string will be used. * `{{episodelink}}`: A clickable `obsidian://podnotes` link that reopens this episode in the PodNotes player and **resumes from where you left off** (or starts at the beginning if you have never played it, or have already finished it). The resume position is resolved when you click the link β€” not baked in when the note is created β€” so the link always jumps to your latest position. Put it in your template to get a "back to the episode" link on every note, e.g. `[▢️ Resume in PodNotes]({{episodelink}})`. The value is the bare URL, so wrap it in your own Markdown link text. It is empty when the episode has no feed URL or local file path to address it by. See [issue #35](https://github.com/chhoumann/PodNotes/issues/35) . ### Linking an episode to its podcast (feed) note In an episode note, `{{url}}` and `{{artwork}}` always describe the **episode**. To reference the parent podcast (feed), use these additional tags: * `{{episodeurl}}` / `{{episodeartwork}}`: Explicit aliases of `{{url}}` / `{{artwork}}` (the episode's own URL and artwork). Use these when you also use the feed tags below and want to be unambiguous. * `{{feedurl}}`: The podcast's RSS feed URL. * `{{feedartwork}}`: The podcast's (feed) artwork. Falls back to the episode artwork if the feed isn't saved. * `{{podcastlink}}`: A ready-made wikilink to the podcast's [feed note](https://podnotes.obsidian.guide/templates/#podcast-feed-notes) . It points at the same file the feed note is created at, so episodes and the feed note link up automatically. When the feed-note path has a folder it is path-qualified (e.g. `[[PodNotes/Podcasts/My Show|My Show]]`) so it can't resolve to an unrelated note that shares the basename; otherwise it's a plain `[[My Show]]`. (Avoid putting a `{{date}}` in the feed-note path, since the episode side can't reproduce the feed note's creation date.) ### Using the default template with Bases PodNotes ships this default episode note template, which links each episode back to its feed note and exposes structured frontmatter properties for [Obsidian Bases](https://help.obsidian.md/bases) : --- type: podcastEpisode podcast: "{{podcastlink}}" date: {{date:YYYY-MM-DD}} tags: - podcastEpisode status: rating: favorite: false --- # {{title}} ![]({{artwork}}) [Resume in PodNotes]({{episodelink}}) {{url}} {{description}} The frontmatter is built so it stays **valid YAML** for every episode, because only values that can never contain a YAML-hostile character go into it: * The full episode title goes in the body as the `# {{title}}` heading, where YAML rules don't apply (a raw title can contain `"` or `:`, which would break a frontmatter scalar). * `{{podcastlink}}` is quoted so its leading `[[` isn't read as a YAML flow sequence, and the linked name is sanitized. (If you customize _Feed note file path_ to a folder containing a literal `"` or `\`, that character flows into the link verbatim β€” keep the feed-note path to ordinary path characters.)\ * `{{url}}` and `{{artwork}}` are kept in the **body** (a bare link and a Markdown image), not in the frontmatter. Tag values are inserted verbatim, and for a local-file episode `{{url}}` is a vault link whose name can contain a `"`; keeping it out of a quoted scalar means an awkward URL or file name can never break the note's properties. If your episodes all come from feeds (so `{{url}}` is always a well-formed web URL), you can add `url: "{{url}}"` back to the frontmatter.\ * `date:` is a bare `YYYY-MM-DD` (or empty/null when the feed has no publish date).\ * `status`, `rating`, and `favorite` are left for you to fill in β€” they give Bases columns to sort and filter on (e.g. mark an episode `favorite: true`, or set `status` to `to-listen`/`listening`/`listened`).\ \ A starter Bases view (save as e.g. `Podcast Episodes.base`) that lists every episode note, grouped by listening status, with a column for each property:\ \ filters:\ and:\ - 'type == "podcastEpisode"'\ views:\ - type: table\ name: Episodes\ order:\ - file.name\ - note.podcast\ - note.date\ - note.status\ - note.rating\ - note.favorite\ groupBy:\ property: note.status\ direction: ASC\ \ \ Open the base in Obsidian to sort, filter, or add views from the view options. Because `note.podcast` resolves to the linked [feed note](https://podnotes.obsidian.guide/templates/#podcast-feed-notes)\ , you can also group by show or pivot from a feed note to all of its episodes.\ \ ![Bases view of episode notes, grouped by listening status](https://podnotes.obsidian.guide/resources/bases_view.png)\ \ Podcast feed notes\ ------------------\ \ A _feed note_ is a single parent note for an entire podcast (the feed), which episode notes can link to (great for [Obsidian Bases](https://help.obsidian.md/bases)\ / Dataview rollups).\ \ Create one with the `Create podcast feed note` command (pick a saved podcast β€” no playback needed) or from an episode's right-click menu. Configure the feed note **file path** and **template** under PodNotes settings β†’ _Podcast feed note settings_. PodNotes ships sensible Bases-friendly defaults.\ \ ![A podcast feed note](https://podnotes.obsidian.guide/resources/feed_note.png)\ \ In a feed note, `{{url}}` and `{{artwork}}` describe the **feed** (the note's subject). Available tags:\ \ * `{{title}}`: The podcast's name.\ * `{{podcast}}` / `{{safeTitle}}`: The podcast's name, formatted safely for file paths/links (special characters removed).\ * `{{url}}`: The podcast's website (from the feed's ``). May be empty if the feed has no website.\ * `{{feedurl}}`: The podcast's RSS feed URL.\ * `{{artwork}}` / `{{feedartwork}}`: The URL of the podcast artwork.\ * `{{author}}`: The podcast author (``), if present.\ * `{{description}}`: The podcast's description. Supports the `{{description:> }}` prepend syntax, like episode notes.\ * `{{date}}`: The current date (when the note is created). Supports `{{date:format}}`. (In feed notes, `{{date}}` already returns the current date, so `{{currentDate}}` is not registered here β€” use `{{date}}`.)\ \ The file path template supports `{{title}}`/`{{podcast}}` (with the optional `{{podcast:_}}` whitespace-replacement format) and `{{date}}`.\ \ The default feed note path is `PodNotes/Podcasts/{{podcast}}.md`, so an episode's `{{podcastlink}}` (`[[Podcast Name]]`) resolves to it automatically. --- # Usage with QuickAdd - PodNotes [Skip to content](https://podnotes.obsidian.guide/QuickAdd/#quickadd) QuickAdd ======== I have made some QuickAdd macros & actions that might be helpful to others. Both of these are seen in the demo: ![Demo](https://podnotes.obsidian.guide/resources/demo.gif) Timestamp capture ----------------- This is how I capture timestamps so fast in the demo. You can make a Capture action like so: ![Capture](https://podnotes.obsidian.guide/resources/quickadd_timestamp_podcast.png) The capture format is as follows: \n- **```js quickadd const pn = this.app.plugins.plugins.podnotes.api; return pn.getPodcastTimeFormatted("HH:mm:ss", true); ```** | This captures a new line with the current time, linked to the current podcast, in the active file. Add podcast note ---------------- This is how I add podcast notes with QuickAdd. First, you will need my template. --- tags: in/podcast state/process aliases: - "{{VALUE:title}}" cssclass: null image: {{VALUE:artworkUrl}} --- # {{VALUE:title}} ### Metadata Type:: [[%]] Tags:: Podcast:: [[{{VALUE:podcastName}}]] Title:: {{VALUE:title}} URL:: {{VALUE:url}} Guest:: Reference:: Reviewed Date:: ==UPDATE THIS== ### Description > {{VALUE:description}} --- ## Notes Now, you should make a macro with the following script: module.exports = { entry: (params, settings) => { const pn = params.app.plugins.plugins.podnotes.api; const podcast = pn.podcast; if (!podcast) { new Notice("No podcast loaded.", 5000); throw new Error(); } params.variables = { ...podcast, ...params.variables, safeTitle: replaceIllegalFileNameCharactersInString(podcast.title), }; }, settings: { name: 'Podcast Script', author: 'Christian', options: { } } } function replaceIllegalFileNameCharactersInString(string) { return string .replace(/[\\,#%&\{\}\/*<>$\'\":@\u2023\|\?]*/g, '') // Replace illegal file name characters with empty string .replace(/\n/, ' ') // replace newlines with spaces .replace(' ', ' '); // replace multiple spaces with single space to make sure we don't have double spaces in the file name } First, create a new macro in the macro panel. This is accessed by clicking `Manage Macros`. Add a macro with any name you like. Now, add the script as the first step and the template as the second step. Adding these requires that the script and template is saved as files in your Obsidian vault. Their file names are up to you, but ensure that they end in .js and .md, for the script and template respectively. Once you have created the macro in the macro panel, you should add a macro action to the QuickAdd menu. This is done from the main QuickAdd settings. You should see an input field where you can input the name of the macro choice. Right next to it is a dropdown menu with the type of choice you'd like to addβ€”select macro here. Then click `Add Choice`. Once the choice has been added, you should see the macro in the QuickAdd menu in the settings panel. Click the cogwheel next to the macro choice to edit the macro. You'll want to select the appropriate macro that you created in the macros panel. Notably, we distinguish between a macro and a macro choice. Selecting a macro in the menu that pops up 'links' it to the macro choice, so the macro choice can execute the macro. My settings for the Template action/step in the macro are as follows: ![Template action](https://podnotes.obsidian.guide/resources/quickadd_create_note_settings.png) Which means that it creates a file with the podcast episode title as the file name in the `inputs/podcasts` folder, and then opens the file after. Ultimately, activating the macro will lead to notes like this one. ![Example note](https://podnotes.obsidian.guide/resources/quickadd_example_note.png) If you want more information / guidance on how to use QuickAdd, you can check out the [QuickAdd documentation](https://github.com/chhoumann/quickadd/) . You can also check out the [video I made to help you get started with QuickAdd](https://www.youtube.com/watch?v=gYK3VDQsZJo) . There are also similar use cases to this one, which all have similar instructions for installation. These may help: * [How I Import Literature Notes into Obsidian](https://bagerbach.com/blog/importing-source-notes-to-obsidian) * [Macro: Zettelizer - easily create new notes from headings while keeping the contents in the file](https://github.com/chhoumann/quickadd/blob/master/docs/Examples/Macro_Zettelizer.md) * [Macro: Toggl Manager - set preset Toggl Track time entries and start them from Obsidian](https://github.com/chhoumann/quickadd/blob/master/docs/Examples/Macro_TogglManager.md) * [Macro: Fetching movies and TV shows into your vault](https://github.com/chhoumann/quickadd/blob/master/docs/Examples/Macro_MovieAndSeriesScript.md) ---