agentsclimarketplace

Transcribe and cut video

Skill ciro-rosa/claude-skills/transcribe-and-cut-video

Use when the user sends an MP4 video and wants it transcribed and split by topic. Triggers on "process video", "transcribe audio", "cut video by topic", "split lesson", "lecture", "MP4 transcription", or any workflow combining faster-whisper audio transcription with ffmpeg video segmentation.From its SKILL.md

Install
npx -y skills add ciro-rosa/claude-skills --skill transcribe-and-cut-video

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.5 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it

Transcribe and Cut Video by Topic

Overview

Transcribes the audio of an MP4 using faster-whisper (CPU, tiny model), identifies topics from the spoken content, and cuts the video with ffmpeg — no re-encoding, no quality loss.

Works in memory-constrained environments (3–4 GB RAM, no GPU, no swap).

When to Use

  • User sends an .mp4 to transcribe and/or split by topic
  • Lectures, webinars, testimonials, podcasts — any spoken-word video
  • Low-resource environment: CPU-only, limited RAM, no swap

Full Workflow

1. Check Dependencies

python3 -c "import faster_whisper; print('OK')" 2>/dev/null || \
  pip install faster-whisper --break-system-packages -q
which ffmpeg

⚠️ Do NOT use openai-whisper — it requires PyTorch (~530 MB) and will likely run out of disk space. faster-whisper uses CTranslate2 and is much lighter.

2. Extract Audio (always do this first)

Reduces memory footprint and speeds up transcription:

ffmpeg -i "video.mp4" -vn -ar 16000 -ac 1 -c:a pcm_s16le audio.wav -y

3. Transcribe

Short videos (< 30 min): transcribe the WAV directly.

Long videos (≥ 30 min): split into 30-minute chunks and transcribe each one separately — prevents OOM kill.

# Create chunks (replace TOTAL_SECONDS with actual video duration)
mkdir -p chunks
for i in $(seq 0 1800 TOTAL_SECONDS); do
  IDX=$((i / 1800 + 1))
  ffmpeg -i audio.wav -ss $i -t 1800 -c copy \
    chunks/chunk_$(printf "%02d" $IDX).wav -y 2>/dev/null
done

Save as transcribe_chunk.py and run once per chunk:

import sys, json, os
from faster_whisper import WhisperModel

chunk_idx   = int(sys.argv[1])
chunk_start = (chunk_idx - 1) * 1800  # time offset in seconds

model = WhisperModel("tiny", device="cpu", compute_type="int8",
                     download_root=os.path.expanduser("~/whisper_models"))

segments, _ = model.transcribe(
    f"chunks/chunk_{chunk_idx:02d}.wav",
    language="pt",   # change to "en" for English
    beam_size=3,
    vad_filter=True,
    vad_parameters=dict(min_silence_duration_ms=700)
)

results = [
    {
        "start": round(s.start + chunk_start, 2),
        "end":   round(s.end   + chunk_start, 2),
        "text":  s.text.strip()
    }
    for s in segments
]

with open(f"chunks/chunk_{chunk_idx:02d}.json", "w", encoding="utf-8") as f:
    json.dump(results, f, ensure_ascii=False, indent=2)

print(f"[Chunk {chunk_idx}] {len(results)} segments saved.")

Run for each chunk:

for i in $(seq 1 NUM_CHUNKS); do
  python3 transcribe_chunk.py $i
done

4. Merge Chunks and Save Transcript as .md

import json, os

all_segs = []
for i in range(1, NUM_CHUNKS + 1):
    with open(f"chunks/chunk_{i:02d}.json", encoding="utf-8") as f:
        all_segs.extend(json.load(f))

def fmt(s):
    h = int(s) // 3600
    m = (int(s) % 3600) // 60
    sec = s % 60
    return f"{h}h{m:02d}m{sec:04.1f}s" if h else f"{m:02d}m{sec:04.1f}s"

video_name = "your-video-name"
output_dir = f"output/{video_name}"
os.makedirs(output_dir, exist_ok=True)

md = f"# Transcript — {video_name}\n\n"
for seg in all_segs:
    md += f"**[{fmt(seg['start'])} → {fmt(seg['end'])}]** {seg['text']}\n\n"

with open(f"{output_dir}/{video_name}_transcript.md", "w", encoding="utf-8") as f:
    f.write(md)

5. Identify Topics and Present to User

Analyze the transcript and propose 3–8 coherent topics with timestamps. Present as a table before cutting:

#TopicStartEnd
1Introduction00:00:0000:15:00
2Core Concept00:15:0000:45:00
…………

⚠️ Always wait for user confirmation before cutting.

6. Cut with ffmpeg (after confirmation)

ffmpeg -i "video.mp4" -ss HH:MM:SS -to HH:MM:SS -c copy \
  "output/Part N - Topic Name.mp4" -y

-c copy = stream copy, no re-encoding — fast and lossless.

Output Structure

/VideoName/
  ├── VideoName_transcript.md
  ├── Part 1 - Introduction.mp4
  ├── Part 2 - Core Concept.mp4
  └── Part N - Conclusion.mp4

Rules

  • File names must not contain accents, special characters, or characters invalid for the filesystem
  • Temporary files (WAV, chunks, JSONs) stay in the session's temp folder — not delivered to user
  • Default language: "pt" for Portuguese, change to "en" for English
  • Never cut the video without user confirmation
  • Output files always go in a subfolder named after the original video

Common Errors

ProblemCauseFix
Killed (exit 137)OOM — long video loaded entirely into RAMUse chunk strategy
No space left on deviceopenai-whisper tries to install PyTorch (530 MB)Use faster-whisper instead
Transcription interruptedSession timeout on long videoTranscribe chunk by chunk
Wrong timestamps after mergingMissing time offsetAdd (chunk_idx - 1) * 1800 to each segment's start/end
Model re-downloaded every sessionCache path is session-specificUse ~/whisper_models as download_root

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.