Skill instructions
fountain-clip-finder6 KB
View saved version →
---
name: fountain-clip-finder
description: Find the strongest clip moments in a show, write the post copy, and open a draft post for each channel.
---
## Overview
This skill searches a show's transcripts for the moments that could become a strong clip.
Four modules process the moments in order.
Module **discovery** scores the moments.
Module **media** resolves the file that each moment is cut from.
Module **boundaries** sets the span, and module **copy** writes the words around it.
For a video that Fountain does not hold, module **external-source** replaces the search.
Each clip becomes a draft post, so the user decides which clips are posted.
## Input
One of these:
- A topic, or the terms to search for.
- A kind of moment, for example funny, angry, or surprising.
- An episode, with an optional quote or approximate time.
- A person, to find the moments of one guest or host.
- One or more videos that the show never published as an episode, each a URL or a file on this
machine, with an optional topic or quote.
Optional:
- `clip_count` - the maximum number of clips to return.
The show's archive may hold fewer.
- `min_duration_seconds` and `max_duration_seconds` - the length range of a clip.
- A link that every post MUST contain, for example the landing page of a campaign.
- Trend context with its sources, when the clip must answer a news story.
This skill does not search the news, so the caller gives the sources.
## Output
One draft `SocialPost` for each clip on each connected `SocialChannel`.
The posts are ranked by the clip score of module **boundaries**.
A post targets one channel, and the platform of that channel sets the style of the text.
Thus one clip on two channels gives two posts, each with its own text.
This skill MUST write `source` when `media` is a URL.
A later renderer cuts the clip from `source`.
Module **copy** writes `meta.label`, `content.title`, `content.text`, and `context`.
Module **media** and module **boundaries** build `source` between them.
A Fountain episode source names its episode and show in `ids`.
A YouTube match for that episode adds its YouTube video id.
A standalone YouTube source names only its YouTube video id.
Another external URL uses empty `ids`.
Module **external-source** builds the last two forms.
A raw local path is not a URL, so its post holds no `source`.
Thus the render MUST happen in the same session.
The posts with `source` then wait in the Social API.
This skill does not start the next stage.
Skill **fountain-clip-producer** works from `source` and attaches the video to the post.
Skill **fountain-clip-producer** receives a raw local source directly in the same session.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Requirements
- Fountain API.
- A web search tool, for episodes that have no video on Fountain.
- Python 3.11 or later, yt-dlp for a video URL, and ffmpeg with whisper for a local video that has no
subtitle file.
Module **external-source** needs all three.
A machine without them can run every other input.
- Skill **fountain-onboarding**.
## Process
Make the calls that do not need each other's answers at the same time.
A run loses time between its actions, and not inside them.
1. Resolve the show, and list the connected `SocialChannel` with the Social API.
Run skill **fountain-onboarding** when the show has no channel.
A clip becomes a draft post on a channel, and there is no other place to keep the work.
Continue only when the user asks for the clips without a channel.
2. Run module **discovery** to search the transcripts, score each moment, and drop the weak ones.
For a video that is not an episode, run module **external-source** first.
Give its segments to module **discovery** as the passages to score.
3. Run module **media** to resolve the file that each moment is cut from, and the clock of that file.
Drop a moment when its episode has no video to cut from.
Skip this module for a video that
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 8 — file references are metadata, not package contents.
fountain-clip-producer11.1 KB
View saved version →
---
name: fountain-clip-producer
description: Render a clip on this machine, only when the user asks. To change a clip on Fountain, render it again there.
---
## Overview
This skill renders the video of a clip post on this machine, when the user asks for a local render.
Fountain renders each clip automatically, and that render is the first choice, even when it misses part of the request.
Module **media** cuts the landscape master, and every module after it works from that file.
The other modules crop the picture and put the captions and the layers on it.
The skill delivers nothing until one report passes.
## Input
- The `SocialPostMediaSource` of a `SocialPost`, which names the file and the span.
The file can have no video.
Most files of a podcast catalogue have no video.
Empty `ids` and a YouTube video id both name sources that Fountain does not hold as episodes.
- Or an external source for a raw local video, which carries the media path and span for this session.
Its post carries no `source`, because a raw local path is not a valid `media` URL.
- The word timings of that span, which this skill makes from the clip's own audio.
Module **shots** also needs the speaker of each word.
No input supplies it.
- A delivery tier, which the words of the request imply.
Optional:
- A target shape, which is vertical, square, or landscape.
- The name of a caption preset, or the text of an overlay.
## Output
- The finished work: a landscape master, and one export for each shape that the request asks for.
The master is finished work, and not one of the workings.
The user keeps it and cuts from it again.
- A `SocialPostUpload` on `content.uploads` of the post, unless the user asked you not to attach it.
- Workings: a clip manifest, a crop plan, a caption plan, an overlay plan, a QA report, a removal
report when module **trims** cut the clip, and a pace plan when module **pace** sped it up.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Requirements
- Fountain API.
- Python 3.11 or later.
- OpenCV 4.8 or later, importable from that same Python, for the face detection of module **framing**.
Module **preflight** downloads its model, the fonts that the presets name, and the overlay placeholders.
- ffmpeg and ffprobe, built with libass, drawtext, fontconfig and whisper.
Without them, the skill cannot burn a caption or time a word.
A stock build often has none of them.
On macOS, the Homebrew `ffmpeg-full` formula has them.
- A whisper.cpp model file.
The whisper filter takes the path of this file, and does nothing without it.
That file is 141 MB, so the machine installs it one time.
Module **preflight** finds the file, and prints the line that installs it.
- ImageMagick, to measure the width of caption text.
- yt-dlp, for a source that ffmpeg cannot seek directly.
Keep it current, because YouTube changes what a client must send.
A build a few weeks old gets a 403 error on every download, while the captions still download.
- A web search tool, and a way to read a page, for the reference sources of module **brand**.
## Process
1. Read the delivery tier from the request.
Do the least work that the tier asks for.
2. Run module **preflight** to check the machine before the first render.
One report serves every clip of a run, because the machine does not change between clips.
3. Run module **media** to cut the landscape master from `media`, between `ts_start` and `ts_end`.
Cut all the clips of the run together, then transcribe them all together.
No clip waits for another one.
Then transcribe the master with whisper to get the word timings of the clip.
Rebase the timings so that the first word starts at zero.
Use the binary and the model that module **preflight** names, with `max_len=1`.
Put `model=` last in the filter string, or the filter loses the option after it.
Write the output as SRT, and give it to `scripts/align-word-timings.py`.
Give the scri
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 54 — file references are metadata, not package contents.
fountain-daily-growth5.38 KB
View saved version →
---
name: fountain-daily-growth
description: Read yesterday's results and today's news, then brief fountain-clip-finder on the best trends.
---
## Overview
This skill is the first step of the daily content chain.
It runs two modules in order.
Module **performance-review** reviews yesterday's posts.
It turns the numbers of those posts into lessons in the preferences.
Module **trend-discovery** reviews today's news.
It scores the news and makes the best trends into briefs for skill **fountain-clip-finder**.
The skill itself updates the narratives first, because both modules read them.
## Input
- `show` - the show to run the loop for.
- The Narratives and Editorial sections of the preferences.
## Output
- One brief per advancing trend, handed to skill **fountain-clip-finder**.
A brief is a completed trend of module **trend-discovery**.
Each brief holds its share of the day's clip budget as `clip_count`.
- One report for the day.
It shows the posts that wait, then yesterday's numbers.
With auto-render on, the report goes out when the videos exist, and it is the only mail of the day.
- Updated preferences: the narratives, and the lessons of module
**performance-review**.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Requirements
- An HTTP client, e.g. curl, for the Google News RSS route of module **trend-discovery**.
- Optional: a web search tool, and a social trend search tool such as one for X, when the machine has them.
- Fountain API.
- Skill **fountain-clip-finder**.
- Skill **fountain-reports**.
- Skill **fountain-onboarding**.
## Process
1. Update the Narratives section, because both modules read it.
2. Run module **performance-review** to turn yesterday's posts and their numbers into lessons.
Skip it when a render machine sends the report, because that machine runs it.
3. Run module **trend-discovery** to score today's trends and shape the strongest into briefs.
4. Hand each brief to skill **fountain-clip-finder**, and do not read its result.
The chain continues without this skill.
5. List the day's drafts with the Social API, because step 4 hands the briefs on and never reads them back.
Render them with skill **fountain-clip-producer**, under the rules of Rendering below.
6. Send the day's report one time, as the `review-posts` report of skill **fountain-reports**.
The report shows the clips that wait, then the numbers of module **performance-review**.
Ask skill **fountain-reports** to send the report and also to print the same report here.
## Additional notes
Some steps repeat one API call over many items.
Examples are the numbers of each post, the news of each subject, and the drafts of each clip.
These items do not depend on each other, so ask for them all at the same time.
This skill owns the two morning modules, and none of the work after them.
Finding moments and writing the copy is the job of skill **fountain-clip-finder**.
Rendering is the job of skill **fountain-clip-producer**, run here or on a render machine that picks the
drafts up from the Social API.
The rules for rendering come from the Automation section.
Auto-render is on unless that section says otherwise.
- With auto-render on, render the drafts here as a clean final.
Then the user reviews the clip, and not a description of it.
- With no confirmed kit under Brand, render the strongest clip first, as the style proof of skill
**fountain-clip-producer**.
Render the rest after the user confirms or corrects that clip.
This is because a batch in the wrong look is rendered twice.
- With a render machine named for this show, do not render here.
The render machine renders the drafts and sends the report.
Stop after step 5, unless no draft waits for a video.
When no draft waits, the render machine renders nothing and sends nothing.
- With auto-render off, something else has to render.
Say which: the user's word in the chat, or a render machine that works this show.
The thing tha
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 3 — file references are metadata, not package contents.
fountain-onboarding4.07 KB
View saved version →
---
name: fountain-onboarding
description: Set up Fountain: show, channels, clip look, preferences, and Daily Growth. Use on first use or on request.
---
## Overview
This skill gets a podcaster from a new Fountain account to fresh clips in their own style each morning.
It walks the user through the setup, fixes what it can, and links to the rest.
The last step is a short guide to the daily drafts.
## Input
- None.
## Output
- A project with a show, connected channels, and Daily Growth on.
- Updated preferences: Brand, Editorial, Accounts, and the Narratives of the show.
- A summary in the chat: what changed, what is still missing, and who must act on it.
- A short guide to the daily work with the drafts.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Requirements
- Fountain API.
## Process
1. Fetch the projects of the user, to make sure that Fountain API is reachable.
An empty array is fine, as long as the status is 200.
If the API is not reachable, install the plugin from https://github.com/fountain-fm/fountain-skills
2. Make sure that the user has at least one project.
Otherwise, link to https://fountain.fm/studio/onboarding, where the user also chooses a plan.
3. Make sure that the project has at least one show.
Otherwise, connect the show with the Project API, or link to
https://fountain.fm/studio/{project_id}/onboarding?kind=PODCAST
A connected show costs one credit for each episode with no transcript.
Tell the user this cost before you connect the show.
4. Make sure that the project has at least one social channel, e.g. X, YouTube, or Instagram.
Connect it with the Social API, and send the user the link that approves access.
Daily Growth writes one post for each connected channel.
5. Choose the look of the clips.
Read the caption styles and the settings that Fountain renders on the clip rendering page.
Look at the artwork of the show, its website, and its existing clips.
Propose one caption style, with colors and a font that match the show, and record them under Brand.
Link the clip rendering page, where the user can preview each style.
6. Record the rules for the words of each post under Editorial, e.g. emoji, hashtags, and tone.
Record the handles of people that posts tag under Accounts.
7. Show the user the Narratives of the show, and change them as the user says.
When the show has none, write a few from its recent episodes.
8. Load the automations of the project with the Project API, and explain each one in one sentence.
Turn on Daily Growth, unless the user declines.
Another automation stays off until the user agrees to it.
9. Describe the daily routine to the user, in a few lines:
- With Daily Growth on, Fountain finds new clips each day, drafts their posts, renders the videos, and emails
a report.
The report goes to each project member who can access the show.
- The user approves and schedules each draft at the `drafts_url`, or tells the agent to do it.
- To change a clip, the user tells the agent, e.g. "make the captions bigger on my latest clip".
- Each post that goes out uses one credit.
## Additional notes
Record each preference with the Project API as soon as you or the user choose it.
Any preference that the agent asks to confirm MUST already be recorded in project preferences.
Therefore, if the user leaves the chat, the choices made so far are still recorded.
Onboarding must not feel overwhelming:
- Choose the defaults yourself, record them, and then present them for the user to confirm.
Say that the user can change each one.
- Do not present all options unless the user chooses to customize.
- Do not provide unnecessary information.
A request to run Daily Growth each day means: turn on the Daily Growth automation.
This skill installs no software, because Fountain renders the clips.
When no user is present, do only the steps that need no answer from the user.
Report what is still missing, soPreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
fountain-reports4.61 KB
View saved version →
---
name: fountain-reports
description: Build the reports the user reads - compose components into a preset, then email or print it.
---
## Overview
This skill owns how a report looks, so no caller invents its own format.
A report is a preset, which is an ordered list of components.
Each component is a markdown template that the data fills.
The caller names the preset and gives the data.
This skill composes the report.
It delivers the report the way the Reporting section asks: email, printed, combined with a later report,
or not at all.
The user customizes a preset once, in the preferences, and every later report follows that customization.
## Input
- The preset name.
- The data that the preset's components need, from the caller.
- Optional: the surface, when the user is present and asks to read the report here.
- Report customizations from the Reporting section of the preferences, when the show has any.
## Output
- The report, delivered as the Reporting section asks.
Email is the default.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Requirements
- Fountain API.
- Skill **fountain-onboarding**.
## Process
1. Read the report customizations from the Reporting section of the preferences.
A customization can drop a component, reorder them, change a subject line, or change the delivery.
2. Read the preset from `assets/presets`, and apply the customization.
3. Fill each component template from `assets/components` with the caller's data.
Drop a component whose data the caller did not give, and say so after the send.
This rule never drops a component that needs no data, because that component is never missing data.
Only a customization can drop it.
4. Deliver the report as the Reporting section asks: email via the Project API, printed in the chat,
combined into a report sent later in the same run, or not at all.
Email is the default, and goes to the addresses under Reporting.
Run skill **fountain-onboarding** when the section holds no addresses.
When the caller asks for both, send the report and also print it in the chat.
When the user asked only to read it here, print it instead of sending it.
A printed report has the same words as the sent report.
So the reader never has to open the mail to learn what the chat left out.
Say plainly when a report was composed but not sent.
A send that returns success is not proof of delivery, so say which of the two you saw.
## Additional notes
The presets:
- `performance` - the numbers for a window: headline, channels overview, yesterday's clips, learnings,
warnings.
- `review-posts-simple` - the posts that wait for a decision, and nothing else.
The reader reads the words in the dashboard, where the reader approves or deletes.
So the mail says which posts exist, and sends the reader to the dashboard.
The approve note says whether approving renders a clip or sends it.
A second preset does not do this job.
- `review-posts` - the whole day in one mail: the posts that wait for a decision, then the numbers.
The user asks for it in place of the two presets above.
The Reporting section records which of these forms the show wants.
- `settings` - the current settings, each with its origin, and the tour of the headings.
Sent when the user asks what their settings are.
A preset is named for the state that it reports.
It is never named for the occasion, or for the skill that sends it.
So any skill that starts a chain can reuse it unchanged.
The printed surface is for the review in the chat.
There the user reads the same report that the email holds, so the two never disagree.
A caller that prints and sends gives the reader one report in two places, and never two reports.
Combining joins reports, and not machines.
A report can wait only for a report that is sent later in the same run.
This is because nothing holds a pending report between machines.
A component is small and single-purpose.
A new kind of email is
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 15 — file references are metadata, not package contents.