MA

Media-Assets Management

Hybrid templates · full content · expandable · copy-ready

ready
12 sections 297 boxes all visible Source: Hybrid templates for media-assets management.md · every word preserved
No matches. Try a shorter keyword.
100% AGENT READY

⚡ ALL-IN-ONE AGENT READY-TO-PASTE BOXES

11 boxes
INTRO

Universal Rules & Global Agent Protocol

8 boxes
U1

U1 — Screen → 9:16 Short-Form

19 boxes
U2

U2 — Screen → 16:9 Long + Feed

12 boxes
U3

U3 — General Enhance

35 boxes
T4

Template-4: Social Media Package (U4)

10 boxes
T5

Template-5: Pass Gate (U5)

11 boxes
T6

Template-6: Aggregated Master Prompt

47 boxes
T7

Template-7: Images → Video Production

36 boxes
T8

Template-8: Voice-Over + SEO Captions

63 boxes
T9

Template-9: AI-Visualization & Understanding

43 boxes
LIGHT

Light Stack Optimization (Heavy → Light)

9 boxes
GEMINI

Gemini 3.6 Senior Dev Review

4 boxes
ENHANCEMENTS

2026-08-09 Enhancements — Whisper pin · framemd5 · final_gate() · U10

4 Additions · No Removals

Four surgical additions to the hybrid template library, sourced from the editor-vs-zayatx comparison. No existing content was modified or removed. Verbatim from Hybrid templates for media-assets management.md.

1. Whisper model pin (in U1 + U2 caption step) Reason: model choice shifts word-timestamp accuracy ±30ms
# Whisper is 100% free, local, no API key — runs on CPU or GPU
# ponytail: pin the model — model choice shifts word-timestamp accuracy ±30ms
#   English-only short-form  → --model base.en   (fast, ~140 MB, sync-tight)
#   Multi-lang / medical     → --model medium    (slower, ~1.5 GB, ±10ms drift)
#   Never use --model tiny for captioned work — drift > 60ms, captions feel off
2. Frame-hash stability check (new step 21 in U3) Catches silent ffmpeg regressions via framemd5
# ponytail: framemd5 proves deterministic re-render; binary hash breaks on codec timestamp drift
# Run after every render that should be reproducible (same input + same flags = same frames)
FRAME_COUNT=$(ffprobe -v quiet -count_frames -select_streams v:0 \
  -show_entries stream=nb_read_frames -of csv=p=0 input.mp4)
UNIQUE_HASHES=$(ffmpeg -i out.mp4 -f framemd5 - 2>/dev/null | sort -u | wc -l)
echo "frames=$FRAME_COUNT unique_hashes=$UNIQUE_HASHES"
# ponytail: if UNIQUE_HASHES != FRAME_COUNT, the render is non-deterministic — re-run failed
3. final_gate() — runnable three-state QA gate (new step 16 in U5) PASS / FAIL / INCONCLUSIVE — INCONCLUSIVE is NOT a pass
# ponytail: three-state gate; INCONCLUSIVE is NOT a pass
# Source $QA_JSON from any QA runner that emits {verdict: PASS|FAIL|INCONCLUSIVE, reason: str}
final_gate() {
  local qa_json="$1"
  local verdict
  verdict=$(jq -r '.verdict' "$qa_json" 2>/dev/null)
  if [ -z "$verdict" ] || [ "$verdict" = "null" ]; then
    echo "⚠️  INCONCLUSIVE: $qa_json missing .verdict — re-run QA"
    return 2
  fi
  case "$verdict" in
    PASS)         echo "✅ ship — $(jq -r '.reason // "all checks passed"' "$qa_json")"; return 0 ;;
    FAIL)         echo "❌ fix: $(jq -r '.reason // "unspecified failure"' "$qa_json")"; return 1 ;;
    INCONCLUSIVE) echo "⚠️  re-run: $(jq -r '.reason // "could not measure"' "$qa_json")"; return 2 ;;
    *)            echo "⚠️  unknown verdict '$verdict' — treat as INCONCLUSIVE"; return 2 ;;
  esac
}

# Usage:
#   qa_runner > qa.json && final_gate qa.json && echo "ship it"
#   ponytail: never promote INCONCLUSIVE to PASS — return code 2 must block ship
4. U10 — Long-form 16:9 → 9:16 Re-Cut (Repurposing Pipeline) New template · U7/U8/U9 already taken (Images→Video / VO / AI-vision)

Agent directive: Convert a finished 16:9 long-form video into vertical 9:16 short-form clips. Source is already edited — find the best 12–60s segment, reframe (crop, don't letterbox), rebuild the hook (move payoff to 0:00), re-loudness for short-form platforms. Crop with crop=ih*9/16:ih, never scale=1080:1920.

# ponytail: long-form sits at -16 LUFS; shorts need -11 (TikTok) or -14 (IG/YT)
# Step 1: probe + silence + scene detection
ffprobe -v quiet -print_format json -show_format -show_streams input_long.mp4 > probe.json
ffmpeg -i input_long.mp4 -af "silencedetect=noise=-30dB:d=0.6" -f null - 2>&1 | grep silence_ > silences.txt
ffmpeg -i input_long.mp4 -filter:v "select='gt(scene,0.3)',showinfo" -f null - 2>&1 | grep showinfo > scenes.txt

# Step 2: reframe (crop, not letterbox)
ffmpeg -ss "$START" -to "$END" -i input_long.mp4 \
  -vf "crop=ih*9/16:ih,scale=1080:1920:flags=lanczos,eq=brightness=0.02:contrast=1.05:saturation=1.02" \
  -c:v libx264 -preset slow -crf 18 -r 30 -g 60 -c:a aac -b:a 192k -ar 48000 \
  "$OUT_DIR/segment_${START}.mp4"

# Step 3: hook rebuild (prepend payoff to body)
ffmpeg -ss "$PAYOFF_START" -to "$PAYOFF_END" -i input_long.mp4 -c copy payoff.mp4
ffmpeg -ss "$START" -to "$END" -i input_long.mp4 -c copy body.mp4
printf "file 'payoff.mp4'\nfile 'body.mp4'\n" > concat.txt
ffmpeg -f concat -safe 0 -i concat.txt -c:v libx264 -crf 18 -c:a aac -ar 48000 "$OUT_DIR/hook_first.mp4"

# Step 4: re-loudness for short-form
ffmpeg -i hook_first.mp4 -af "loudnorm=I=-11:LRA=11:TP=-1" -c:v copy -c:a aac -b:a 192k -ar 48000 "$OUT_DIR/short_tiktok.mp4"
ffmpeg -i hook_first.mp4 -af "loudnorm=I=-14:LRA=11:TP=-1" -c:v copy -c:a aac -b:a 192k -ar 48000 "$OUT_DIR/short_ig_yt.mp4"

# Step 5: captions (pin Whisper model)
whisper hook_first.mp4 --model base.en --language en --word_timestamps True --output_format srt --output_dir "$OUT_DIR"

# Step 6: final gate (no short ships without PASS)
final_gate "$OUT_DIR/qa.json" || exit $?

Routing: "cut this long video into shorts" → U10 · "long video then cut to shorts" → U2 then U10. See Hybrid templates for media-assets management.md routing table for full dispatch rules.