An A2A Agent Service Provider on OKX.AI that turns a YouTube URL + a natural-language brief into decision-grade video clips. A requesting agent sends a video and a brief; OKClip negotiates scope and price, finds the best moments, cuts them with burned-in speaker-labeled subtitles, and returns structured clip metadata the agent can approve — every clip carrying a viral score, a confidence, and the reasons it was picked.
Built for the OKX.AI Genesis Hackathon. Sibling project to WalletLens.
| Type | A2A (Agent-to-Agent) — negotiated, escrow-settled on X Layer |
| OKX.AI Agent ID | #5189 |
| Protocol | OKX onchainos agent (CLI + XMTP state machine); escrow is gas-free via the platform paymaster |
| Work engine | this repo — invoked by the ASP agent on job_accepted |
| Human surface | / — Alpine + Tailwind SPA |
| Stack | Node 20 · TypeScript · Express 5 · Deepgram · Sumopod LLM · FFmpeg |
| Download | loader.to API (free 3rd-party, no proxy/cookies needed) |
Clipping a video is a commodity — Whisper/Deepgram + an LLM + FFmpeg, and every SaaS tool already does it. OKClip is different in two ways that matter to an autonomous agent:
- It's agent-native, not a web app. Other agents compose OKClip into workflows: find a trending video → OKClip → 3 posted clips. No competitor offers an A2A interface.
- Its output is decision-grade, not a black box. Every clip ships the
reasons it was picked (topic match, laughter/scene-cut hook, question→answer
exchange, sentence-boundary), a
confidence, and anevidenceblock. The requesting agent approves on structured data — it never has to watch the video.
Plus the things a serious clip tool needs: negotiation (infer platform/aspect, price transparently, decline out-of-scope), a revision loop (reject a clip with feedback; OKClip re-cuts just that moment from the cached transcript), and per-agent style memory that learns aspect ratio, clip length, and topics from history.
OKX A2A is not an HTTP endpoint — it is an agent process driven by the
onchainos agent CLI over XMTP, with escrow funded and released on the platform
(gas-free). The ASP agent negotiates, applies, and — only once the job is
accepted and escrow is funded — runs OKClip as its work engine, then delivers
the clips over XMTP.
user publishes task
-> job_created ASP agent: apply (on-chain, gas-free) [OKX CLI]
-> user confirm-accept
-> job_accepted escrow funded; NOW do the work [OKX event]
run the engine: okclip run --url <yt> --prompt "<brief>" --clips <n>
-> clip files + metadata + summary
-> deliver attach clips + send summary over XMTP [OKX CLI]
-> user confirms payment released [OKX]
CLI — what the ASP agent shells out to:
okclip run --url "https://youtu.be/…" --prompt "3 DeFi clips for tiktok" --clips 3
# stdout: JSON { ok, jobId, price, summary, delivery, clipFiles[], workDir }clipFiles[] are absolute paths to attach; summary is an XMTP-ready text block.
Internal HTTP API — used by the frontend and local callers:
| Method | Path | Purpose |
|---|---|---|
POST |
/api/negotiate |
{ agentId, brief } → proposal | clarify | decline (probes source, applies style memory) |
POST |
/api/jobs |
{ agentId, brief, terms } → { jobId } (enqueues the job) |
GET |
/api/jobs/:id |
poll the delivery |
POST |
/api/jobs/:id/revise |
{ rejections[] } → re-clips rejected moments (async) |
GET |
/clips/:jobId/:file |
the produced mp4 / thumbnail (path-traversal safe) |
GET |
/health |
liveness + feature flags |
A brief is { url, prompt, clipCount (1–5), aspectRatio?, maxClipSeconds?, minClipSeconds?, language?, subtitleStyle?, resolution? }.
Platform auto-detect: mention tiktok/reels/shorts/youtube in prompt → aspect & max duration auto-set.
Subtitle styles: default (white, outline), bold (yellow, pop animation, thick outline), karaoke (word-by-word fill), minimal (clean, fade-in).
The delivery also carries scored runner-up moments (candidates not clipped), so an agent can swap a pick without a full re-process.
loader.to download → Deepgram transcribe + word-level + diarize
→ LLM select moments (+ score + reasons + runner-ups)
→ scene-cut refine (hook) → face-aware crop (cropdetect auto-bias)
→ FFmpeg cut + burn animated subtitles (style presets: default/bold/karaoke/minimal)
→ fade in/out (0.3s) + blur-pillarbox crop (16:9→9:16 keeps full frame)
→ smart thumbnail (3-frame sharpness scoring + AI text overlay)
→ decision-grade delivery
→ multi-clip stitch with crossfade transitions
Transcription cost scales with source length and is paid once per task, not per clip — so price is a clip-count tier plus a length surcharge.
| Clips | Base (source ≤ 30 min) |
|---|---|
| 1 | 0.5 USDT |
| 3 | 1 USDT |
| 5 | 1.5 USDT |
+0.5 USDT per additional 30-minute block of source. Quoted up front during negotiation.
- Node.js 20+
ffmpegonPATH- A Deepgram API key and a Sumopod (OpenAI-compatible) API key
# macOS
brew install ffmpegcd backend
npm install
cp .env.example .env # fill in DEEPGRAM_API_KEY + SUMOPOD_API_KEY
npm run dev # http://localhost:3001Open http://localhost:3001 for the SPA, POST to /api/* as an agent, or run
the engine directly:
npm run build
node dist/cli.js run --url "https://youtu.be/…" --prompt "best moments" --clips 1npm run dev # tsx watch
npm run build # tsc -> dist/
npm start # node dist/index.js
npm test # node:test suite (hermetic, no network)
npm run typecheck # tsc --noEmitThe test suite is hermetic (no network): it covers the pure logic — pricing, aspect inference, sentence-boundary snapping, score clamping, SRT/ffmpeg arg building, playlist parsing, and the A2A job adapter.
| Variable | Required | Default | Purpose |
|---|---|---|---|
PORT |
no | 3001 |
HTTP port |
NODE_ENV |
no | development |
Environment |
DEEPGRAM_API_KEY |
for ASR | — | Transcription + word timings + diarization |
SUMOPOD_API_KEY |
for analysis | — | LLM moment selection / scoring / captions |
SUMOPOD_BASE_URL |
no | https://ai.sumopod.com/v1 |
OpenAI-compatible base URL |
SUMOPOD_MODEL |
no | deepseek-v4-flash |
Model id |
STORAGE_DIR |
no | /tmp/okclip |
Temp clip storage |
PREFERENCES_DIR |
no | data/preferences |
Persistent per-agent style memory |
CLIP_TTL_MS |
no | 86400000 |
Clip retention before cleanup (24 h) |
MAX_SOURCE_SECONDS |
no | 7200 |
Product cap on source length (2 h) |
The server boots without the API keys — /health reports which features are
enabled — so discovery and negotiation always work.
backend/src/
index.ts Express server: work API, clip serving, cleanup
cli.ts `okclip run` — headless engine the ASP agent shells out to
worker.ts run one job to completion (no HTTP)
a2a-adapter.ts OKX A2A job <-> Brief + platform auto-detect (TikTok/Reels/Shorts)
jobs.ts internal work API (negotiate / jobs / revise)
negotiation.ts pricing, aspect inference, decline/clarify
pipeline.ts retry logic + download → transcribe → analyze → clip orchestration
loader-downloader.ts YouTube download via free loader.to API (replaced yt-dlp)
downloader.ts oEmbed probe + loader.to download bridge
transcriber.ts Deepgram nova-2 (transcript + word-level + diarization)
analyzer.ts LLM moment selection, scoring, sentence-boundary snapping, duration enforcement
clipper.ts ffmpeg cut + face-aware blur-pillarbox crop + subtitle burn + fade
subtitles.ts style presets (default/bold/karaoke/minimal) + ASS animations + speaker labels
thumbnail.ts smart thumbnail (sharpness scoring 3 frames) + AI text overlay via drawtext
hooks.ts scene detection near candidate timestamps + hook refine
stitch.ts highlight-reel concat + crossfade transitions (xfade)
memory.ts per-agent style memory (the data moat)
storage.ts safe clip serving + TTL cleanup
queue.ts in-memory single-worker job queue
delivery.ts decision-grade delivery envelope
config.ts types.ts logger.ts exec.ts
frontend/
index.html Alpine + Tailwind SPA (no build step)
Node backend under pm2 behind nginx (TLS via Let's Encrypt) on a VPS.
See ecosystem.config.cjs (single instance — the queue and style memory are
in-process). Install ffmpeg, then:
then set the API keys in backend/.env.
Deliberate constraints, not omissions:
- Viral score is capped at 95. A transcript heuristic never justifies certainty.
- Evidence travels with every clip — source length, segments analyzed, ASR used, and an explicit caveat.
- Reasons are real signals — topic-match, audio/scene hooks, boundary quality, conversational structure — not decoration.
- Prices reflect real cost — the length surcharge tracks the ASR cost that actually scales.
Built for the OKX.AI Genesis Hackathon. Registered as an A2A ASP, Agent ID #5189. Deadline: Jul 17, 2026 23:59 UTC.
## License
MIT
{ "downloadUrl": "/clips/<job>/clip-1.mp4", "thumbnailUrl": "/clips/<job>/clip-1.jpg", "viralScore": 87, // heuristic, capped at 95 — never certainty "confidence": 0.82, // how well the moment matches the brief "durationSec": 47, "timestamp": { "startSec": 272, "endSec": 319 }, "transcriptSnippet": "…", "speakers": ["Speaker 1", "Speaker 2"], "reasons": ["topic match: DeFi", "question -> answer exchange", "opens on a scene cut"], "caption": "…", "hashtags": ["#DeFi"], "evidence": { "sourceDurationSec": 3720, "analyzedSegments": 214, "asr": "deepgram-nova-2", "caveat": "…" } }