SkillsSkill for Claude

Post-match reel selects from match day clips

For the one person at a club who films the match and cuts the post-match reel: Claude takes the folder of camera clips and the match report, keeps only the clips around each goal and after full time, prices them against your Vivu plan, indexes them in a private project, searches for players piling on the scorer, the handshake line, the bench jumping up and supporters with flags, checks every window on a contact sheet, marks the loudest second of the cheer, and writes a selects sheet you cut from yourself.

Maintained by Vivu. Updated 2026-09-28.

Download

post-match-reel-selects.zip

9 KB. Unzips to post-match-reel-selects/SKILL.md. Upload the zip as it is in the Claude app, or unzip it into your skills folder for Claude Code.

SHA-256 de8a4201d2814dc355286047ea05f880c55f7018b22a9b730ca655f0c785a9be

At a glance

What the Post-match reel selects from match day clips skill does, where it runs, what it needs, and when it asks
Looks forThe seconds where players pile on the scorer, the teams shake hands at full time, the bench gets up and supporters wave flags: moments a file name like C0047.MP4 and a goal minute in the report cannot point to. Every window is checked on a contact sheet from your own clip before it goes on the sheet.
Runs onClaude Code on your computer (terminal or the Code tab of Claude Desktop), because it reads your local clips with ffprobe and makes contact sheets and loudness readings with ffmpeg. No residential IP, nothing posted, nothing scheduled.
Needs
  • The Vivu connector with write access, to create a private project, open its upload page and search.
  • ffmpeg and ffprobe on the computer that holds the clips, to read clip times, make contact sheets and measure loudness.
  • The match day clips on local disk, because Vivu has no export tool and frames come from your files.
  • The match report with goal minutes and the kick-off time on the camera clock, to pick the clips worth indexing.
  • A browser that can open the Vivu upload page, since the connector has no direct upload tool.
Your Vivu planUses index minutes for the kept clips only (the clips around each goal and after full time) and about 20 search credits per match as an estimate, for the standing precise searches. Claude shows the minutes and the credit estimate against your plan before uploading. In our test run 12 clips, 7.7 minutes in total, were ready in 5.6 minutes.
Asks you firstBefore uploading, to confirm the footage is your club's own, that guardian consent covers any youth match, and the kept clip list; before spending index minutes and credits; before writing the full sheet, to ask whether anyone asked not to appear and to approve one sample row per segment.

The skill does its video work through the Vivu connector. If the connector is not in your Claude yet, add it first; the skill checks that it is connected before it does anything else.

Before you run it

  • Use only footage your club filmed itself; do not import broadcast feeds or platform links.
  • For youth matches, go ahead only when the club holds guardian consent; the skill does not identify players, read shirt numbers or recognize faces.
  • Search results are candidates: each window is checked on a contact sheet, and in our test run 2 of the goals had no celebration window and were found on per second contact sheets.
  • Crowd and bench searches are weak: in our test run the crowd search returned 3 false of 4, mostly players celebrating in front of supporters, and an empty result does not prove there is no such shot.
  • Claude in Chrome uploads at most 10 MB per call; larger clips are added by you in the Vivu web app.
  • Clips stay in your Vivu project until you delete them; the project is created private because the default is visible to your whole organization.

Start it

Once the skill is installed, ask for the task in your own words. Naming the skill is the most reliable way to have Claude use it. For example:

Here are today's match clips in ~/Footage/2026-10-04 and the match report: we won 3-1, goals 14', 50', 63', theirs 71', kick-off 15:00 on the camera clock. Find the celebrations, the handshakes and any crowd shots and give me a selects sheet for the reel.

In Claude Code you can also type /post-match-reel-selects. Claude asks for anything the request leaves out, most important first.

What is inside

  1. When to use
  2. Working principles
  3. What you need before starting
  4. Inputs to collect
  5. Files and state
  6. Step 1: Check the Vivu connector and the setup
  7. Step 2: Pick the clips around each goal minute
  8. Step 3: Price the indexing and get approval
  9. Step 4: Upload and index
  10. Step 5: Run the four searches and check every window
  11. Step 6: Fill gaps from contact sheets and mark the cheer
  12. Step 7: Assemble selects.csv and confirm the sample
  13. Compliance
  14. Known failure modes

The full skill

This is post-match-reel-selects/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: post-match-reel-selects
description: "Turn a club's match day camera clips and the match report into a selects sheet for the post-match reel with Vivu: goal celebrations, full time handshakes, crowd shots, each checked on frames."
---

Post-match reel selects from match day clips

This skill is for the one person at a club or association who films the match and cuts the post-match reel. The user gives Claude the folder of camera clips from match day (files named C0001.MP4, MVI_0123.MP4 and so on, 10 seconds to 2 minutes each) and the match report with goal minutes and the final whistle. Claude keeps only the clips around each goal and after full time, prices them against the user's Vivu plan, uploads and indexes them in a private Vivu project, runs four standing searches (players piling on the scorer, the handshake line at full time, the bench jumping up, supporters with flags or scarves), checks every returned window on a contact sheet, marks the loudest second of the cheer from the clip's own sound, and writes selects.csv: one row per moment with the source file, start and end, a frame, what the picture shows, the cheer peak, the report minute and an empty "use" column. The user cuts the reel; Claude does not edit anything.

The value is in what the file names and the report cannot tell you. C0047.MP4 says nothing about what it caught, and "63' goal" does not say which of the four clips from that minute has the players running to the corner flag, whether the camera caught the handshakes or was pointed at the stand, or which clip has the bench on its feet. The cheer has no transcript either. Only the pictures and the sound answer that, and every row on the sheet has been looked at on frames before it is written.

When to use

Use when a club videographer or media officer says "find the celebrations in today's clips", "which clips have the goals and the handshakes", "pull selects for the post-match reel", or "log the match day footage against the match report". For a single question about one clip, search Vivu directly or scrub the clip. For a full match recording from one fixed camera, where the question is "where is each goal", this skill is the wrong fit: it assumes many short clips and a match report. It does not identify players, read shirt numbers or cut a highlight reel.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. Nothing goes on the sheet until it has been checked on frames from the user's own file. Vivu's results are candidates until then, and the reason text is a description, not a check.
  3. Stop and tell the user when a required capability or file is missing (no match report, no ffmpeg, no write access in Vivu). Do not guess around it.
  4. Ask the user before anything that is expensive to redo or that acts on their behalf: the clip list before upload, the indexing cost, the sample rows before the full sheet.
  5. Claude never names a player. Names and shirt numbers go into the sheet only when the user types them in.

What you need before starting

Check each item at the start of the run and tell the user plainly what is missing.

Requirement Why How to check
Vivu connector with write access create a private project, open its upload page, search vivu_get_account shows can_create_projects: true (tool names may carry a server prefix). A write call failing with "has not granted vivu.write" means the connection is read only; the user reconnects Vivu and allows write access
A shell with ffmpeg and ffprobe on the computer that holds the clips read clip times, measure minutes, make contact sheets, measure loudness ffmpeg -version and ffprobe -version
The match day clips on local disk, one folder per match the sheet points at the original files; Vivu has no export tool, so frames come from the local files ls MATCH_FOLDER
The match report with goal minutes, and the kick-off time on the camera's clock picks the clips to index the user pastes the report; the kick-off clock time comes from the first clip of the kick-off (Step 2)
A browser that can open the Vivu upload page the connector has no direct upload tool the user opens the link, or Claude in Chrome is connected

No residential IP is needed (nothing is downloaded), nothing is posted anywhere and nothing is scheduled.

Inputs to collect

Ask for anything missing, most important first.

  1. The folder of clips for one match. Required.
  2. The match report: goal minutes (with the team), half time and full time. Required.
  3. The kick-off time on the camera clock, or the file name of the kick-off clip. Required.
  4. How wide a window around each goal to keep. Default: from 2 minutes before to 3 minutes after the goal minute.
  5. Whether to keep all clips after full time. Default: yes, up to 10 minutes after the final whistle.
  6. The Vivu project name. Default: "HOME v AWAY DATE reel selects", private.

Files and state

Keep everything in one working folder next to the clips:

reel-selects/
  config.json      match, kick-off clock times for each half, goal minutes, window rule, vivu project id
  clips.csv        one row per clip: file, camera start time, duration, match minute range, keep yes or no
  results/         raw search results, one JSON file per query
  sheets/          contact sheets per window and per clip
  loudness/        per second loudness per clip
  selects.csv      the sheet
  state.json       uploaded file names and video ids, queries run with job ids, windows checked with verdicts, rows written

state.json is updated after every step. A rerun reads it first: clips already uploaded are not uploaded again, queries already run are not rerun, and windows already checked keep their verdicts, so an interrupted run picks up where it stopped and no moment is written twice.

Step 1: Check the Vivu connector and the setup

Goal: every row of What you need is confirmed before anything is uploaded.

  1. Call vivu_get_account. If the tool is missing, tell the user to add the Vivu connector in Claude (https://mcp.vivu.ai/mcp) and stop. If can_create_projects is not true, or a write call later fails with "has not granted vivu.write", ask the user to reconnect Vivu with write access and stop until they have.
  2. Run ffmpeg -version and ffprobe -version. List the match folder.
  3. Ask for the match report and the kick-off clock time if they are missing.

Done when vivu_get_account shows can_create_projects: true, ffmpeg and ffprobe print versions, and config.json holds the goal minutes and the kick-off time.

Step 2: Pick the clips around each goal minute

Goal: only the clips a reel uses get indexed, which keeps a match inside a monthly plan.

  1. Read each clip's start time and length:
ffprobe -v error -show_entries format=duration:format_tags=creation_time -of csv=p=0 MATCH_FOLDER/CLIP.MP4

CLIP is each file name. creation_time is the camera clock when the clip started. Some cameras write it in UTC and some in local time, so check it once against the kick-off clip before trusting it. 2. For each clip, compute the match minute range: (camera start minus the kick-off time of that half) in minutes, plus 45 for the second half. Keep a clip when its range overlaps any goal window (default 2 minutes before to 3 minutes after the goal minute) or starts after the final whistle. Write clips.csv. 3. Show the user the kept clips per goal and the total, and wait for a yes. If a goal has no kept clip, say so: the camera may have been off or the clock may be wrong.

If the clips have no creation_time, ask the user for the clip names around each goal instead, or keep the whole match and let Step 3 price it. This step was not exercised in our test run: the test clips had no camera clock, so the goal minutes were matched to clips by hand.

Done when the user has approved clips.csv.

Step 3: Price the indexing and get approval

Goal: the user sees what the match costs before anything is uploaded.

  1. Sum the durations of the kept clips from clips.csv and convert to minutes.
  2. Call vivu_get_usage for the plan and what remains this month.
  3. Estimate search credits: four standing precise searches per match. A precise search uses 5 credits in total, so a match is about 20 credits as an estimate, plus 5 for each rewording.
  4. Show one table and wait for approval:
This match Remaining on the plan
Index minutes measured sum from vivu_get_usage
Search credits estimate from vivu_get_usage

For reference, the Free plan has 20 index minutes a month and 50 search credits a month; Premium is $30 a month with 180 index minutes and 500 search credits. As an example estimate, two matches of about 25 kept minutes each fit Premium, and one match of that size is more than Free. If the kept clips do not fit, offer these levers in order: narrow the goal window, drop the pre-match clips, index one match now and the next one next month, and only then a larger plan. Never drop a goal or the full time clips without saying so.

This step was not exercised in our test run: the factory account is an admin account whose vivu_get_usage shows no remaining allowance.

Done when the user has approved the minutes and the credit estimate.

Step 4: Upload and index

Goal: every kept clip is ready in a private Vivu project.

  1. Call vivu_list_projects and reuse the project named in config.json if it exists. Otherwise call vivu_create_project with that name and visibility "private". Match footage shows players and supporters; the default visibility is the whole organization.
  2. Call vivu_open_upload_page with the project ID right before the upload. The link expires in 180 seconds and is a sign in link, so do not paste it into any message or file. Give it to the user to open in their own browser and select the kept clips, or attach them with a browser tool that can upload local files. Claude in Chrome accepts at most 10 MB per upload call, and camera clips are often larger; the user adds those in the Vivu web app. Never split or recompress a clip to fit a tool limit.
  3. Poll vivu_list_videos about every 30 seconds until every clip shows ready. Match each video back to clips.csv by file name; Vivu turns spaces and punctuation into underscores, and camera names like C0007.MP4 come through unchanged. duration_ms matches the ffprobe duration and settles a doubt. Record the video IDs in state.json.

In our test run 12 clips (7.7 minutes) went from the start of the upload to all ready in 5.6 minutes. The upload did not go through a user's browser or Claude in Chrome; that path was not exercised in our test run.

Done when vivu_list_videos shows every clip in clips.csv as ready.

Step 5: Run the four searches and check every window

Goal: four lists of checked moments, one per part of the reel.

Field Query Mode maximum_results
goal_celebration players run together and pile onto the goal scorer, hugging and jumping in a group celebration after scoring precise 30
final_whistle after the final whistle, both teams file past each other in a line, every player shaking hands with each opponent and the referees one after another precise 30
bench_rise (candidates) the substitutes and coaches on the bench jump up off their seats together, arms raised precise 30
crowd_reaction (candidates) supporters in the stand wave scarves, flags or banners, or cheer with arms in the air precise 30

Why this chain: the match report gives the minute (text), goal_celebration turns it into the clip and seconds where the players pile on (picture), and bench_rise and crowd_reaction look for the reaction shots around the same minutes. final_whistle gives the ending. All four are precise because the sheet needs time ranges; fast returns whole files with no reason. maximum_results 30 is above the number of goals, reactions and handshake shots in one match's kept clips, so a list that stops at exactly 30 means the cap was hit: raise it and rerun that query.

The final_whistle wording asks for the handshake line because a shorter wording (players from both teams shake hands at the end, or walk to the fans and clap) also returned a half time handshake with the referee. Players walking over to thank the supporters is not covered by the final wording and was not in our test clips; look for it on the contact sheets of the full time clips in Step 6.

Run each query with vivu_search_videos (project_id, query, mode, maximum_results). It returns a job ID. Call vivu_get_search_results until complete is true; each status call can wait up to 45 seconds, so a pending search is not a stalled one. Save each completed result as results/FIELD.json. Show the result page link in the live reply only; it expires after four hours, so it never goes into selects.csv or any file.

Check every returned window before it goes anywhere:

  1. Make a contact sheet of the window, two frames a second (DURATION is end_ms minus start_ms in seconds; 12x5 covers 30 seconds, use 12x8 for longer windows):
mkdir -p reel-selects/sheets reel-selects/results reel-selects/loudness
ffmpeg -v error -ss START -t DURATION -i MATCH_FOLDER/CLIP.MP4 -vf "fps=2,scale=240:-2,tile=12x5" -frames:v 1 reel-selects/sheets/FIELD_hN.png

START is start_ms / 1000 and N is the result number. Keep the quotes around the filter; some shells treat the comma list as a pattern otherwise. 2. goal_celebration is real only when the sheet shows players running together, hugging or piling on. A corner with players packed in the box, a wall at a free kick, a pre-match huddle and an argument with the referee are not celebrations. 3. final_whistle is real only when the teams shake hands after the match. A handshake at half time or the pre-match handshake line is not. 4. bench_rise is real only when the bench is the subject and people are getting up. crowd_reaction is real only when supporters fill the picture; players celebrating in front of the rail with supporters behind them are a goal celebration, not a crowd shot. 5. Narrow each real window to the seconds the sheet shows. Windows are wider than the moment and often run into the replay or the next play. 6. Record every verdict in state.json. Rejected windows stay in results/ and are counted, not written to the sheet.

Vivu returns a time range that contains the moment, not an exact frame. Every search in the table reads movement and composition in the picture, which Vivu does less reliably than speech or large on-screen text. The goal and handshake searches were clean on one small test corpus of edited highlights, not on raw camera clips, so their windows still go through the sheet check. bench_rise and crowd_reaction are the weakest searches here (composition: who fills the picture). Treat their results as candidates and keep only what the sheet shows. An empty or short list does not prove the clips have no such shot.

Worked example from our test run

In our test run we used 12 clips, 7.7 minutes in total, cut from the published highlights of a pair of non-league cup finals (adult players, Creative Commons), renamed like camera files and cropped so no scorer graphics were on screen. They are edited highlights with replays, not camera originals. Our list of moments was written from contact sheets before searching. From the start of the upload to all clips ready took 5.6 minutes.

The goal_celebration query returned 6 windows: 6 real and 0 false. They covered 5 of the 7 goals (one goal came back twice, as the live shot and its replay), and 2 goals were missed: a celebration at the supporters' rail and a short run with arms raised. Pre-match huddles, a corner, a free kick wall and the handshake lines did not come back. The median window was 16 seconds.

The final_whistle query returned 2 real and 0 false with the wording we settled on after 1 rewording on the same corpus. The first wording returned 3 windows with 1 false (a half time handshake with the referee).

The crowd_reaction query returned 4 windows: 1 real (a supporter waving a flag) and 3 false, all players celebrating in front of the rail with supporters behind, and it missed 2 crowd shots. The bench_rise query returned 0 windows; the clips had no bench rise, so its recall was not tested.

Done when every returned window of every query has a verdict in state.json and the user has seen the real and false counts per query.

Step 6: Fill gaps from contact sheets and mark the cheer

Goal: every goal in the report has a celebration row or a note saying the camera did not catch one, and each row has its cheer second.

  1. For every goal minute with no checked goal_celebration row, make a sheet of each kept clip for that minute, one frame a second (10x12 covers 120 seconds):
ffmpeg -v error -i MATCH_FOLDER/CLIP.MP4 -vf "fps=1,scale=240:-2,tile=10x12" -frames:v 1 reel-selects/sheets/CLIP_every_second.png

Pick the celebration by eye and write its seconds. Also look at crowd_reaction windows rejected for that clip: a celebration at the supporters' rail comes back there. Do the same for the full time clips to find players walking over to thank the supporters. 2. Measure loudness once a second for each kept clip:

ffmpeg -v error -i MATCH_FOLDER/CLIP.MP4 -vn -af "aresample=48000,asetnsamples=n=48000,astats=metadata=1:reset=1,ametadata=mode=print:key=lavfi.astats.Overall.RMS_level:file=reel-selects/loudness/CLIP.txt" -f null -

Each pts_time line is one second and the RMS_level under it is its level in dB (closer to zero is louder). For each row, write the loudest second inside the checked seconds as loudness_peak. The cheer is a cross signal, not a check: the loudest second of a clip is often the goal itself, a whistle or the wind on the microphone, so a loud second without a celebration on the sheet is not a row.

In our test run both missed celebrations were on the per second sheets of their clips, and the penalty celebration also came back, as a rejected window, in the crowd_reaction results. The loudest second fell inside the checked celebration seconds for the live windows and before them for the replay window.

Done when every goal minute has a row or the note "not on camera", and every row has a loudness_peak or "not measured".

Step 7: Assemble selects.csv and confirm the sample

Goal: the videographer gets one sheet in match order.

  1. Build one row per checked moment, in match order:
segment,source_file,start_mmss,end_mmss,frame,picture,loudness_peak_mmss,report_minute,source,use
goal_celebration,C0005.MP4,00:06,00:18,sheets/goal_celebration_h1.png,red and white striped players pile on the scorer by the corner flag,00:17,50',vivu+frames,
  1. Field mapping:
Field Source If unavailable
segment the query that found it, or the contact sheet in Step 6 none
source_file the original clip name from clips.csv none
start_mmss, end_mmss the checked seconds inside the clip, as MM:SS none
frame path of the contact sheet that was checked none
picture what Claude saw on the sheet, no names UNCERTAIN
loudness_peak_mmss loudest second inside the checked seconds not measured
report_minute the goal minute from the report, or FT blank
source vivu+frames, or contact sheet for rows found in Step 6 none
use left empty for the videographer blank
  1. Show the user one sample row per segment and the mapping, and wait for a yes before writing the full sheet. Say which field is inferred (picture) and what happens if Claude read the sheet wrong: the videographer opens the clip at that time and skips it.
  2. Write selects.csv. Add a short note under it with the counts: checked rows per segment, windows rejected per segment, goals with no row, and segments that returned nothing. An empty result does not prove the clips have no such shot; say so for those segments.

In our test run the sheet was built from the checked windows and the Step 6 sheets; the user approval of sample rows was not exercised in our test run.

Done when selects.csv exists with one row per checked moment and the user has approved the sample rows.

Compliance

  1. Use only footage the club or association filmed itself. Broadcast feeds, league streams and platform links belong to someone else; do not import them. Confirm this before Step 4.
  2. People on camera: players, staff and supporters appear under the club's own filming and image rules. Ask the user before Step 7 whether anyone asked not to appear, and leave their shots out.
  3. Minors: for youth matches, go ahead only when the club holds guardian consent for filming and for this use; otherwise stop before Step 4.
  4. The skill does not recognize faces, read shirt numbers or name anyone. The videographer fills in names.
  5. The clips stay in the user's Vivu project until the user deletes them. The skill never calls vivu_delete_video or vivu_delete_project unless the user asks, and confirms first.
  6. Nothing is posted or sent. selects.csv stays in the working folder, and the reel is cut by the videographer.

Known failure modes

Symptom Cause Fix
(observed) a goal in the report has no goal_celebration window; in our test run 2 goals were missed the players celebrated at the supporters' rail or with a short run, not a pile make the per second contact sheet of that minute's clips and check rejected crowd_reaction windows (Step 6)
(observed) a half time handshake came back for the first final_whistle wording, 1 false of 3; the reason said "At the conclusion of the match, players from opposing teams and the referee shake hands." a handshake with the referee looks like the end of a match use the handshake line wording and check that the sheet shows the teams after the match
(observed) crowd_reaction returns players celebrating in front of the rail; in our test run 3 false of 4, the reason said "Supporters standing along the sideline barrier cheer and celebrate with their arms and fists in the air after the penalty goal is scored." composition is read loosely: supporters in the background are counted as the subject keep only sheets where supporters fill the picture; move the celebration to goal_celebration if the report has a goal at that minute
(observed) a window runs from the goal build-up into the replay; the median goal_celebration window was 16 seconds Vivu returns a range that contains the moment, not its edges narrow start and end to what the contact sheet shows before writing the row
(observed) bench_rise returned nothing the clips may have no bench shot, or the search missed it write in the note that the search returned nothing; an empty result does not prove there is no such shot
the loudest second is not a cheer a whistle, wind on the microphone or the goal itself use loudness only as a cross signal on rows already checked on the sheet
creation_time is empty or hours off the camera clock was not set or is in UTC check it against the kick-off clip, or ask the user for the clip names around each goal
"has not granted vivu.write" Vivu connected read only the user reconnects Vivu with write access
upload page asks to sign in or shows an error the one time upload link expires after 180 seconds request a new link right before opening it
a clip is rejected by the browser upload tool Claude in Chrome takes at most 10 MB per upload call the user adds that clip in the Vivu web app; never split or recompress it
a result's file name does not match clips.csv Vivu replaced spaces or punctuation in the name match on the camera file number and on duration_ms
a list stops at exactly maximum_results the cap cut the list short raise maximum_results and rerun that query

Connect Vivu, then add the skill.

The skill runs through the Vivu connector. Add it to Claude from the connector directory, then install the skill.