ugcinc 4.27.0 → 4.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -30
- package/dist/content-skills.js +3 -3
- package/dist/media-analysis.d.ts +1984 -19
- package/dist/media-analysis.js +41 -5
- package/dist/tools/media.js +1 -1
- package/package.json +1 -1
- package/skills/media/SKILL.md +16 -4
- package/skills/media/references/tools.md +26 -1
package/README.md
CHANGED
|
@@ -357,11 +357,11 @@ Both operations require an organization and `content:analyze` for scoped keys.
|
|
|
357
357
|
Errors may include `errorCode` and `retryable`. Existing scraper credit/rate safeguards
|
|
358
358
|
apply. Storage/provider errors do not imply that a post or profile was deleted.
|
|
359
359
|
|
|
360
|
-
## Native iMessage conversations and PNG snapshots
|
|
360
|
+
## Native iMessage conversations and PNG snapshots
|
|
361
361
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
362
|
+
These methods require a deployment with native rendering enabled. An unavailable
|
|
363
|
+
native service returns a retryable 503. The existing still-image DM renderer
|
|
364
|
+
remains available separately.
|
|
365
365
|
|
|
366
366
|
Quick reference: `client.media.renderIMessageConversation(input)` queues a video by default;
|
|
367
367
|
`client.media.getIMessageConversation({jobId})` polls its status.
|
|
@@ -474,9 +474,12 @@ API reference:
|
|
|
474
474
|
`timing.emojiSelectionDelayMs` (100–10000, default 350) controls the pause before
|
|
475
475
|
selecting a focused emoji. These can be overridden per message. Complete
|
|
476
476
|
grapheme sequences are preserved. Incoming emoji text never opens the local
|
|
477
|
-
keyboard. Outgoing emoji interactions require `keyboard: true`.
|
|
478
|
-
|
|
479
|
-
|
|
477
|
+
keyboard. Outgoing emoji interactions require `keyboard: true`. Skin-tone
|
|
478
|
+
variants open the native variant selector and choose its visible option.
|
|
479
|
+
Supported family variants select each native tone row, then select the
|
|
480
|
+
configured family preview to commit. The selected native emoji must match the
|
|
481
|
+
requested sequence exactly; unavailable variants reject. Personal recents and
|
|
482
|
+
saved emoji preferences are not used or modified.
|
|
480
483
|
- Optional `timing.incomingTypingDurationMs` (0–30000) sets the exact interval
|
|
481
484
|
from the other person's typing indicator starting until their message arrives.
|
|
482
485
|
Set it globally or override it in an incoming message's `timing` (for example
|
|
@@ -540,11 +543,10 @@ API reference:
|
|
|
540
543
|
organization. Reuse the same body/key to recover the same job; changing the body
|
|
541
544
|
returns 409. To retry a failed render, use a new key or omit it. Job ownership
|
|
542
545
|
records are retained for seven days.
|
|
543
|
-
- This authoring API
|
|
544
|
-
conversations with configurable chrome, receipts, reactions and replies.
|
|
545
|
-
carrier-name/network-type selection, numerical
|
|
546
|
-
|
|
547
|
-
by this contract. Unknown input fields reject rather than silently approximating them.
|
|
546
|
+
- This authoring API supports text/emoji, PNG image messages, initial history and
|
|
547
|
+
sequential conversations with configurable chrome, receipts, reactions and replies.
|
|
548
|
+
Image captions, carrier-name/network-type selection, numerical battery-percentage
|
|
549
|
+
display and arbitrary low-level native event scripts are not accepted by this contract. Unknown input fields reject rather than silently approximating them.
|
|
548
550
|
|
|
549
551
|
## Video inspection
|
|
550
552
|
|
|
@@ -646,33 +648,115 @@ Both tools accept single-frame PNG (up to 8-bit channels), JPEG and WebP, at mos
|
|
|
646
648
|
|
|
647
649
|
### Match text style
|
|
648
650
|
|
|
649
|
-
Quick reference: `client.media.matchTextStyle({url, box, text?})`;
|
|
651
|
+
Quick reference: `client.media.matchTextStyle({url, box, text?, renderer?})`;
|
|
652
|
+
agent tool `match_text_style`. `POST /media/analysis/match-text-style` uses the
|
|
653
|
+
normal authenticated analysis-job flow. Keep a pending/processing job ID and
|
|
654
|
+
poll `getMediaAnalysis`; do not submit a replacement while it is still running.
|
|
650
655
|
|
|
651
656
|
```typescript
|
|
652
657
|
const match = await client.media.matchTextStyle({
|
|
653
658
|
url: referenceImageUrl,
|
|
654
|
-
box: {x:
|
|
655
|
-
text: '
|
|
659
|
+
box: {x: 76, y: 219, width: 424, height: 112},
|
|
660
|
+
text: 'I could LITERALLY KISS the\nflight attendant that showed\nme this🫣🤭',
|
|
661
|
+
renderer: 'auto',
|
|
656
662
|
});
|
|
657
|
-
if (match.ok && match.data.
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
663
|
+
if (match.ok && match.data.status === 'completed'
|
|
664
|
+
&& match.data.result?.operation === 'match_text_style') {
|
|
665
|
+
const result = match.data.result;
|
|
666
|
+
if (result.status === 'unavailable') {
|
|
667
|
+
console.log(result.reasonCode, result.reason, result.fitAttempted, result.nextActions);
|
|
668
|
+
} else if (result.nativeResult) {
|
|
669
|
+
// Reuse this clean transparent PNG as an image layer.
|
|
670
|
+
console.log(result.nativeResult.stickerUrl, result.nativeResult.composition);
|
|
671
|
+
// Or reproduce it through the supported native render helper.
|
|
672
|
+
const render = await submitNativeTextStickerRenderJob(result.nativeResult.settings);
|
|
673
|
+
} else {
|
|
674
|
+
const candidate = result.candidates[0];
|
|
675
|
+
if (candidate) {
|
|
676
|
+
const render = await submitImageRenderJob({
|
|
677
|
+
config: candidate.previewConfig, imageUrls: {}, textValues: {},
|
|
678
|
+
});
|
|
679
|
+
}
|
|
665
680
|
}
|
|
666
681
|
}
|
|
667
682
|
```
|
|
668
683
|
|
|
669
|
-
The
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
684
|
+
The native and image render helpers require the server's configured
|
|
685
|
+
`UGC_RENDER_URL`; matching itself uses the public API. The returned sticker URL
|
|
686
|
+
is already rendered and can be used without submitting another render.
|
|
687
|
+
|
|
688
|
+
#### Choose the renderer
|
|
689
|
+
|
|
690
|
+
- Omit `renderer`, or use `'image-editor'`, for the existing generic matcher.
|
|
691
|
+
Its version1 result and `surface: 'image-editor-element'` are unchanged.
|
|
692
|
+
It fits plain-background ASCII text using the supported image-editor fonts,
|
|
693
|
+
weight, size, spacing, line height, alignment and outline.
|
|
694
|
+
- Use `'auto'` to allow native TikTok fallback when the generic path cannot
|
|
695
|
+
use the reference, including photographed captions and supplied Unicode/emoji.
|
|
696
|
+
- Use `'tiktok-native'` to request only the supported original native
|
|
697
|
+
`tiktok-classic-ios-47` profile. It has white text, a dark outline, original
|
|
698
|
+
text/emoji shaping and native font metrics. It does not add arbitrary font,
|
|
699
|
+
weight or outline controls that this profile does not expose.
|
|
700
|
+
|
|
701
|
+
Crop coordinates are integer display-oriented source pixels, width 16–1536 and
|
|
702
|
+
height 16–512. Supplied text is optional; local English OCR supplies it otherwise.
|
|
703
|
+
Provide exact text, emoji and intended line breaks when known. Generic text is
|
|
704
|
+
1–160 printable ASCII characters/up to four lines. Native/auto text supports
|
|
705
|
+
valid printable Unicode/emoji, at most 160 UTF-16 code units/up to four lines;
|
|
706
|
+
unsupported native sequences fail explicitly rather than substituting fonts.
|
|
707
|
+
Native paragraphs cannot be empty or space-only. Source image type/size/color
|
|
708
|
+
constraints match color/layout analysis.
|
|
709
|
+
|
|
710
|
+
#### Interpret the result
|
|
711
|
+
|
|
712
|
+
Check outer `ok`, the analysis job's `status`, **and** inner `result.status`.
|
|
713
|
+
A completed analysis can return `unavailable`. `fitAttempted: false` or
|
|
714
|
+
`renders: 0` means it rejected the reference before font search. Read
|
|
715
|
+
`reasonCode` and `nextActions` instead of repeating nearly identical crop
|
|
716
|
+
requests or downloading replacement fonts. An unavailable result is not proof
|
|
717
|
+
that the correct font is missing.
|
|
718
|
+
|
|
719
|
+
Generic version 1 results retain up to three `candidates`, each with actual
|
|
720
|
+
image-editor `element`/`previewConfig`, `maskIoU`, `foregroundMae`, unverified
|
|
721
|
+
font identity and `quality: 'close' | 'approximate'`. `element` is positioned in
|
|
722
|
+
source pixels; `previewConfig` is a crop-sized image-editor configuration. The
|
|
723
|
+
legacy mask treats differences from an estimated uniform border color as ink;
|
|
724
|
+
it is unsuitable for photographic backgrounds. It does not infer emoji,
|
|
725
|
+
shadows, gradients, perspective, mixed styles or custom fonts.
|
|
726
|
+
|
|
727
|
+
Native version 2 uses `surface: 'native-text-sticker'`, an empty generic
|
|
728
|
+
`candidates` array, and `nativeResult` on a fitted result:
|
|
729
|
+
|
|
730
|
+
- `profile` and `settings`: the actual native sticker input, ready for
|
|
731
|
+
`submitNativeTextStickerRenderJob`.
|
|
732
|
+
- `stickerUrl`: an owned HTTPS transparent PNG generated from those settings.
|
|
733
|
+
- `composition: {x, y, width, height, scale}`: its placement and displayed extent
|
|
734
|
+
in source pixels. Native settings use points and intrinsic 3× output; apply
|
|
735
|
+
the returned placement/scale rather than treating points as source pixels.
|
|
736
|
+
- `maskIoU`: white-fill overlap, with separate `diagnostics.outlineIoU`;
|
|
737
|
+
`foregroundMae` compares rendered text, outline and detected warm-color emoji
|
|
738
|
+
against an estimated photo background. These scores are estimates, not proof
|
|
739
|
+
of an identical font. `fontIdentity` remains `unverified`.
|
|
740
|
+
- `diagnostics`: named mask/residual/foreground metrics, observed/expected lines,
|
|
741
|
+
text/outline/emoji pixel counts, clipping, render count and `resampling`
|
|
742
|
+
(`none` or `lanczos3`). Inspect these alongside the comparison.
|
|
743
|
+
|
|
744
|
+
On the native path, top-level `backgroundColor` is a compatibility placeholder;
|
|
745
|
+
it does not represent a recovered photograph color. The sticker is transparent.
|
|
746
|
+
|
|
747
|
+
Both paths return an owned reference/render/difference preview and manifest,
|
|
748
|
+
source hashes, warnings, render metadata and counts. Font identity remains
|
|
749
|
+
`unverified`: neither equal line widths nor the availability of a TikTok font
|
|
750
|
+
proves the original font or exact rasterization. Transparent source pixels are
|
|
751
|
+
composited over white for analysis. Compression, background separation and
|
|
752
|
+
resizing may leave residuals; inspect the actual-resolution comparison before
|
|
753
|
+
calling a fit accurate. Do not paste extracted caption pixels onto a changed
|
|
754
|
+
background; use the clean rendered sticker.
|
|
755
|
+
|
|
756
|
+
Matching runs locally within bounded render/job budgets. The existing native
|
|
757
|
+
renderer and image-editor bundle are reused without new font downloads, SAM,
|
|
758
|
+
or hosted inference. The native path targets white text with dark outlines;
|
|
759
|
+
other caption styles may remain approximations or unavailable.
|
|
676
760
|
|
|
677
761
|
## Agent media inspection and content workflows
|
|
678
762
|
|
package/dist/content-skills.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.contentSkillFiles = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated from published 4.27.1 skills plus reviewed T0582 media changes.
|
|
5
5
|
exports.contentSkillFiles = {
|
|
6
|
-
"media/SKILL.md": "---\nname: media\ndescription: Acquire TikTok and Instagram posts and inspect images, video and audio with UGC Inc tools. Use for reference analysis, OCR, frames, scenes, transcription, colors, layout, text-style fitting, or media-library management.\nallowed-tools: Bash, Read\n---\n\nUse the installed UGC Inc CLI:\n\n```bash\nnpx ugcinc --list\nnpx ugcinc <tool_name> '<json_params>'\n```\n\nCredentials come from `UGC_API_KEY` or existing UGC configuration. Use the user's\norganization and a key with `content:analyze` for acquisition/analysis. If using\nan admin key, pass the authorized `orgId` in the JSON parameters. Do not print\ncredentials, copy an administrator key to another user's machine, or change\norganizations to bypass a denial. Confirm access with one small tool call.\nIf credentials already live in an app env file, set `UGC_ENV_FILE` to that file's\npath so the CLI reads the existing key without duplicating its contents. Set\n`UGC_ORG_ID` in that file or the process environment to scope calls to the user's\norganization; an explicit JSON `orgId` takes priority.\n\nRead [references/tools.md](references/tools.md) for request shapes, result fields\nand limits. The CLI lists names/descriptions; the reference explains parameters.\n\n## Choose the input and tools\n\n- A profile URL: `list_profile_posts` discovers a bounded page; follow its cursor\n only as needed. Listing does not download media or guarantee complete history.\n- A post URL: `download_social_post` ingests its ordered assets into owned media.\n Use returned asset URLs for analysis; the TikTok/Instagram HTML URL is not a\n video file. Check complete/partial/failed status and failed assets.\n- A direct media URL: use the corresponding inspection tool directly.\n- Video: `detect_scenes`, `extract_frames`, `read_video_text`; audio tools accept\n video too. Inspect multiple moments, including changes near the beginning/end.\n- Image: `read_image_text`, `sample_colors`, `measure_layout` using supplied\n boxes/masks, and `match_text_style` for a specified text crop.\n- Audio: `transcribe_audio` and `measure_audio_levels`.\n\nThe SDK/CLI waits for processing automatically. Check both the outer response's\n`ok` and the returned job's `status`. Analysis is usable when\n`data.status === \"completed\"`; its content is `data.result`. If still pending or\nprocessing, keep its job ID and use `get_media_analysis` rather than resubmitting.\nUse bounded retries for retryable failures; report persistent errors/partial\ncoverage. A zero process exit code alone does not establish API success.\n\n## Interpret evidence accurately\n\n- Coordinates are display-oriented source pixels; times are source-relative\n milliseconds. Use returned decoded timestamps, dimensions and coverage.\n- OCR is English, may miss stylized text, and can be empty on unreadable input.\n `fast` video OCR leaves uninspected intervals. `frame_scan` is bounded and\n cannot inspect an arbitrarily long clip in one request.\n- Speech timestamps are estimates; speaker labels/forced alignment are absent.\n A transcript does not establish music, emotion, delivery or sound effects.\n- Color sampling measures decoded sRGB pixels, not guaranteed design hex values.\n Layout measurement does not detect objects or recover original layer files.\n-
|
|
7
|
-
"media/references/tools.md": "# UGC media tool requests and results\n\nRun `npx ugcinc TOOL 'JSON'`. Shell quoting varies on Windows; if the shell\nchanges the JSON, use a small Node script with `UGCClient` and its `media`\nmethods instead of repeatedly sending malformed requests. For example:\n\n```js\nconst { UGCClient } = require('ugcinc');\nconst client = new UGCClient({\n apiKey: process.env.UGC_API_KEY,\n orgId: process.env.UGC_ORG_ID,\n});\n// Use admin:true only with an authorized administrator credential.\n```\n\nRequest URLs must be HTTPS. Analysis source URLs must not contain credentials\nor fragments. Image operations support still PNG/JPEG/WebP, at most4096pixels\nper side; the shared download limit is100MiB. Geometry must fit the actual\ndisplay-oriented source. Respect more restrictive operation limits below.\n\n## Acquisition\n\n| CLI tool / SDK method | Parameters | Result |\n| --- | --- | --- |\n| `list_profile_posts` / `media.listProfilePosts` | `{url, limit?, cursor?}`; TikTok/Instagram profile; limit1–50 | `data.posts`, profile metadata, continuation cursor. Follow the actual returned cursor, not a fabricated page number. |\n| `download_social_post` / `media.downloadSocialPost` | `{url}`; canonical TikTok/Instagram post URL | `data.status`, `assets[]` in order, `failedAssets[]`, `manifestUrl`, post/sound metadata. Each asset has `url`, `mediaId`, dimensions, type, duration, audio presence and hash. Repeat the same URL to resume retryable partial imports. |\n\nEmbedded video audio remains attached. Photo assets have no embedded soundtrack;\nsound attribution does not mean audio bytes were downloaded. Preserve sound\nID/link separately; never replace a post excerpt with the full sound-page track\nand call them identical. Partial imports are not a complete carousel.\n\n## Analysis\n\nThese return `{ok, data:{jobId,status,operation,result?,error?}}`. Use the completed\n`data.result` fields listed below. Failure can occur after successful submission.\n\n| CLI tool / SDK method | Parameters | Result content |\n| --- | --- | --- |\n| `extract_frames` / `media.extractFrames` | `{url,timestampsMs:[0,1500,3000],selection:\"nearest\",contactSheet:true}` OR `{url,range:{startMs,endMs,intervalMs}}`; choose exactly one selector, at most48samples | `frames[]` with requested/decoded time, source PTS, dimensions and URL; optional `contactSheet` with individual frame links; source metadata. |\n| `detect_scenes` / `media.detectScenes` | `{url}` | `scenes[]` with start/end milliseconds, frame indexes, source PTS; no split MP4 exports. |\n| `read_image_text` / `media.readImageText` | `{url}` | `regions[]` with text/rawText, polygons/boxes/confidence; inferred `lines[]`/reading order; `previewUrl`. |\n| `read_video_text` / `media.readVideoText` | `{url,mode:\"fast\",intervalMs:1000,range?:{startMs,endMs}}` OR `{url,mode:\"frame_scan\",range?:{startMs,endMs}}` | `frames[]`, text `tracks[]` with observations/positions; explicit `coverage.inspected` and `uninspected`. Maximum240inspected frames and120seconds per request. `intervalMs` only applies to fast mode. |\n| `transcribe_audio` / `media.transcribeAudio` | `{url,range?:{startMs,endMs},language?:\"auto\",timing?:\"word\",channel?:0}` | `status`, `text`, timed `segments[]` and estimated words, warnings, `audioPreviewUrl`. Range at most120seconds; timing `word` or `segment`; optional channel0/1. Empty/no-audio/no-speech states are distinct. |\n| `measure_audio_levels` / `media.measureAudioLevels` | `{url,range?:{startMs,endMs},windowMs?:100,silenceThresholdDbfs?:-50}` | Native-channel RMS/sample peaks, loudness timeline/LUFS, silence, possible clipping, `previewUrl`. Windows20–5000ms, threshold−100to−10dBFS, range at most120seconds. |\n| `sample_colors` / `media.sampleColors` | `{url,maxColors?:8,point?:{x,y},box?:{x,y,width,height},mask?}`; choose at most one selection | Observed RGBA point or palette/proportions, omitted mass, declared color policy, `previewUrl`. Palette1–32colors. |\n| `measure_layout` / `media.measureLayout` | `{url,elements:[{id,box:{x,y,width,height}}]}`; each element may instead have `mask` | Margins, centers, spacing/alignment deltas, intersections/IoU and `previewUrl`.1–32unique IDs. Boxes are supplied, not automatically detected. |\n| `match_text_style` / `media.matchTextStyle` | `{url,box:{x,y,width,height},text?}`; integer
|
|
6
|
+
"media/SKILL.md": "---\nname: media\ndescription: Acquire TikTok and Instagram posts and inspect images, video and audio with UGC Inc tools. Use for reference analysis, OCR, frames, scenes, transcription, colors, layout, text-style fitting, or media-library management.\nallowed-tools: Bash, Read\n---\n\nUse the installed UGC Inc CLI:\n\n```bash\nnpx ugcinc --list\nnpx ugcinc <tool_name> '<json_params>'\n```\n\nCredentials come from `UGC_API_KEY` or existing UGC configuration. Use the user's\norganization and a key with `content:analyze` for acquisition/analysis. If using\nan admin key, pass the authorized `orgId` in the JSON parameters. Do not print\ncredentials, copy an administrator key to another user's machine, or change\norganizations to bypass a denial. Confirm access with one small tool call.\nIf credentials already live in an app env file, set `UGC_ENV_FILE` to that file's\npath so the CLI reads the existing key without duplicating its contents. Set\n`UGC_ORG_ID` in that file or the process environment to scope calls to the user's\norganization; an explicit JSON `orgId` takes priority.\n\nRead [references/tools.md](references/tools.md) for request shapes, result fields\nand limits. The CLI lists names/descriptions; the reference explains parameters.\n\n## Choose the input and tools\n\n- A profile URL: `list_profile_posts` discovers a bounded page; follow its cursor\n only as needed. Listing does not download media or guarantee complete history.\n- A post URL: `download_social_post` ingests its ordered assets into owned media.\n Use returned asset URLs for analysis; the TikTok/Instagram HTML URL is not a\n video file. Check complete/partial/failed status and failed assets.\n- A direct media URL: use the corresponding inspection tool directly.\n- Video: `detect_scenes`, `extract_frames`, `read_video_text`; audio tools accept\n video too. Inspect multiple moments, including changes near the beginning/end.\n- Image: `read_image_text`, `sample_colors`, `measure_layout` using supplied\n boxes/masks, and `match_text_style` for a specified text crop.\n- Audio: `transcribe_audio` and `measure_audio_levels`.\n\nThe SDK/CLI waits for processing automatically. Check both the outer response's\n`ok` and the returned job's `status`. Analysis is usable when\n`data.status === \"completed\"`; its content is `data.result`. If still pending or\nprocessing, keep its job ID and use `get_media_analysis` rather than resubmitting.\nUse bounded retries for retryable failures; report persistent errors/partial\ncoverage. A zero process exit code alone does not establish API success.\n\n## Interpret evidence accurately\n\n- Coordinates are display-oriented source pixels; times are source-relative\n milliseconds. Use returned decoded timestamps, dimensions and coverage.\n- OCR is English, may miss stylized text, and can be empty on unreadable input.\n `fast` video OCR leaves uninspected intervals. `frame_scan` is bounded and\n cannot inspect an arbitrarily long clip in one request.\n- Speech timestamps are estimates; speaker labels/forced alignment are absent.\n A transcript does not establish music, emotion, delivery or sound effects.\n- Color sampling measures decoded sRGB pixels, not guaranteed design hex values.\n Layout measurement does not detect objects or recover original layer files.\n- For text over photographic backgrounds, call `match_text_style` with\n `renderer: \"auto\"` or `\"tiktok-native\"` and exact text/line breaks when known.\n Native results include Unicode/emoji and a clean transparent sticker using\n the supported native TikTok profile. Omitted renderer keeps the older\n ASCII/plain-background image-editor path. Inspect `surface`/version and use\n `nativeResult` or generic `candidates` accordingly.\n- A completed matching job can return inner `status: \"unavailable\"`. Check\n `reasonCode`, `fitAttempted`, `renders` and `nextActions`. Zero renders means\n no font fit was attempted: do not spend repeated calls on similar rejected\n crops or download replacement fonts. Font identity stays unverified; compare\n text/outline residuals and the preview before calling any result accurate.\n Equal line widths or matching positions alone do not prove identical text.\n- SAM/object segmentation, automatic overlay detection, element/mask tracking,\n motion measurement, extraction, media comparison/alignment and semantic search\n are not available through this tool set. Do not invent those calls or install\n SAM. Existing OCR text tracks remain available.\n\n## Review and share media\n\nOpen returned image/contact-sheet previews and review the relevant sequence.\nWhen the agent runtime can consume audio/video, use it. Otherwise use the\navailable transcript, audio preview and level measurements and explicitly state\nwhat was not listened to or inspected. Do not claim to have watched/listened\nbecause an analysis request succeeded.\n\nShare only verified browser-accessible HTTPS artifacts. Fetch without auth and\ncheck status, content type and decoding; for video also check byte-range support.\nUse the returned owned-media URLs. Local paths, localhost/private addresses and\nexpiring upstream CDN links are not deliverable previews. If an artifact needs\nuploading, use the supported owned storage path; do not claim a file is hosted\nbecause a media record was created for an arbitrary URL.\n\nFor building a reusable content format, use the `content-automation` skill.\n\nFor native iMessage render jobs use the `imessage` skill and its separate\nsubmit/status/cancel tools. They require `content:render`, not `content:analyze`,\nand are not media-analysis jobs.\n",
|
|
7
|
+
"media/references/tools.md": "# UGC media tool requests and results\n\nRun `npx ugcinc TOOL 'JSON'`. Shell quoting varies on Windows; if the shell\nchanges the JSON, use a small Node script with `UGCClient` and its `media`\nmethods instead of repeatedly sending malformed requests. For example:\n\n```js\nconst { UGCClient } = require('ugcinc');\nconst client = new UGCClient({\n apiKey: process.env.UGC_API_KEY,\n orgId: process.env.UGC_ORG_ID,\n});\n// Use admin:true only with an authorized administrator credential.\n```\n\nRequest URLs must be HTTPS. Analysis source URLs must not contain credentials\nor fragments. Image operations support still PNG/JPEG/WebP, at most4096pixels\nper side; the shared download limit is100MiB. Geometry must fit the actual\ndisplay-oriented source. Respect more restrictive operation limits below.\n\n## Acquisition\n\n| CLI tool / SDK method | Parameters | Result |\n| --- | --- | --- |\n| `list_profile_posts` / `media.listProfilePosts` | `{url, limit?, cursor?}`; TikTok/Instagram profile; limit1–50 | `data.posts`, profile metadata, continuation cursor. Follow the actual returned cursor, not a fabricated page number. |\n| `download_social_post` / `media.downloadSocialPost` | `{url}`; canonical TikTok/Instagram post URL | `data.status`, `assets[]` in order, `failedAssets[]`, `manifestUrl`, post/sound metadata. Each asset has `url`, `mediaId`, dimensions, type, duration, audio presence and hash. Repeat the same URL to resume retryable partial imports. |\n\nEmbedded video audio remains attached. Photo assets have no embedded soundtrack;\nsound attribution does not mean audio bytes were downloaded. Preserve sound\nID/link separately; never replace a post excerpt with the full sound-page track\nand call them identical. Partial imports are not a complete carousel.\n\n## Analysis\n\nThese return `{ok, data:{jobId,status,operation,result?,error?}}`. Use the completed\n`data.result` fields listed below. Failure can occur after successful submission.\n\n| CLI tool / SDK method | Parameters | Result content |\n| --- | --- | --- |\n| `extract_frames` / `media.extractFrames` | `{url,timestampsMs:[0,1500,3000],selection:\"nearest\",contactSheet:true}` OR `{url,range:{startMs,endMs,intervalMs}}`; choose exactly one selector, at most48samples | `frames[]` with requested/decoded time, source PTS, dimensions and URL; optional `contactSheet` with individual frame links; source metadata. |\n| `detect_scenes` / `media.detectScenes` | `{url}` | `scenes[]` with start/end milliseconds, frame indexes, source PTS; no split MP4 exports. |\n| `read_image_text` / `media.readImageText` | `{url}` | `regions[]` with text/rawText, polygons/boxes/confidence; inferred `lines[]`/reading order; `previewUrl`. |\n| `read_video_text` / `media.readVideoText` | `{url,mode:\"fast\",intervalMs:1000,range?:{startMs,endMs}}` OR `{url,mode:\"frame_scan\",range?:{startMs,endMs}}` | `frames[]`, text `tracks[]` with observations/positions; explicit `coverage.inspected` and `uninspected`. Maximum240inspected frames and120seconds per request. `intervalMs` only applies to fast mode. |\n| `transcribe_audio` / `media.transcribeAudio` | `{url,range?:{startMs,endMs},language?:\"auto\",timing?:\"word\",channel?:0}` | `status`, `text`, timed `segments[]` and estimated words, warnings, `audioPreviewUrl`. Range at most120seconds; timing `word` or `segment`; optional channel0/1. Empty/no-audio/no-speech states are distinct. |\n| `measure_audio_levels` / `media.measureAudioLevels` | `{url,range?:{startMs,endMs},windowMs?:100,silenceThresholdDbfs?:-50}` | Native-channel RMS/sample peaks, loudness timeline/LUFS, silence, possible clipping, `previewUrl`. Windows20–5000ms, threshold−100to−10dBFS, range at most120seconds. |\n| `sample_colors` / `media.sampleColors` | `{url,maxColors?:8,point?:{x,y},box?:{x,y,width,height},mask?}`; choose at most one selection | Observed RGBA point or palette/proportions, omitted mass, declared color policy, `previewUrl`. Palette1–32colors. |\n| `measure_layout` / `media.measureLayout` | `{url,elements:[{id,box:{x,y,width,height}}]}`; each element may instead have `mask` | Margins, centers, spacing/alignment deltas, intersections/IoU and `previewUrl`.1–32unique IDs. Boxes are supplied, not automatically detected. |\n| `match_text_style` / `media.matchTextStyle` | `{url,box:{x,y,width,height},text?,renderer?}`; integer crop 16–1536 wide, 16–512 high. `renderer: auto` allows native fallback; `tiktok-native` requests the native profile. Omitted renderer keeps legacy image-editor behavior. Supply exact text and line breaks when available. | `status`, `reasonCode`, `fitAttempted`, `nextActions`, comparison and warnings. Generic v1 returns `candidates` with image-editor `element`/`previewConfig`. Native v2 returns `nativeResult` with actual native `settings`, clean transparent `stickerUrl`, source-pixel `composition`, masked residuals and diagnostics; `candidates` is empty. Native/auto accept Unicode/emoji, up to 160 UTF-16 code units/four lines; generic remains ASCII/plain-background only. Original font identity is unverified. |\n| `get_media_analysis` / `media.getMediaAnalysis` | `{jobId}` | Current status/result in the current organization; use when automatic waiting returned pending/processing. |\n\nBoxes are half-open source-pixel rectangles. For masks used by colors/layout:\n`{width,height,counts}` uses row-major binary RLE, alternating background then\nforeground. Counts must sum to width×height. This is not COCO's column-major\nconvention. Supply only masks you actually have; automatic segmentation is off.\n\n## Text matching decisions\n\nFor photographed TikTok captions, use `renderer: \"auto\"` or `\"tiktok-native\"`\nand supply the exact caption, including emoji and intended line breaks. The\nnative candidate uses the supported `tiktok-classic-ios-47` profile: white text,\ndark outline, original native shaping and emoji. This does not imply every\nTikTok caption uses that profile. Unsupported styles remain unavailable or\nexplicit approximations; no new font download or hosted model is required.\n\nCheck all three levels: outer response `ok`, analysis job `status`, and inner\nmatching `result.status`. A completed analysis can legitimately return\n`unavailable`. If `fitAttempted` is false or `renders` is zero, no font candidate\nwas tested. Read `reasonCode` and `nextActions`; do not keep resubmitting nearly\nthe same crop after a background/segmentation rejection. Keep the source frame\nand failure for a tool repair rather than claiming a missing font.\n\nUse `surface` and result version to choose the output. Generic image-editor\nresults retain `candidates[].element` and `previewConfig`. Native results use\n`nativeResult.settings` with the native sticker renderer, or directly reuse\n`nativeResult.stickerUrl`. Its `composition` positions the clean PNG in source\npixels; native settings themselves use points and produce 3× pixels. Do not\npaste extracted source-caption pixels onto a changed background. Compare the\nreturned fit/difference preview and residuals; matching a line width or locating\nits top-left corner does not establish correct glyphs, spacing or emoji.\n\n## Existing media library\n\n- `list_media({ids?,tag?})`, `list_social_audio({ids?,tag?})`.\n- `create_media_from_urls({urls,names?,tag?,sourceIds?,useName?})` registers URLs;\n it does not turn an inaccessible local file into a public upload.\n- `import_text({texts:[{content,name?,tag?}]})`.\n- `create_social_audio({url,tag?})` imports social audio separately; do not use it\n as proof of the exact soundtrack/mix/offset in a downloaded reference video.\n- `delete_media({ids})` removes media/storage; only use when deletion is requested.\n",
|
|
8
8
|
"content-automation/SKILL.md": "---\nname: content-automation\ndescription: Turn reference social posts or a rough content idea into a reusable UGC Inc workflow, with editable inputs and reviewed visual/audio output. Use for developing and validating content formats rather than scheduling existing finished posts.\nallowed-tools: Bash, Read\n---\n\nBuild the format the user wants and collaborate at the level they requested.\nWhen they want to discuss, compare or review a specific artifact, do that before\nmaking additional format decisions. Keep questions concise and ask only when a\nmissing answer prevents useful work. Do not impose a new per-video reference input\nwhen the user wants a fixed reusable visual format.\n\nUse the `media` skill for acquisition/inspection and the `automations` skill for\ncurrent workflow tool calls. Read [references/build-review.md](references/build-review.md)\nwhen constructing or reviewing a workflow. Use only shipped tools/nodes discovered\nthrough `npx ugcinc --list`, `list_node_types` and `get_node_type`.\n\n## Understand and specify the format\n\nAcquire a bounded set of real references and inspect full frames and changes over\ntime, including audio using available modalities. A contact sheet or transcript\nalone cannot establish all animation/pacing/music details. State uninspected\nparts instead of claiming playback. Distinguish reusable formats from variants;\nseveral posts may use the same structure with different assets, copy or timing.\n\nWrite a compact spec: what the viewer sees first, the sequence/reveal, required\ninputs, reusable assets/components, changing copy, audio source/timing and final\naction/CTA if required by this format. Separate measured facts from inference\nand user choices. Share a verified HTTPS reference/preview when the user needs\nto identify the parts they want changed.\n\nClassify assets by replacement behavior. A recognizable Mii, Wojak or other exact\nmeme image may need a static asset; an ordinary or newly generated face need not\nbe static just because it looks meme-like. Preserve a headshot's identity across\nvariants when requested, while making intended differences visibly meaningful.\n\n## Build reusable production behavior\n\nSeparate layout, data/assets and motion. Expose the inputs a normal run needs:\nasset pools/overrides, text pools, contact/destination, duration/timing and seed\nwhere appropriate. Keep canonical outputs independent of an operator's laptop.\nImplement procedural animations as reusable components rendered on demand;\ndo not substitute one pre-rendered clip when each run should vary. Randomness\nmust respect the intended visual roles and remain replayable from saved inputs.\n\nReuse existing nodes/compositions and actual public schemas. Analysis tools are\navailable as CLI/SDK operations; do not assume every one is a workflow node.\nValidate the graph before executing. Prefer a reviewable output over publishing\nor enabling recurring runs unless the user authorized those actions.\n\n## Make the content work\n\n- Keep the hierarchy clear: readable hook, focal content, then the intended CTA.\n Give characters/subjects enough visual weight; align visible content within\n its section instead of trusting transparent image bounds alone.\n- Measure margins, spacing, text wrapping and overlap. Check at phone viewing\n size, not only on a large canvas. Keep important text away from platform UI;\n inspect the relevant target presentation rather than assuming universal margins.\n- Use sampled reference colors and real render previews. Judge font, stroke,\n kerning, line height and emoji spacing together. Treat text-style fitting as a\n measured candidate, not proof of an exact font or pixel-perfect output.\n- Match the reference post's actual audio excerpt, mix, start and duration when\n requested. Preserve attribution separately. Empty transcription can mean music\n or unrecognized speech, not silence. Keep visual reveals and audio timing coherent.\n- Keep required CTA/contact copy present and legible across every requested\n variant. Use the user's actual destination/formatting, not a number copied from\n an old example. Vary copy intentionally without altering the required action.\n- Test with real content and multiple asset/copy lengths. A composition that\n works with one face or one short headline is not a validated reusable format.\n Inspect early, changing and final states; a still cannot certify a full video.\n\n## Deliver and describe the boundary\n\nProvide the workflow, its normal inputs, replayable example parameters, verified\nHTTPS previews, and any observed visual/audio limits. For videos verify decoding,\nduration/dimensions/audio and byte-range playback; images need correct content\ntype and decoding. Do not use local/localhost/private URLs as deliverables.\n\nSAM and automatic segmentation/overlay tracking are deferred. Use supplied\nassets, user-supplied boxes/masks or honest visual analysis; do not claim recovered\nsource layers or automatic clean cutouts. If the runtime cannot inspect a media\nmodality, record that limit and do not certify the uninspected property.\n",
|
|
9
9
|
"content-automation/references/build-review.md": "# Construct and review a reusable workflow\n\n## Discover the real interface\n\n`npx ugcinc list_node_types '{}'` lists current node metadata.\nUse `get_node_type '{\"nodeType\":\"...\"}'` for the nodes you choose and read the\nbundled `automations` skill for current tool parameters. These tools still need\na configured CLI key even when their own operation is local.\n\nConnections live on the target node, not a separate edges array:\n\n```json\n{\n \"nodes\": [\n {\n \"id\": \"target\",\n \"type\": \"node-type-from-discovery\",\n \"config\": {},\n \"inputs\": {\n \"actual-input-port\": {\n \"sourceNodeId\": \"source\",\n \"sourceOutputId\": \"actual-output-port\"\n }\n }\n }\n ]\n}\n```\n\nUse actual IDs/configuration returned by discovery, not these placeholders.\nConfigure dynamic interfaces before wiring them. Re-check ports after config\nchanges. Current validation requires a terminal outcome; inspect pass-through,\nsave-to-media and posting nodes to choose the intended behavior. Publishing is\nnot required just to make a reviewable workflow output.\n\nFor reusable sub-workflows, configure their input/output contracts explicitly\nand inspect the Compose Workflow node's actual schema. For custom Remotion,\ninspect `remotion-composition`; use its supported composition/props/import\ncontract. Do not invent an upload/register API or rely on arbitrary packages.\n\nValidate using `validate_workflow` with the shape described by the installed\nautomation skill/tool. Execute only the intended single test scope, inspect its\nstatus/output, and retain resolved inputs and seed. Saving a template or receiving\na run ID alone does not prove the output renders correctly.\n\n## Review a representative run\n\nCheck the viewer's actual sequence: hook visibility, subject size, changing state,\ntext wrapping/CTA, transitions and finish. Compare the full frame before zooming\ninto details. Inspect multiple points around animation/text changes. Re-test a\nlonger caption and a different asset where those vary in normal runs.\n\nDistinguish observed pixels/timestamps from estimates. Examples: sRGB sampling\ndoes not recover design colors from compression, transcript word timestamps are\nestimated, sampled OCR leaves gaps, and bounding boxes are not exact ink bounds.\nManually supplied boxes are allowed; describe how they were determined.\n\nPreserve both soundtrack bytes and source attribution. Check whether music is\nembedded or only attributed, whether the output repeats/truncates it, and whether\nvisual changes coincide with the intended moments. Do not invent beat detection,\naudio separation, universal media comparison or other unavailable tools.\n\nWhen revising content, name the concrete issue and inspect the changed output.\nKeep reusable parameters instead of baking a correction into one reference\nimage. Report remaining defects plainly; avoid calling a draft production-ready\nbased only on successful API execution.\n"
|
|
10
10
|
};
|