Soundtrack a video
Overview

Soundtrack a video

Score any video automatically. Submit a clip (uploaded file or YouTube URL), get a ranked list of Slipstream tracks that match the video's tone, pacing, and mood. Optionally render a final video with the track mixed in.

This isn't a single endpoint. It's an orchestration of four. The good news: each step is small, and you can stop after step 2 if all you need is the track list.

The flow

  1. Upload the video, either as a file or as a YouTube URL. You get back a SoundtrackVideo with an id and a source_value.
  2. Search for matching tracks by passing that source_value to the AI search endpoint. You get back a ranked list of tracks.
  3. The user picks a track in your UI.
  4. Render and download a new video with the track mixed in. Only available for uploaded files, not YouTube URLs.

Step 1 — Upload the video

You have two options:

Upload a file (multipart form):

curl https://api.slipstreammusic.com/api/v4/soundtrack/video/ \
  -X POST \
  -H "Authorization: Bearer $PARTNER_API_KEY" \
  -F "file=@/path/to/clip.mp4"

Accepted formats: .mov, .mpeg, .mp4, .avi. Max 60 MB.

Or pass a YouTube URL (JSON):

curl https://api.slipstreammusic.com/api/v4/soundtrack/video/ \
  -X POST \
  -H "Authorization: Bearer $PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'

Response — 201 Created:

{
  "id": "8a4b2c1d-9e7f-4a6b-b3c2-1f8d4e5a7c6b",
  "source_type": "file",
  "source_value": "5f3e7d9c8b2a4f1e6d0c5b8a3e2f7d9c",
  "source_title": "clip.mp4",
  "file": "https://media.slipstreammusic.com/.../clip.mp4"
}

Hold on to two things: id (used in step 4) and source_value (used in step 2).

Uploaded files are stored temporarily and expire after a few days. If your user needs to revisit the result later, store the id and reference the same video in subsequent calls before it expires.

Step 2 — Search for matching tracks

Pass source_value to the AI search:

curl "https://api.slipstreammusic.com/api/v4/search/ai/by-video/?value=5f3e7d9c8b2a4f1e6d0c5b8a3e2f7d9c&limit=20" \
  -H "Authorization: Bearer $PARTNER_API_KEY"

The value parameter accepts both forms returned by step 1:

  • An AIMS hash (32-char hex), when the user uploaded a file.
  • A YouTube URL, when the user submitted a link.

You can narrow results with the same filter parameters used everywhere else in Search — genre, mood, bpm__range, etc.

Response — paginated list of Track objects, ranked by match score.

If you only need the track list, you can stop here. Show the results, let the user play previews, and you're done. The remaining steps are for delivering a finished video.

Step 3 — User picks a track

Render the results in your UI. Each Track has audio_url (a stream-proxy path) so users can preview without leaving your page.

When the user clicks a track to confirm, capture its id. That's what step 4 needs.

Step 4 — Render and download

Generate a single video with the chosen track mixed against the original audio. Only works for uploaded files — YouTube videos are licensed differently and can't be re-rendered.

curl https://api.slipstreammusic.com/api/v4/soundtrack/video/$VIDEO_ID/download/ \
  -X POST \
  -H "Authorization: Bearer $PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "track_id": "1f3c4d5e-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
    "video_volume": 0.2,
    "track_volume": 1.0,
    "track_start": 0
  }'
FieldTypeDescription
track_idUUIDThe picked track from step 3.
video_volumefloat, 0.01.0How much of the original video audio to keep. 0 mutes it. Default 1.0.
track_volumefloat, 0.01.0The new track's volume. Default 1.0.
track_startfloat, secondsWhere in the track to start playing. Useful for skipping intros. Default 0.

The render is async. You'll get one of two responses:

200 OK — already cached, ready to download:

{ "url": "https://media.slipstreammusic.com/.../rendered.mp4" }

202 Accepted — being processed, retry shortly:

{
  "send_email": true,
  "detail": "Download is being prepared. Please try again in a few moments."
}

If send_email is true, the user will get an email with the download link once rendering finishes. Polling the same endpoint with the same parameters will return 200 with the URL once it's ready.

Error cases worth handling

WhatWhenWhat to do
422 Unprocessable Entity on uploadVideo can't be analyzed (corrupt, too short, no audio)Show the user error_code and detail from the body
400 on downloadTrying to render a YouTube-source videoTell the user that downloads are only available for uploaded files
404 on retrieveSource file expiredRe-upload from the original
401 on downloadCaller isn't authenticatedThe download endpoint requires a signed-in user

Tips

  • Step 2 is cacheable. The same source_value returns the same ranked list. Cache it client-side per session so users can refine filters without re-running the AI.
  • Step 4 is idempotent for given parameters. Same video + same track + same volumes = same rendered URL. Reuse it.
  • Stop at step 2 if your product just needs suggestions. Steps 3 and 4 are only for products that ship a finished video back.

Endpoint reference