API
Read and control the PodNotes player from your own scripts through app.plugins.plugins.podnotes.api.
It works wherever a script can reach Obsidian’s app, such as a QuickAdd script, a Templater template, or the developer console.
The API exists while PodNotes is enabled, and it works while the PodNotes view is closed. For links that open PodNotes, see PodNotes URI.
export interface IAPI { readonly podcast: Episode; readonly transcript: Promise<string | null>; 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<string | null>; start(): void; stop(): void; togglePlayback(): void; skipBackward(): void; skipForward(): void; increasePlaybackRate(): void; decreasePlaybackRate(): void; resetPlaybackRate(): void;}podcast
Section titled “podcast”The loaded episode, also while it is paused. After Obsidian starts, it is the episode that PodNotes restored, before you play it.
IAPI declares Episode, but the value is undefined until an episode is loaded.
export type EpisodeMediaType = "audio" | "video";
export interface Episode { title: string; streamUrl: string; url: string; description: string; content: string; podcastName: string; feedUrl?: string; guid?: string; artworkUrl?: string; episodeDate?: Date; itunesTitle?: string; episodeNumber?: number; duration?: number; chaptersUrl?: string; mediaType?: EpisodeMediaType;}streamUrlis the media source.urlis the episode’s web page. It is the feed URL when the episode has no link, and a vault link for a local file.feedUrlholds the placeholder of a private feed that you added and that PodNotes recognizes, instead of a URL you can fetch. For an episode of a private feed you have not added, opened from a link, it holds the private address.guidis the episode’s ID in its feed, from<guid>. Links and notes use it to find the episode after the podcast renames it. It is missing when the feed gives no ID, or gives the same ID to several episodes.durationis the length in seconds that the feed reports. It can differ from the player’s measuredlength.- A local file has
podcastName: "local file", an emptydescriptionandcontent, and an optionalfilePath.
isPlaying
Section titled “isPlaying”true while the episode plays, and while its media loads to play.
false when the episode is paused, has ended, or failed to load, and for the episode PodNotes restores when Obsidian starts, until you play it.
length
Section titled “length”The duration of the loaded episode in seconds. Before the media loads, it is the duration PodNotes saved for the episode, or else the duration the feed gives, or else 0.
currentTime
Section titled “currentTime”Gets or sets the playback position in seconds. Before the media loads, it is the position where playback starts, such as the saved position of the episode PodNotes restored. Setting it cancels the end of an active segment, so playback no longer pauses there. PodNotes ignores a value that is negative or not a finite number. Once the media loads, a position at or past the end moves to 0.25 seconds before the end, and playback pauses.
volume
Section titled “volume”Gets or sets the volume, from 0 to 1.
PodNotes clamps finite values to that range and ignores values that are not finite.
PodNotes uses one volume for every episode, the one the full player’s volume button sets, and keeps it when Obsidian restarts.
transcript
Section titled “transcript”A shortcut for getTranscript() with no argument:
const transcript = await app.plugins.plugins.podnotes.api.transcript;It resolves to the text of the current episode’s transcript note.
It resolves to null when no episode is loaded or the episode has no transcript note yet.
It never calls a transcription provider. Run PodNotes: Transcribe current episode to create the note.
The text is the whole note.
If your Transcript template adds a title and date, the text includes them. A template of only {{transcript}} returns only the transcript.
getTranscript()
Section titled “getTranscript()”getTranscript(episode?: Episode): Promise<string | null>Reads the transcript note of episode, or of the current episode when you omit it.
PodNotes finds the note at the Transcript path rendered for that episode.
It resolves to null when there is no episode or no note, and rejects when the note cannot be read.
const api = app.plugins.plugins.podnotes.api;const transcript = await api.getTranscript();QuickAdd AI prompt example
Section titled “QuickAdd AI prompt example”Send a transcript to an AI prompt has a QuickAdd user script that returns a prompt with the current episode’s transcript.
getPodcastTimeFormatted()
Section titled “getPodcastTimeFormatted()”getPodcastTimeFormatted(format: string, linkify?: boolean, offsetSeconds?: number): stringReturns the current playback time, formatted with the time tokens. api.getPodcastTimeFormatted("HH:mm:ss", true) returns a link such as [00:12:41](obsidian://.
linkifydefaults tofalse. Withtrue, the result is a Markdown link that opens PodNotes at that time, with the episode’sguidwhen it has one. The result stays plain text when the episode has no feed or local file to link to, or when a link would show a private feed’s address, as for an episode of a private feed that you have not added.offsetSecondsdefaults to0. PodNotes subtracts it before formatting and linking, and never goes below zero.
Throws "No podcast loaded" when no episode is loaded.
getPodcastSegmentFormatted()
Section titled “getPodcastSegmentFormatted()”getPodcastSegmentFormatted( format: string, startTime: number, endTime: number, linkify?: boolean,): stringReturns a start-end range, formatted with the time tokens.
startTimeandendTimeare in seconds. Both must be finite. PodNotes raises negative values to zero, and the end must be after the start.linkifydefaults tofalse. Withtrue, a valid range becomes a link withtimeandendTime, so playback pauses at the end.- An invalid range returns plain text. So do the cases in which
getPodcastTimeFormatted()returns plain text.
There is no offset parameter. Throws "No podcast loaded" when no episode is loaded.
playbackRate
Section titled “playbackRate”Gets or sets the current playback speed, from 0.5 to 4, rounded to hundredths, so 1.25 stays 1.25.
A value that is not finite sets the speed to Default speed.
Setting the speed does not change Default speed. The speed lasts until a different episode loads, which starts at Default speed.
Playback controls
Section titled “Playback controls”start()plays the current episode from where it is. After Obsidian starts, it plays the restored episode from its saved position. A finished episode starts over, unless you moved its position after it finished, or another device synced a position before the end.stop()pauses the current episode and saves its position.togglePlayback()switches between playing and paused.skipBackward()andskipForward()move by Skip back (s) and Skip forward (s). An invalid length falls back to 15 seconds.- A backward skip stops at the start. A skip keeps the episode playing or paused. When the duration is known, a forward skip that would reach the last 0.25 seconds stops 0.25 seconds before the end, or stays where it is when the position is already closer to the end. A playing episode then ends, and the next episode in the queue starts if Queue episodes I switch away from is on.
increasePlaybackRate()anddecreasePlaybackRate()change the current speed by0.1, within0.5to4.resetPlaybackRate()sets the current speed to Default speed.