YouTube Thumbnail
imageimage/youtube-thumbnailPaste the video link. We read the video itself and stage a thumbnail about it, starring a real face.
Their photo
The thumbnail it staged for the videoYou give the video and a style; the server reads the page for the title and subject, then composes the layout, the legibility rules and the face-fidelity clauses itself. Your prompt only says how it should look.
Billed per image. $0.15, which covers reading the video as well as the render. Live rate from GET /v3/pricing.
A complete call
A thumbnail for a published video, starring one person.
1Upload the faces
Send every person or product the composition expects in one POST /v3/files/upload. Skip it entirely for no-person.
curl -X POST "https://api.neurall.io/v3/files/upload" \
-H "Authorization: nl-YOUR_API_KEY" \
-F "files=@face.jpg"It answers with the file ids
{
"files": [
{
"id": "f_9c21e0b4",
"originalName": "face.jpg",
"size": 690455
}
]
}2Submit the render
POST /v3/generations with the video link, the style and the ids from step 1.
curl -X POST "https://api.neurall.io/v3/generations" \
-H "Authorization: nl-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"feature": "image/youtube-thumbnail",
"args": {
"videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"prompt": "High-contrast tech review look: deep blue background, hard rim light, one bold accent color, generous negative space for a short headline.",
"composition": "person",
"images": [
"f_9c21e0b4"
],
"expressions": [
"excited"
]
}
}'It answers immediately
{
"generation": {
"id": "7d31…",
"feature": "image/youtube-thumbnail",
"kind": "image",
"status": "pending"
}
}3Poll until it lands
Poll GET /v3/generations/{id}, or pass webhookUrl and skip polling.
# repeat every 2s or so until status is done, error or timeout
curl "https://api.neurall.io/v3/generations/9f2c1d84-6a3b-4f21-9c77-2f0a1b8e5d43" \
-H "Authorization: nl-YOUR_API_KEY"Once status is done
{
"generation": {
"status": "done",
"output": {
"image": "https://cdn.neurall.io/…/image.png",
"mime": "image/png"
}
}
}output holds the finished asset on a signed CDN URL. Download it rather than hotlinking: API-created outputs expire 24 hours after the request.
Arguments
videoUrlstring- The video the thumbnail is for. We fetch it and read the title and topic. Send this OR videoDescription, never both.
- A well-formed http(s) URL. Sending both videoUrl and videoDescription is a 400.
videoDescriptionstring- What the video is about, when it is not published yet. The alternative to videoUrl.
- At most 2000 characters.
promptstringrequired- The creative STYLE only: palette, energy, treatment. Layout, legibility and fidelity clauses are appended server-side.
- At most 2000 characters.
composition'person' | 'two-people' | 'person-product' | 'product' | 'two-products' | 'no-person'defaults to 'person'- What is in the frame. It decides how many reference images the render expects.
imagesarray- The references, in the order the composition implies. Each entry is a plain file id from POST /v3/files/upload.
- PNG, JPEG, WebP, GIF, HEIC or AVIF, up to 30 MB and 30 megapixels per file, 10 files per upload request.
- An uploaded file is deleted 24 hours after it lands, so upload again for a later render rather than caching an id.
- The count must match the composition: person takes one, two-people takes two, no-person takes none.
args.images[0]The person, or the first person- Say "the person" if the prompt needs to mention them at all. Do not describe their face; it is preserved from the photo.
args.images[1]The second person, or the product- On two-people this is the second face; on person-product it is the product. Refer to it as "the product" and the render maps that to this slot.
expressionsstring[]- One expression per person in the composition, in the same order as images.
brandobject- Brand kit values, raw: background, text and accent are hex colors, all three required when brand is sent; name and voice (a short tone description) are optional strings; logo is an optional file id from POST /v3/files/upload (upload the logo file first); do not put it in images or count it in the composition, the server adds it after the reference photos and places it small in one corner.
How the prompt refers to these
An image you send but never mention still occupies its slot. Send only what the composition expects.
Output
Once status is done, the generation carries an output object with these fields. On any other status, output is absent.
imagestring- The finished thumbnail, as a URL.
- A signed URL that expires 24 hours after the request (expiresAt on the generation). Download the file rather than hotlinking it.
mimestring- The image's MIME type, e.g. image/png.
Limits and failure
- Video source
- Exactly one of videoUrl or videoDescription.
- Images
- As many as the composition implies, 30 MB and 30 megapixels each, deleted 24 hours after upload.
- Likeness
- A real person in the frame requires their permission; the Terms of Use cover it, there is nothing to send.
- Render time
- A generation that has not finished in 15 minutes is marked timeout and refunded.
- Concurrency
- Your plan caps how many generations run at once. Over it the API answers 429 with a Retry-After header; wait that many seconds rather than retrying immediately.
- Output lifetime
- API-created outputs expire 24 hours after the request (expiresAt on the generation). Download the file rather than hotlinking it.
- Deletion
- DELETE /v3/generations/{id} removes the generation and its rendered assets immediately, rather than waiting for the 24 hour expiry. It does not refund anything and cannot cancel a render already in flight.
- Failure
- A failed or timed-out generation is refunded automatically.
Worth knowing
- Reading the video happens server-side and is part of the price; you do not pass a transcript or a title.
- The output is 16:9 by design. There is no ratio argument.