Skip to content
AINSOFAPI Get API key

GuidesScore a video

Score a video

Send a video link and get an MP4 back, with AINSOF music placed on the real cuts, silences where you ask, a change of track between sections, and the mix kept under dialogue. Leave out the brief and AINSOF reads the film first and chooses. Watching is free; downloading the file asks for a quick sign-in on ainsof.io.

MCP toolscore_my_videoRESTaction: "score_video"

Try it

curl https://mcp.ainsof.io/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AINSOF_API_KEY" \
  -d '{"action": "score_video", "video_url": "https://example.com/my-video.mp4", "brief": "warm, hopeful acoustic"}'

The whole flow in one script

Upload a file, score it, then collect the files, repeating each request while it is still running.

import os, time, requests

API = "https://mcp.ainsof.io/"
H = {"Authorization": f"Bearer {os.environ['AINSOF_API_KEY']}"}

def call(body, tries=30):
    # repeat the identical request while the job is still running
    for _ in range(tries):
        r = requests.post(API, headers=H, json=body, timeout=60)
        data = r.json()
        if data.get("error") != "still_running":
            if not data.get("ok"):
                raise RuntimeError(data)
            return data
        time.sleep(5)
    raise TimeoutError("still running")

# 1. a video on this computer: get an upload slot and send the file
slot = call({"action": "get_upload_link", "filename": "cut.mp4"})
with open("cut.mp4", "rb") as f:
    # use the file's own type: video/mp4, video/quicktime (.mov), video/x-m4v or video/webm
    requests.put(slot["upload_url"], data=f, headers={"Content-Type": "video/mp4"}, timeout=600).raise_for_status()

# 2. score it, then 3. collect the files
job = {"action": "score_video", "video_url": slot["video_url"], "brief": "warm, hopeful acoustic"}
scored = call(job)
print(scored["download_url"])
files = call({**job, "action": "deliver_score"})
print(files["download_url"])

What you send

video_urlrequired
string
The video (see above).
Also accepted as url
sign_in_code
string
The code returned with sign_in_required, once the person has signed in. Pass the same code to every video action; it stays valid for 30 days. Not needed with a key created on ainsof.io.
brief
string
The music wanted, in English. Leave it out and AINSOF reads the film first and chooses.
track_id
string
Use this exact cue instead of choosing one.
version
string
Force a version, e.g. CUT_30. Upper-cased.
music_offset_db
number
Music level relative to the video's own audio, in dB. Negative is quieter; 0 is level. When omitted, the renderer's default applies.
silences
array
Music-free moments: objects with at (seconds, required) and for (duration in seconds, default 1).
sections
array
Timed acts, each scored separately: from and to (seconds, required), plus brief (English), track_id, version or stems (an array of stem names from that cue; the schema asks for track_id with it). Every section needs a brief, track_id or stems.
user_request
string
Optional. In one sentence, what the user wants the music to do for this video, in their own words. Kept for 30 days to review how well the music fit, then deleted.
Longer text is cut to 500 characters.
project_type
string
Optional. What kind of project the video is. Kept as anonymous usage statistics. Other values are stored as other.
Allowed: ad, social, documentary, film, trailer, game, corporate, event, podcast, music_video, other
music_intent
string
Optional. The music the user wants, e.g. tense build, minimal, no vocals. Kept as anonymous usage statistics.
At most 8 English words (longer text is cut to 8), no names.

Good to know

  • Before AINSOF works with a video, a person signs in once on ainsof.io (Google or email). With a key created on ainsof.io this has already happened. Without one, the first request answers 401 sign_in_required with sign_in_url and sign_in_code: show the link, and when the person has signed in, repeat the request with sign_in_code.
  • video_url accepts a direct link to a video file, a Dropbox or Google Drive share link, or the video_url returned by get_upload_link. YouTube, Vimeo, Dailymotion and Twitch pages are not supported.
  • brief, track_id and sections are all optional: leave them out and AINSOF watches the film first and chooses the music for what it shows and how it feels (returned as film).
  • Section and silence boundaries are moved onto the video's measured cuts.
  • An identical request made within 15 minutes returns the same render rather than starting another. Requests made with a key are only matched to that key's renders.
  • Renders usually take longer than one request waits: expect 202 still_running, and repeat the same request unchanged. That reply includes delivery_request with the arguments to repeat (add your sign_in_code if you signed in without a key).
  • Watching the result is free. Downloading the file opens ainsof.io, which asks for a quick sign-in (Google or email) first.
  • Videos up to 15 minutes.

Every field it returns, and its errors, in the API Reference