You have a 70-minute episode and you want six Shorts out of it by tonight. An LLM can read the transcript and suggest clips in seconds. The risk is that it hands you a lovely clip titled around a number nobody said. So the podcast to Shorts workflow below has one rule: the model proposes, a script verifies, and only verified clips get cut.
Short version: transcribe with timestamps, prompt for clips as JSON that includes the exact quote, run a quote checker against the transcript, then cut with ffmpeg. I ran the checker and the cut step on 2026-10-09; the transcript and the "model output" in the example are small hand-written samples, labelled as such.
The workflow in five steps
- Transcribe with timestamps. You need segments with start and end seconds (SRT, VTT or JSON). Any transcription tool that exports these works. A plain text transcript is not enough, because you can't cut audio from text.
- Ask the model for candidates. Use the prompt below. It returns JSON, not prose, so a script can read it.
- Verify. Run the checker. It fails clips whose quote isn't in the transcript, isn't inside the stated time range, or has the wrong length.
- Review by ear. Listen to each surviving clip once. The script catches wrong words, not a clip that starts mid-thought.
- Cut and caption. ffmpeg for the cut, then your usual editor or caption tool.
If you already repurpose long content into other formats, the repurposing prompts post covers the written side. This one is the audio and video cut.
What makes a good Short clip
Decide this before you prompt, because the model will otherwise pick the funniest sentence, which often makes no sense alone. A clip works as a standalone when:
- It makes sense with no setup. Pronouns like "that" and "he" refer to something inside the clip.
- It has one claim or one story, not two.
- It starts on the first word of the point, not on "so, um".
- It ends when the point lands, not mid-sentence.
- A claim in it is something the speaker actually said, with their own hedges intact.
That last line is the one models break. In my sample, the speaker says tickets dropped "at least for us" and "I don't have a clean number." A clip that keeps the first and cuts the second misleads viewers, even though every word is genuine. Add a rule to your review: if the surrounding sentence hedges, the clip includes the hedge or it doesn't run.
The clip-selection prompt (untested template)
This is a template I wrote. I did not run it against a live model for this post, so treat the wording as a starting point and test it on one episode first.
You are selecting short-form clips from a podcast transcript.
Transcript segments (JSON, with start and end in seconds):
{{PASTE SEGMENTS}}
Pick up to 6 clips. Rules:
- Each clip must be between {{MIN}} and {{MAX}} seconds.
- Each clip must make sense with no earlier context.
- "quote" must be copied exactly, character for character, from the
segments inside the clip. Do not paraphrase, tidy or merge sentences.
- "start" and "end" must be segment boundaries taken from the input.
- If the speaker hedges a claim in an adjacent segment, extend the clip
to include the hedge.
- Do not add numbers, names or claims that are not in the transcript.
Return only a JSON array of objects:
{"id": "clip1", "start": 0.0, "end": 0.0,
"quote": "<the single most quotable sentence, verbatim>",
"title": "<max 60 characters>"}
Two design choices to copy. Asking for a verbatim quote gives you something to check. Asking for segment boundaries (not free-form times) stops the model inventing a second like 47.3 that isn't in the transcript.
The quote checker, and what it printed
Save this as verify_clips.py. It uses only the Python standard library. It normalises case and punctuation, then looks for the quote inside the segments that overlap the clip's time range (with one second of padding). If the quote isn't there it looks across the whole transcript, so it can tell you whether the problem is the time range or the words.
import json, re, sys
from difflib import SequenceMatcher
def norm(s):
s = s.lower().replace("’", "'")
s = re.sub(r"[^a-z0-9' ]+", " ", s)
return re.sub(r"\s+", " ", s).strip()
def window_text(segs, start, end, pad=1.0):
return " ".join(s["text"] for s in segs
if s["end"] > start - pad and s["start"] < end + pad)
def best_match(quote, text):
q, t = norm(quote), norm(text)
if q in t:
return 1.0
qw, tw = q.split(), t.split()
n = len(qw)
return max((SequenceMatcher(None, q, " ".join(tw[i:i+n])).ratio()
for i in range(max(1, len(tw) - n + 1))), default=0.0)
MIN_S = float(sys.argv[3]) if len(sys.argv) > 3 else 15.0
MAX_S = float(sys.argv[4]) if len(sys.argv) > 4 else 60.0
def check(segs, clip):
issues = []
dur = clip["end"] - clip["start"]
if dur < MIN_S or dur > MAX_S:
issues.append(f"duration {dur:.1f}s outside {MIN_S:g}-{MAX_S:g}s")
in_window = best_match(clip["quote"], window_text(segs, clip["start"], clip["end"]))
whole = best_match(clip["quote"], " ".join(s["text"] for s in segs))
if in_window < 0.95:
if whole >= 0.95:
issues.append("quote exists but NOT inside the clip's time range")
elif whole >= 0.8:
issues.append(f"quote only approximately matches (best {whole:.2f}): paraphrase")
else:
issues.append(f"quote NOT FOUND in transcript (best {whole:.2f})")
return issues
segs = json.load(open(sys.argv[1]))
clips = json.load(open(sys.argv[2]))
bad = 0
for c in clips:
issues = check(segs, c)
print(f"{c['id']}: {'FAIL' if issues else 'ok'}")
for i in issues:
print(" -", i)
bad += bool(issues)
print(f"{len(clips) - bad}/{len(clips)} clips passed")
sys.exit(1 if bad else 0)
Run it as python3 verify_clips.py transcript.json clips.json 5 60. The last two arguments are the minimum and maximum clip seconds. My sample transcript is a made-up 75-second talk about returns policies with nine segments, so I used a 5 second minimum. Use real values for real episodes.
I wrote five "model proposals" by hand, planting two mistakes: clip2 has a number the speaker never said ("dropped by 40 percent"), and clip4 has a real quote attached to the wrong time range. This is the real output:
clip1: ok
clip2: FAIL
- quote only approximately matches (best 0.81): paraphrase
clip3: ok
clip4: FAIL
- quote exists but NOT inside the clip's time range
clip5: ok
3/5 clips passed
Both planted errors were caught. Notice clip2 is labelled "paraphrase", not "not found". The invented number sits inside an otherwise near-identical sentence, which is exactly why a quick skim misses it. Treat any "approximately matches" result as a failure.
Limits of the checker, so you don't over-trust it:
- It checks words and time. It can't tell if a clip is coherent, funny or fair.
- It doesn't check speaker attribution. If your transcript has no speaker labels, a quote from the host can be credited to the guest in your title and still pass.
- Transcription errors flow through. If the transcript heard "fifteen" and the speaker said "fifty", the checker agrees with the transcript. Listen to any clip that contains a number or a name.
Cutting the verified clips with ffmpeg
For a clip that passed, one command does the cut. I generated a 75-second test tone to run this, because I didn't want to use a real recording. For video, swap the codec options for your own.
ffmpeg -ss 40.4 -to 52.0 -i episode.m4a -c:a aac clip1.m4a
Checking the result with ffprobe -show_entries format=duration reported duration=11.600000, which is 52.0 minus 40.4, so the timestamps from the JSON map straight to the output length. Putting -ss before -i makes ffmpeg seek in the input, which is fast; for video you can get slight frame inaccuracy when stream-copying, so re-encode for frame-exact cuts and check the first and last second by ear.
The review step the script can't do
Run this short checklist on each surviving clip:
- Does the first second contain the point, not throat-clearing?
- Is there a hedge or correction right after the end that changes the meaning?
- Is anyone named, quoted or criticised who hasn't agreed to be clipped?
- Does the title promise something the clip doesn't deliver?
- Is a claim in it checkable? If it states a fact, confirm it with the fact-checking checklist before posting, because a clip travels without the rest of the conversation.
Guest permission is worth settling before the episode, in your booking message or release. What it must say depends on your agreement and local law, so ask a professional if you're unsure. If your show runs on YouTube, your own podcast is your own content, but clipping someone else's show is where YouTube's reused-content rules bite; see what YouTube's policy pages say about AI and reused content. Check the current help pages for anything about altered or synthetic content before using AI voices or edits. For title ideas on the finished clips, the thumbnail and title testing framework covers how to test them honestly.
Titles and captions: a second prompt
Once clips pass, titles are safe to generate because the quote is fixed. A template (untested):
Here is a verified quote from a podcast clip and the 2 sentences around it.
Write 5 title options under 60 characters. Rules: use only claims present
in the text, keep any hedge ("at least for us"), no numbers that are not in
the text, no "you won't believe".
Then run the same quote logic on your titles by hand: every number in a title must appear in the clip.
What I'd skip
Fully automatic pipelines that go from episode to posted Short with no human step. The checker removes one class of error. It does not remove the clip that is accurate and still unfair to the speaker. Keep the listen-through.
Also skip trusting a model's claim that it "copied exactly". The point of the script is that you don't have to.



