Close OSS self-host gaps: in-repo API docs, legal notes, and packaging.
Add MIT license and docs/api, strip SaaS status/admin remnants from robots and footer, align env/compose/README with payment-free product truth.
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
# Endpoints
|
||||
|
||||
Set these for the examples below:
|
||||
|
||||
```bash
|
||||
export BASE_URL="http://localhost:3000" # local / self-hosted app
|
||||
export API_KEY="s2yt_live_your_key_here"
|
||||
```
|
||||
|
||||
Live HTML docs: [docs.songs2vid.com/docs/api/endpoints](https://docs.songs2vid.com/docs/api/endpoints).
|
||||
|
||||
## Discovery
|
||||
|
||||
```bash
|
||||
curl "$BASE_URL/api/v1"
|
||||
```
|
||||
|
||||
Returns the endpoint list and requirements (**no auth**). No billing routes are listed or implemented.
|
||||
|
||||
## Upload a file (two-step)
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/upload" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-F "file=@cover.jpg" \
|
||||
-F "type=image"
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/upload" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-F "file=@track1.mp3" \
|
||||
-F "type=audio"
|
||||
```
|
||||
|
||||
```bash
|
||||
# Optional: PNG watermark logo
|
||||
curl -X POST "$BASE_URL/api/v1/upload" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-F "file=@logo.png" \
|
||||
-F "type=logo"
|
||||
```
|
||||
|
||||
```bash
|
||||
# Optional: custom font (.ttf / .otf, max 10 MB)
|
||||
curl -X POST "$BASE_URL/api/v1/upload" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-F "file=@Brand.ttf" \
|
||||
-F "type=font"
|
||||
```
|
||||
|
||||
### Request fields
|
||||
|
||||
| Field | Required | Notes |
|
||||
|-------|----------|--------|
|
||||
| `file` | Yes | Multipart file |
|
||||
| `type` | Yes | `image` \| `audio` \| `logo` \| `font` |
|
||||
|
||||
### Allowed files
|
||||
|
||||
| `type` | Formats | Max size |
|
||||
|--------|---------|----------|
|
||||
| `image` | JPEG, PNG, WebP, GIF | 500 MB |
|
||||
| `audio` | MP3, WAV, FLAC | 500 MB |
|
||||
| `logo` | PNG only | 500 MB |
|
||||
| `font` | `.ttf` / `.otf` | **10 MB** |
|
||||
|
||||
### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "/uploads/.../track.mp3",
|
||||
"filename": "track.mp3",
|
||||
"size": 4123456,
|
||||
"audioTags": {
|
||||
"title": "Song Title",
|
||||
"artist": "Artist Name",
|
||||
"album": "Album",
|
||||
"genre": "Electronic",
|
||||
"year": "2024"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`audioTags` is present for MP3 when tags are readable; otherwise `null`.
|
||||
|
||||
## Create job from paths (recommended)
|
||||
|
||||
Self-hosted unlocks per-track covers, custom watermarks/fonts, and art-track layouts. Max batch size: **100**. Watermarks are optional — nothing forces the default Songs2VID badge.
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/jobs" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"imagePath": "/uploads/.../cover.jpg",
|
||||
"items": [{
|
||||
"audioPath": "/uploads/.../track.mp3",
|
||||
"audioFilename": "track.mp3",
|
||||
"metadata": {
|
||||
"title": "My Artist - My Track (Official Audio)",
|
||||
"songTitle": "My Track",
|
||||
"artist": "My Artist",
|
||||
"description": "",
|
||||
"tags": "electronic",
|
||||
"privacy": "PUBLIC",
|
||||
"categoryId": "10",
|
||||
"resolution": "1920x1080",
|
||||
"notifySubscribers": true,
|
||||
"madeForKids": false,
|
||||
"embeddable": true,
|
||||
"creativeCommons": false,
|
||||
"includeWatermark": true,
|
||||
"layout": {
|
||||
"template": "COVER_LEFT_TEXT_RIGHT",
|
||||
"blurAmount": 60,
|
||||
"blurOpacity": 85,
|
||||
"textPadding": 48,
|
||||
"titleArtistGap": 12,
|
||||
"textOffsetX": 0,
|
||||
"textOffsetY": 0
|
||||
},
|
||||
"watermark": {
|
||||
"mode": "default",
|
||||
"fontKey": "montserrat",
|
||||
"position": "bottom-right",
|
||||
"offsetX": 24,
|
||||
"offsetY": 24
|
||||
},
|
||||
"playlistId": null
|
||||
}
|
||||
}]
|
||||
}'
|
||||
```
|
||||
|
||||
### Success response
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": "clxxxxxxxx",
|
||||
"itemCount": 1,
|
||||
"status": "PENDING",
|
||||
"playlist": null
|
||||
}
|
||||
```
|
||||
|
||||
### Metadata fields
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|--------|
|
||||
| `title` | string | YouTube video title |
|
||||
| `songTitle` | string \| null | On-video song title for art-track (max **120**) |
|
||||
| `artist` | string \| null | On-video artist line (max **80**) |
|
||||
| `description` | string | YouTube description |
|
||||
| `tags` | string | Comma-separated |
|
||||
| `privacy` | string | `PUBLIC` \| `PRIVATE` \| `UNLISTED` |
|
||||
| `categoryId` | string | YouTube category ID |
|
||||
| `resolution` | string | See resolutions below |
|
||||
| `notifySubscribers` | boolean | YouTube notify flag |
|
||||
| `madeForKids` | boolean | Made for kids |
|
||||
| `embeddable` | boolean | Allow embedding |
|
||||
| `creativeCommons` | boolean | CC vs standard YouTube license |
|
||||
| `includeWatermark` | boolean | Apply watermark settings |
|
||||
| `imagePath` | string \| null | Per-track cover |
|
||||
| `playlistId` | string \| null | Existing playlist ID |
|
||||
| `layout` | object | Art-track layout |
|
||||
| `watermark` | object | Watermark settings |
|
||||
|
||||
Snake_case aliases are accepted for layout/watermark fields.
|
||||
|
||||
### Resolutions
|
||||
|
||||
| Value | Aspect |
|
||||
|-------|--------|
|
||||
| `1920x1080` | 16:9 |
|
||||
| `1280x720` | 16:9 |
|
||||
| `854x480` | 16:9 |
|
||||
| `720x720` | 1:1 |
|
||||
| `640x360` | 16:9 |
|
||||
| `426x240` | 16:9 |
|
||||
|
||||
### YouTube categories
|
||||
|
||||
| ID | Name |
|
||||
|----|------|
|
||||
| `1` | Film & Animation |
|
||||
| `2` | Autos & Vehicles |
|
||||
| `10` | Music |
|
||||
| `15` | Pets & Animals |
|
||||
| `17` | Sports |
|
||||
| `19` | Travel & Events |
|
||||
| `20` | Gaming |
|
||||
| `22` | People & Blogs |
|
||||
| `23` | Comedy |
|
||||
| `24` | Entertainment |
|
||||
| `25` | News & Politics |
|
||||
| `26` | Howto & Style |
|
||||
| `27` | Education |
|
||||
| `28` | Science & Technology |
|
||||
| `29` | Nonprofits & Activism |
|
||||
|
||||
### Watermark fields
|
||||
|
||||
`watermark.mode`: `none` | `default` | `text` | `logo`
|
||||
|
||||
- `none` — no overlay
|
||||
- `default` — built-in Songs2VID badge PNG (`assets/watermark.png`)
|
||||
- `logo` — requires prior `type=logo` upload; set `logoPath`
|
||||
- `text` — custom string (max **80**); set `text`
|
||||
|
||||
`watermark.position`: `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center`
|
||||
|
||||
`watermark.offsetX` / `offsetY`: `0`–`200` (default `20`)
|
||||
|
||||
`watermark.fontKey`: `system` | `inter` | `montserrat` | `roboto` | `oswald` | `playfair` | `custom` (styles art-track text and text watermarks)
|
||||
|
||||
### Art-track layouts
|
||||
|
||||
`metadata.layout.template`:
|
||||
|
||||
| Enum | Description |
|
||||
|------|-------------|
|
||||
| `COVER_LEFT_TEXT_RIGHT` | Cover left, title & artist right |
|
||||
| `COVER_TOP_TEXT_BOTTOM` | Cover top, title & artist below |
|
||||
| `COVER_RIGHT_TEXT_LEFT` | Cover right, title & artist left |
|
||||
| `CENTERED_COMPACT` | Centered cover + text stack |
|
||||
|
||||
Fine-tuning (defaults in parentheses): `blurAmount` (55), `blurOpacity` (100), `textPadding` (48), `titleArtistGap` (10), `textOffsetX` (0), `textOffsetY` (0).
|
||||
|
||||
## YouTube playlists
|
||||
|
||||
```bash
|
||||
curl "$BASE_URL/api/v1/playlists" \
|
||||
-H "Authorization: Bearer $API_KEY"
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/playlists" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title":"My Album","description":"From Songs2VID","privacy":"unlisted"}'
|
||||
```
|
||||
|
||||
Or pass `createPlaylist` on a job / batch body to create a playlist and attach all videos.
|
||||
|
||||
## One-shot batch (small packs only)
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/jobs/batch" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-F "image=@cover.jpg" \
|
||||
-F "audio=@track1.mp3" \
|
||||
-F "audio=@track2.mp3" \
|
||||
-F 'metadata={"defaults":{"privacy":"PUBLIC"},"items":[{"title":"Track One"},{"title":"Track Two"}]}'
|
||||
```
|
||||
|
||||
Prefer two-step upload + jobs for larger packs.
|
||||
|
||||
## Poll job status
|
||||
|
||||
```bash
|
||||
curl "$BASE_URL/api/v1/jobs/JOB_ID" \
|
||||
-H "Authorization: Bearer $API_KEY"
|
||||
```
|
||||
|
||||
```bash
|
||||
curl "$BASE_URL/api/v1/jobs?limit=10" \
|
||||
-H "Authorization: Bearer $API_KEY"
|
||||
```
|
||||
|
||||
`GET /api/v1/jobs` accepts `limit` (default **20**, max **100**).
|
||||
|
||||
### Job statuses
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| `PENDING` | Queued |
|
||||
| `PROCESSING` | Encoding or uploading |
|
||||
| `COMPLETED` | All items succeeded |
|
||||
| `FAILED` | All items failed |
|
||||
| `PARTIAL` | Mix of completed and failed |
|
||||
|
||||
### Item statuses
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| `PENDING` | Waiting |
|
||||
| `ENCODING` | FFmpeg building video |
|
||||
| `UPLOADING` | Uploading to YouTube |
|
||||
| `COMPLETED` | Live (`youtubeVideoId` set) |
|
||||
| `FAILED` | Failed (`error` message) |
|
||||
|
||||
YouTube channel daily upload caps are enforced by Google, not Songs2VID.
|
||||
|
||||
## HTTP errors
|
||||
|
||||
| Status | When |
|
||||
|--------|------|
|
||||
| `400` | Validation error |
|
||||
| `401` | Missing or invalid API key |
|
||||
| `403` | YouTube not connected, or request not allowed |
|
||||
| `404` | Job not found |
|
||||
| `429` | API rate limit exceeded |
|
||||
|
||||
There is no `402` payment / credits status in OSS.
|
||||
@@ -0,0 +1,66 @@
|
||||
# API overview
|
||||
|
||||
Programmatic uploads and batch jobs for self-hosted Songs2VID. Generate your API key under **Dashboard → Settings → API key**.
|
||||
|
||||
Keys start with `s2yt_live_` and are shown once at creation. The OSS / Docker image always allows API use — there is no plan, credit, or paywall gate.
|
||||
|
||||
There are **no billing endpoints** in this edition.
|
||||
|
||||
## Authentication
|
||||
|
||||
Send the key on every request:
|
||||
|
||||
```http
|
||||
Authorization: Bearer s2yt_live_your_key_here
|
||||
```
|
||||
|
||||
Requirements:
|
||||
|
||||
- YouTube channel connected (sign in with Google OAuth that includes YouTube scopes)
|
||||
|
||||
OAuth setup: root [README](../../README.md) and Google’s [OAuth 2.0 for Web Server Applications](https://developers.google.com/identity/protocols/oauth2/web-server). YouTube scopes/API: [YouTube Data API Overview](https://developers.google.com/youtube/v3/getting-started).
|
||||
|
||||
## Rate limits
|
||||
|
||||
Self-hosted OSS uses a very high per-account ceiling (effectively unlimited for normal automation). You will rarely see `429`.
|
||||
|
||||
If a limit is hit, the response is **429** with `retryAfterSeconds` and a `Retry-After` header. See [Endpoints — HTTP errors](./endpoints.md#http-errors).
|
||||
|
||||
## Choosing a flow
|
||||
|
||||
### Recommended: two-step (especially 5+ audio files)
|
||||
|
||||
1. Upload each file with `POST /api/v1/upload`
|
||||
2. Create the job with `POST /api/v1/jobs` (JSON paths)
|
||||
|
||||
This avoids huge multipart bodies. Max batch size is **100** tracks per job.
|
||||
|
||||
### One-shot batch: small packs only
|
||||
|
||||
`POST /api/v1/jobs/batch` accepts one cover image and a few audio files in a single multipart request. Large bodies often fail with:
|
||||
|
||||
```text
|
||||
failed to parse body as FormData
|
||||
```
|
||||
|
||||
Prefer two-step for albums or long tracklists.
|
||||
|
||||
## Job lifecycle
|
||||
|
||||
1. Create job → status `PENDING`
|
||||
2. Worker picks items → `ENCODING` → `UPLOADING` → `COMPLETED` or `FAILED`
|
||||
3. Job rolls up to `COMPLETED`, `FAILED`, or `PARTIAL`
|
||||
|
||||
Poll with `GET /api/v1/jobs/:id`.
|
||||
|
||||
## Discovery
|
||||
|
||||
```http
|
||||
GET /api/v1
|
||||
```
|
||||
|
||||
Returns the endpoint list and requirements (no auth). Useful as a machine-readable catalog of what this instance exposes.
|
||||
|
||||
## Next
|
||||
|
||||
See [Endpoints](./endpoints.md) for curl examples. Hosted HTML docs: [docs.songs2vid.com/docs/api/overview](https://docs.songs2vid.com/docs/api/overview).
|
||||
Reference in New Issue
Block a user