openclaudia/openclaudia-skills/podcast-edit

Claude Code and agent skill by openclaudia/openclaudia-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Edit podcast audio or video — trim pre/post-show chat, remove filler words, cut silences, enhance audio quality, and cut a video version of the same edit. Use when the user asks to edit a podcast, clean up audio, remove fillers, trim a recording, or improve voice quality.

Install

npx vskill@latest install openclaudia/openclaudia-skills/podcast-edit

SKILL.md

Podcast Edit Skill

Process raw podcast/meeting recordings into polished podcast episodes.

Capabilities

  1. Smart trimming — Find where the actual podcast starts/ends by transcribing and detecting intros/outros
  2. Filler word removal — Remove verbal tics: 嗯, 呃, 啊, 哦, 对对对, um, uh, etc.
  3. Silence trimming — Cut long dead air (>2s) down to natural pauses (~0.6s)
  4. Audio enhancement — Noise reduction, EQ, multi-speaker volume balancing, loudness normalization to podcast standard (−16 LUFS)
  5. Re-cutting a finished episode — Surgically remove flagged sections from an already-rendered episode without re-running the whole pipeline
  6. Highlight clips & reel — Cut shareable soundbites and stitch a ~1-minute reel with music
  7. Video cut — Apply the same edit to a Zoom/Riverside video recording (see "Video episodes")

Prerequisites

  • ffmpeg and ffprobe installed
  • OPENAI_API_KEY in environment (for Whisper API transcription)
  • Python 3 with stdlib only (no extra deps for the helper script)
  • Optional: resemblyzer (pip install resemblyzer) — only for speaker diarization when building highlight reels

Workflow

Step 1: Inspect the audio file
bash
ffprobe -v quiet -print_format json -show_format -show_streams "INPUT_FILE"

Note: duration, sample rate, channels, codec, bitrate.

Step 2: Find podcast start/end (if user says to trim front/back)

Split into 5-minute chunks and transcribe via OpenAI Whisper API with segment-level timestamps:

bash
# Extract chunk
ffmpeg -y -i "INPUT_FILE" -ss OFFSET -t 300 -ar 16000 -ac 1 /tmp/chunk_OFFSET.mp3
# Transcribe
curl -s https://api.openai.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F file="@/tmp/chunk_OFFSET.mp3" \
-F model="whisper-1" \
-F response_format="verbose_json" \
-F language="LANG" \
-F 'timestamp_granularities[]=segment' > /tmp/transcript_OFFSET.json

Scan transcriptions for:

  • Start markers: "welcome", "hello everyone", "大家好", "欢迎", intro music, first substantive topic sentence
  • End markers: "see you next time", "bye", "下期见", "感谢收听", followed by post-show chat

Do an initial trim with -ss START -to END and -c copy (no re-encode) to create a working file.

Step 3: Remove filler words

Split the trimmed file into 5-minute chunks and transcribe each with word-level timestamps:

bash
# Extract chunks
for i in $(seq 0 300 DURATION); do
ffmpeg -y -i "TRIMMED_FILE" -ss $i -t 300 -ar 16000 -ac 1 /tmp/wchunk_${i}.mp3
done
# Transcribe each chunk (can run in parallel)
for i in $(seq 0 300 DURATION); do
curl -s https://api.openai.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F file="@/tmp/wchunk_${i}.mp3" \
-F model="whisper-1" \
-F response_format="verbose_json" \
-F language="LANG" \
-F 'timestamp_granularities[]=word' \
-F 'timestamp_granularities[]=segment' > /tmp/wtranscript_${i}.json &
done
wait

Then run the filler removal script that ships with this skill:

bash
python3 ./filler_removal.py \
--total-duration DURATION \
--end-at END_TIMESTAMP \
--cut START1:END1 --cut START2:END2 \
--chunk-offsets 0,300,600,900,...

Arguments:

  • --total-duration: Duration of the trimmed input file in seconds (required)
  • --end-at: Cut everything after this timestamp (e.g., post-show chat start)
  • --cut START:END: Cut a specific range. Can be repeated.
  • --chunk-offsets: Comma-separated chunk offsets (default: auto 0,300,600,…)

The script outputs /tmp/ffmpeg_filter.txt with an atrim+concat filter.

Apply the filter in two passes:

bash
# Step A: Cut fillers → intermediate WAV (avoids re-encoding artifacts)
ffmpeg -y -i "TRIMMED_FILE" \
-filter_complex_script /tmp/ffmpeg_filter.txt \
-map '[out]' -c:a pcm_s16le -ar 44100 /tmp/podcast_cut.wav
# Step B: Enhance audio → final MP3
ffmpeg -y -i /tmp/podcast_cut.wav \
-af "ENHANCEMENT_CHAIN" \
-c:a libmp3lame -b:a 192k "OUTPUT_FILE"

Limitations: Whisper word-level timestamps for Chinese can miss fillers that are blended into adjacent speech. The script catches standalone fillers reliably but may miss ~10–20% of embedded ones.

Step 4: Audio enhancement filter chain

Default chain (guest-friendly — handles multi-speaker volume imbalance). The biggest mistake in past runs is using a noise gate (agate) that silences the quieter guest entirely. Never add agate back to the default chain.

highpass=f=80, # Remove room rumble
lowpass=f=12000, # Remove hiss (use 7500 for 16kHz sources)
afftdn=nf=-25:nr=8:nt=w, # Gentle FFT noise reduction
equalizer=f=180:t=q:w=1.5:g=-2, # Cut mud
equalizer=f=2500:t=q:w=1.2:g=3, # Boost presence
equalizer=f=4500:t=q:w=1.5:g=1.5, # Boost clarity
dynaudnorm=f=200:g=5:p=0.95:m=5:s=0, # Rolling-window normalization — lifts the quieter speaker independently
acompressor=threshold=-20dB:ratio=2:attack=5:release=200:makeup=1, # Gentle glue
loudnorm=I=-16:TP=-1.5:LRA=13 # Podcast standard loudness

Why `dynaudnorm` is the star: it normalizes in 200 ms rolling windows, so when the guest is speaking, that window gets lifted independently of the host's louder windows. Order matters — run dynaudnorm BEFORE acompressor so the compressor sees a balanced signal.

Never add these to the default chain:

  • agate (noise gate) — cuts off any speaker quieter than the threshold; kills the guest.
  • Heavy compression (ratio >3:1, makeup >2 dB) — flattens dynamics and makes the guest sound pumped.
  • Narrow LRA (<12) in loudnorm — crushes natural speech dynamics.

Adjust lowpass based on source sample rate:

  • 16kHz source → lowpass=7500
  • 44.1kHz+ source → lowpass=12000 (or skip)

Verify guest audibility after rendering: run ffmpeg -i OUTPUT -af "ebur128=peak=true" -f null - and check I: is near −16 LUFS and LRA: is 4–6 LU (tighter LRA is fine because dynaudnorm did per-window balancing first). If the output sounds like the guest was cut, suspect a gate or aggressive compressor crept back in.

Step 5: Verify output
bash
ls -lh "OUTPUT_FILE"
ffprobe -v quiet -show_entries format=duration -of csv=p=0 "OUTPUT_FILE"

Report: duration, file size, what was removed (filler count, silence count, time saved).

Video episodes (Zoom / Riverside recordings)

When the source is a video and the user wants a cut video back (e.g. a co-host needs the edited episode to dub into another language), run Steps 1–3 exactly as above — pull the audio chunks straight out of the mp4 with -vn — then apply the same cut points to picture and sound in a single pass:

bash
# 1) same chunks + transcription as Step 3, but sourced from the video
for i in $(seq 0 300 DURATION); do
ffmpeg -y -v error -ss $i -t 300 -i SOURCE.mp4 -vn -ar 16000 -ac 1 /tmp/wchunk_${i}.mp3 &
done; wait
# 2) filler_removal.py as usual -> /tmp/ffmpeg_filter.txt
# 3) turn its keep segments into a combined video+audio filter
python3 video_cut.py /tmp/video_filter.txt
# 4) one render pass (hardware encoder; ~7 min for a 60-min 1080p episode)
ffmpeg -y -i SOURCE.mp4 -filter_complex_script /tmp/video_filter.txt \
-map '[vout]' -map '[aout]' \
-c:v h264_videotoolbox -b:v 3500k -c:a aac -b:a 160k \
-movflags +faststart episode-edited.mp4

Use -c:v libx264 -crf 21 -preset veryfast instead of h264_videotoolbox on non-Apple hardware.

Notes:

  • Build `--chunk-offsets` as `$(seq 0 300 3600 | paste -sd, -)`. A trailing empty field crashes the argument parser.
  • The result is jump-cut style. That is expected and fine for a talking-head grid; a short dissolve at 400+ cut points looks worse than a hard cut.
  • video_cut.py bakes the enhancement chain into the same pass, so unlike the audio path there is no two-pass WAV intermediate. Do not run the chain again afterwards.
  • Budget ~1.5 GB for a 60-min 1080p output — too large to email, so upload and share a link.
  • Save the keep-segment list next to the episode. Without it, a later "same cut, but as video" request has to re-derive the cuts, and they will not match the audio version you already shipped.

Output conventions

  • Format: MP3, 192 kbps, mono (unless source is stereo with separate speakers per channel)
  • Loudness: −16 LUFS (podcast standard)
  • Always two-pass: cut to WAV first, then enhance to MP3

Re-cutting an already-finished episode

When the user flags specific problems in a published episode ("a few sentences were left in", "cut the part about X", "the ending was re-recorded", "drop the duplicate intro"), do NOT re-run the whole pipeline from raw. Surgically cut the offending ranges out of the finished MP3 and re-encode once:

  1. Re-transcribe the final file in 5-min chunks (segment granularity) → one unified transcript with absolute timestamps. This is your map.
  2. For each flagged item, get word-level timestamps for just the chunk containing it (these phrases are usually embedded mid-sentence, not on segment boundaries). Pin tight in/out points.
  3. Build one atrim+concat filter that keeps everything except the cut ranges; render to WAV (pcm_s16le) then a single MP3 pass. Do not re-apply the enhancement chain — the final is already enhanced/loudnorm'd; re-running it double-processes.
  4. Verify every splice: extract an ~11s window centred on each new join (in the new timeline) and re-transcribe it. Confirm the bad audio is gone and the rejoin reads cleanly.
  5. Recompute any show-notes timeline: every timestamp after a cut shifts earlier by the summed length of all cuts before it. If the published file prepends a highlight reel, also account for the reel's duration as an offset (a re-cut reel changes length, so the whole episode shifts).
Re-cut checklist — what the first pass commonly leaves in

These survive filler/silence removal because they're blended into real sentences. Scan the transcript for them explicitly:

  • Meeting/tech chatter: "you're muted / unmute", "你声音太小 / 听得到吗", "can you see my screen", "等一下我看一下". Cut the phrase, keep the surrounding content.
  • Dead-end topics: the panel raises a product/case nobody researched, then says "我们就跳过吧 / let's skip it" — cut the whole detour, not just the skip line.
  • Re-recorded segments (esp. endings): a messy first take, then a marker like "重新开始 / 从头来 / let's restart / feels redundant", then a clean re-take. Cut the false-start take, keep the re-record. Always inspect the last ~3 min for this.
  • Pre-show / duplicate intros: a self-introduction recorded before the official start that gets repeated later — cut the pre-show copy.
Whisper API flakiness

Parallel word-level calls sometimes return empty (0 bytes). Retry the empties sequentially with a `sleep 1` between calls.

Highlight clips & 1-min reel

Cut short, shareable soundbites from a finished episode (controversial / insightful moments), and optionally stitch them into a ~1-minute reel with music.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
443
Repository forks
13
7-day trend score
30

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 16 Jul 2026, 3 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/openclaudia/openclaudia-skills/podcast-edit/badge)](https://verified-skill.com/skills/openclaudia/openclaudia-skills/podcast-edit)

Something wrong with this skill or its page? Tell us.