SOPs
After a 7FA Call
The rule
Section titled “The rule”Every 7FA Wednesday call ends with a .mov in ~/Movies/Ecamm Live Recordings/ on disk. Upload it unlisted, let YouTube generate the auto-caption, and derive everything else (slug, description, chapters, quotes) from that single source of truth.
Why YouTube-only: the VTT comes with timestamps for free, no local Whisper compute, and the caption that drives chapters and quotes is the same caption viewers see in the player. One transcript, one source.
File naming
Section titled “File naming”Save the recording as:
7fa call YYYY-MM-DD topic.movYYYY-MM-DDis the call date.topicis two to four words describing the actual subject (add-github-users,client-website-handoff,email-as-code).- The slug is derived from the YouTube auto-caption later in the pipeline. The Ecamm default name is fine until step 7.
The twelve steps
Section titled “The twelve steps”1. Confirm the recording
Section titled “1. Confirm the recording”The file lives in ~/Movies/Ecamm Live Recordings/. Confirm the most recent .mov plays and the audio is intact.
2. Upload unlisted to YouTube
Section titled “2. Upload unlisted to YouTube”Use the Ecamm default filename and a placeholder title — both get fixed in step 7 once the slug is known.
python3 -u ~/.youtube-upload/upload.py "~/Movies/Ecamm Live Recordings/Ecamm Recording on YYYY-MM-DD at HH.MM.SS 7fa call.mov" \ --title "7FA Coaching: Pending Title (YYYY-MM-DD)" \ --description "Pending — auto-filled from YouTube auto-caption." \ --privacy "unlisted" \ --tags "7fa,highlevel,coaching"Always invoke with python3 -u so progress prints flush in real time. Capture the returned VIDEO_ID.
3. Start the YouTube VTT poller
Section titled “3. Start the YouTube VTT poller”bash ~/apps/cc/youtube-vtt-poller.sh $VIDEO_ID "<placeholder description>" &The poller speaks every 5 minutes (“5 minutes in. YouTube caption is not ready yet. Checking again in 5 minutes.”), retries up to 60 minutes, and when the caption lands generates chapters via claude -p and pushes them back to the video description. Output VTT is cached at ~/.youtube-vtt-cache/$VIDEO_ID/$VIDEO_ID.en.vtt.
While the poller runs in the background, work the next steps. Do not block on the caption.
4. Pull the VTT once ready
Section titled “4. Pull the VTT once ready”The poller will speak “YouTube caption is ready” when the VTT lands. From that point the VTT is at ~/.youtube-vtt-cache/$VIDEO_ID/$VIDEO_ID.en.vtt. The poller has already used it for chapters; downstream steps reuse the same file.
If you want to start work before the caption is ready, you can transcribe locally with Whisper as a stopgap, but the official pipeline source is the YouTube VTT.
5. Generate slug, metadata, and chapters with claude -p
Section titled “5. Generate slug, metadata, and chapters with claude -p”One call returns everything downstream needs:
cat ~/.youtube-vtt-cache/$VIDEO_ID/$VIDEO_ID.en.vtt | claude -p 'You are processing a 7FA HighLevel coaching call VTT. Return ONLY a JSON object with five keys:"slug": 2-4 word kebab-case topic ("client-website-handoff", "email-as-code")."spotlight_description": exactly two paragraphs of plain text, 60-80 words each, no markdown. For the macOS Spotlight comment on the .mov."youtube_title": format "Month D, YYYY 7FA Coaching: <topic>" (friendly date FIRST, e.g. "May 6, 2026 7FA Coaching: Email as Code" — playlist convention)."youtube_description": two paragraphs covering what was discussed and the practical takeaways. Voice: direct, no em dashes, no leverage/genuinely/delve, no staccato tricolon. The chapter list goes at the END of the final description (after the prose), not at the top."youtube_tags": array of 5-8 short tags.No preamble, no code fences. JSON only.'Chapters are already on the video courtesy of the poller in step 3. The youtube_description returned here gets prepended to the existing chapters when pushed in step 8.
6. Tag the .mov with the Spotlight description
Section titled “6. Tag the .mov with the Spotlight description”osascript -e "tell application \"Finder\" to set comment of (POSIX file \"<MOVPATH>\" as alias) to \"$SPOTLIGHT_DESC\""Verify with mdls -name kMDItemFinderComment "<MOVPATH>".
7. Rename the .mov and stash the VTT
Section titled “7. Rename the .mov and stash the VTT”mv "Ecamm Recording on YYYY-MM-DD at HH.MM.SS 7fa call.mov" "7fa call YYYY-MM-DD $SLUG.mov"cp ~/.youtube-vtt-cache/$VIDEO_ID/$VIDEO_ID.en.vtt "7fa call YYYY-MM-DD $SLUG.vtt"The renamed .mov and .vtt live next to each other in ~/Movies/Ecamm Live Recordings/ until step 12 moves them to Drive.
8. Push final YouTube metadata and add to 7FA Trainings playlist
Section titled “8. Push final YouTube metadata and add to 7FA Trainings playlist”python3 ~/.youtube-upload/upload.py --update $VIDEO_ID \ --title "<youtube_title>" \ --description "<youtube_description prose + blank line + chapters block>" \ --tags "<comma-joined youtube_tags>"Always add to the 7FA Trainings playlist. The standing order: every 7FA call lives in 7FA Trainings (playlist ID PLOb0L6ZaMCiRYlkjFRFuFpMJtNgDNh-Q4). The upload.py --update mode does not accept --playlist, so add via the API directly:
python3 -c "from google.oauth2.credentials import Credentialsfrom googleapiclient.discovery import buildSCOPES = ['https://www.googleapis.com/auth/youtube']creds = Credentials.from_authorized_user_file('/Users/ojhurst/.youtube-upload/token.json', SCOPES)yt = build('youtube', 'v3', credentials=creds)yt.playlistItems().insert(part='snippet', body={'snippet': {'playlistId': 'PLOb0L6ZaMCiRYlkjFRFuFpMJtNgDNh-Q4', 'resourceId': {'kind': 'youtube#video', 'videoId': '$VIDEO_ID'}}}).execute()print('Added to 7FA Trainings')"Open the video in YouTube Studio to confirm: chapters appear in the player timeline, description reads cleanly, tags applied, playlist shows 7FA Trainings.
9. Extract quote candidates with /detect-quotes-from-transcript
Section titled “9. Extract quote candidates with /detect-quotes-from-transcript”/detect-quotes-from-transcript ~/Movies/Ecamm\ Live\ Recordings/7fa\ call\ YYYY-MM-DD\ $SLUG.vttThe skill applies the standalone test, splits results into verbatim / reshape / reject buckets, and writes quote-candidates.md to ~/apps/tms-ops/episodes/7fa-$SLUG-YYYY-MM-DD/. The first two strong quotes get clipboarded for fast posting.
The skill itself lives at ~/apps/skills/skills/detect-quotes-from-transcript.md and has its own Prove It Block. Yield is low (one or two verbatim per 70-minute call) — that is expected. The reshape bucket is the main output.
10. Render quote-candidates.html and open in browser
Section titled “10. Render quote-candidates.html and open in browser”python3 ~/apps/cc/render-quote-candidates.py ~/apps/tms-ops/episodes/7fa-$SLUG-YYYY-MM-DD/quote-candidates.mdbash ~/apps/cc/open-html.sh ~/apps/tms-ops/episodes/7fa-$SLUG-YYYY-MM-DD/quote-candidates.htmlEach verbatim and reshape gets a card with the line in large type, source line, and a one-click “Copy quote” button. Reject section collapsed at the bottom. The HTML lives next to the .md so it travels with the episode folder.
11. Thumbnail — reuse the standard
Section titled “11. Thumbnail — reuse the standard”Every 7FA call uses the same thumbnail. The 7FA Trainings playlist is meant to look like a series, not a feed of one-off videos. The canonical file lives at ~/apps/image-create/youtube-thumbnail/_7fa-standard/7fa-coaching-thumbnail.jpg. Apply it directly:
python3 ~/.youtube-upload/upload.py --update $VIDEO_ID \ --thumbnail "$HOME/apps/image-create/youtube-thumbnail/_7fa-standard/7fa-coaching-thumbnail.jpg"Do not generate a per-episode thumbnail. If the standard ever changes, update the canonical file once and every future call inherits it.
History: 2026-05-13 — I generated a custom thumbnail before checking prior 7FA videos. All four prior thumbnails (April 15, April 22, April 29, May 6) were byte-identical, MD5 61bc3c2d…. The standard was being applied manually each time; codifying it here.
12. Decide article + move to Drive + sop-example stub
Section titled “12. Decide article + move to Drive + sop-example stub”Three small calls in one step:
Article on themarketingshow? Would a non-7FA-member benefit, and is the content general enough to publish without leaking member-only context? If yes, hand off to:
Move to Drive. Move both files to My Drive/3 Resources/Seven Figure Agency/:
mv ~/Movies/Ecamm\ Live\ Recordings/"7fa call YYYY-MM-DD $SLUG.mov" \ "/Users/ojhurst/Library/CloudStorage/GoogleDrive-ojhurst@gmail.com/My Drive/3 Resources/Seven Figure Agency/"mv ~/Movies/Ecamm\ Live\ Recordings/"7fa call YYYY-MM-DD $SLUG.vtt" \ "/Users/ojhurst/Library/CloudStorage/GoogleDrive-ojhurst@gmail.com/My Drive/3 Resources/Seven Figure Agency/"7fa-sop-example stub? Single-purpose, repeatable processes are stub material. One-off Q&A sessions are not. If yes, scaffold a page at ~/apps/7fa-sop-example/src/content/docs/<section>/<slug>.md using the existing What / Who owns it / Steps / Definition of done structure, link the YouTube video at the top, and bump the build.
Definition of done
Section titled “Definition of done”- Recording confirmed intact in
~/Movies/Ecamm Live Recordings/ - Video uploaded unlisted, ID recorded
- YouTube auto-caption pulled and stashed locally as
.vtt - Slug derived from VTT
- Recording renamed, .mov and .vtt living together
- Spotlight comment on .mov (two-paragraph description)
- Final title, description (with chapters), and tags pushed to the YouTube video
- Video added to the
7FA Trainingsplaylist (PLOb0L6ZaMCiRYlkjFRFuFpMJtNgDNh-Q4) - Quote candidates extracted to episode folder, top two clipboarded
quote-candidates.htmlrendered and opened- Thumbnail uploaded
- Article decision made and acted on
- Files moved to
3 Resources/Seven Figure Agency/on Drive - SOP stub decision made and acted on
Today’s call
Section titled “Today’s call”The first call this SOP applies to: 7fa call add github users.mov, recorded April 29, 2026, one hour 19 minutes. Topic is a textbook stub candidate for 7fa-sop-example.
The 2026-05-06 call (client-website-handoff-security, video ID RJXzFoTJ6UE) is the first run of the YouTube-only flow.
Related
Section titled “Related”- Video Pipeline — the full upload-to-article-to-deploy pipeline
- Verify Deploys — for any companion themarketingshow article
- Voice Profile — voice to match when drafting titles and descriptions
- Detect Quotes Skill — the quote-extraction rubric