Video Material Search (for Smart Editing)

Search the copyrighted video material library with a single natural-language scene description or keywords, and get back clips ready to drop onto a timeline — including the best-matching in-clip time ranges (segments), a direct media URL, duration, orientation and fps. Returns synchronously, no polling required.

Designed for smart editing / auto-assembly: query material shot-by-shot from a storyboard, then stitch onto the timeline.

Search Endpoint

Basic Info

ItemValue
MethodPOST
Path/task/video_clip_search
Content-Typeapplication/json
AuthAuthorization header (pass the API Key directly)
ResponseSynchronous search results (not an async task)
Billing1 credit per search (auto-refunded on failure; the response carries a task_id for task lookup. Every material a search returns is permanently granted to you — from then on, re-sign fresh download links for free and without limit via material re-sign)

Request Body

FieldTypeRequiredDefaultDescription
querystringYes—Scene description (natural language) or keywords
top_kintegerNo10Number of results, max 50
diversitybooleanNofalseDe-duplicate near-identical shots
request_idstringNo—uuid, echoed back, for idempotency / tracing
filtersobjectNo—Editing-oriented filters, see below

filters Fields

FieldTypeDescription
min_durationnumberMinimum clip duration (seconds)
max_durationnumberMaximum clip duration (seconds)
orientationstringlandscape / portrait / square, to match the output canvas
min_widthintegerMinimum resolution width (pixels)
exclude_idsarray<integer>Material ids to exclude (already used in the same cut)

Request Example

curl -X POST https://api.ai-mcn.tv:10000/task/video_clip_search \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "silhouette of a person with a camera on a coastal rock at sunset",
    "top_k": 10,
    "diversity": true,
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "filters": {
      "min_duration": 3,
      "orientation": "landscape",
      "min_width": 1920
    }
  }'

Success Response Example

{
  "code": 200,
  "msg": "success",
  "data": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "recalled": 84,
    "results": [
      {
        "clip_id": 2693564728807342,
        "score": 0.87,
        "url": "https://cdn.example.com/nmcn/material/video_clip/raw/2693564728807342.mp4?expires=1750086000&sign=Xa1b2C3d4E5f6G7h8I9j0k",
        "cover_url": "https://cdn.example.com/nmcn/material/video_clip/keyframe/2693564728807342/cover.jpg",
        "preview_url": "https://cdn.example.com/nmcn/material/video_clip/preview/2693564728807342.mp4",
        "duration": 12.4,
        "width": 3840,
        "height": 2160,
        "fps": 25,
        "orientation": "landscape",
        "segments": [
          { "start": 2.0, "end": 8.5, "best": 5.2, "score": 0.91 }
        ],
        "matched": { "facets": { "time_of_day": ["dusk"], "scene": ["coast"] } },
        "note": "Dusk by the sea; a person on the rocky shore filming the water."
      }
    ]
  }
}

Response Fields

FieldTypeDescription
recalledintegerTotal recalled (before filtering), for observability
results[].clip_idintegerMaterial id. Note: this is a large integer that may exceed JS Number.MAX_SAFE_INTEGER (2^53) — JavaScript consumers should treat it as a string (e.g. quote the field at the response-text level before parsing), otherwise precision loss can collide ids of different materials
results[].scorenumberRelevance score (after rerank, sorted descending)
results[].urlstringTemporary media URL (mp4, expires in 24h via ?expires=&sign=; after expiry, get a fresh link for free via Material Link Re-signing)
results[].cover_urlstringRepresentative cover image (unsigned, never expires)
results[].preview_urlstringLow-res preview proxy (mp4, width ≤640, no audio track; unsigned, never expires). Ideal for list previews and a proxy-editing workflow: rough-cut with the small proxy first, then download the original via url when finalizing
results[].durationnumberDuration (seconds)
results[].width / heightintegerResolution (pixels)
results[].fpsnumberFrame rate
results[].orientationstringCanvas orientation
results[].segmentsarrayIn-clip matching ranges (sorted by score; first = best)
results[].segments[].start / endnumberRange bounds (seconds), ready for the timeline; end always stays within the clip's duration
results[].segments[].bestnumberBest-matching timestamp within the range (seconds)
results[].matched.facetsobjectMatched visual attributes (scene / time-of-day, etc.)
results[].notestringMaterial text description

Error Codes

CodeHTTPDescriptionResolution
400400Malformed request body (body is not a valid JSON object)Check the request body
6502401Authentication failedCheck the API Key in the Authorization header
6401500Upstream search service unavailable, or request parameters rejected by the search layer (e.g. empty query, invalid orientation/filters values)Verify request parameters first; if correct, retry later
6402500Upstream search service timeoutRetry later

Determine success/failure from the code field in the response body, not the HTTP status code (top_k overflow does not error — it is clamped to 50).

Limits

  • top_k is capped at 50 (clamped automatically).
  • This endpoint takes a single query; for multiple shots, call it concurrently (batch input is a future capability).
  • Searches the copyrighted library only; material quality level is not differentiated.
  • The media url expires in 24h; after expiry, use Material Link Re-signing to get fresh links free and unlimited — once searched, always granted, no paid re-search needed (cover_url / preview_url are unsigned and never expire).
  • segments are based on keyframes sampled every 1.5s, so localization accuracy is about ±1.5s.

🤝 Join the Tonghe New Media Network to unlock internal member benefits: network members (internal) get custom-scope full-library material search (video / image / audio, including concept and non-commercial materials, with a commercial-only filter) and exclusive internal voices. Apply at the Creator Network; once approved, an administrator will enable internal access for you.