Scenes
A scene belongs to an episode and contains an ordered list of scene blocks (dialog or action lines).
Endpoints overviewβ
| Method | Endpoint | Permission | Description |
|---|---|---|---|
GET | /api/scenes | authenticated | List all scenes |
GET | /api/scenes/episode/:episodeId | authenticated | List scenes by episode |
GET | /api/scenes/:id | authenticated | Get scene by ID |
POST | /api/scenes | scene:create | Create a scene |
PUT / PATCH | /api/scenes/:id | scene:edit | Update a scene |
PUT | /api/scenes/episode/:episodeId/reorder | scene:edit | Reorder scenes in episode |
DELETE | /api/scenes/:id | scene:delete | Delete a scene |
POST | /api/scenes/:id/analyze-emotional-arc | scene:emotional_arc:generate | Analyze emotional arc |
PATCH | /api/scenes/:sceneId/assign-location | scene:location:assign | Assign location to scene |
POST | /api/scenes/:sceneId/blocks | scene:block:create | Add block |
POST | /api/scenes/:sceneId/action-dialog | scene:block:create | Add action/dialog pair |
PUT / PATCH | /api/scenes/:sceneId/blocks/:blockId | scene:block:edit | Update block |
PUT | /api/scenes/:sceneId/blocks/reorder | scene:block:edit | Reorder blocks in scene |
DELETE | /api/scenes/:sceneId/blocks/:blockId | scene:block:delete | Delete block |
POST | /api/scenes/:sceneId/blocks/:blockId/set-start-frame | scene:block:edit | Set start frame (base64) |
POST | /api/scenes/:sceneId/blocks/:blockId/generate-start-frame | scene:block:frame:generate | Generate start frame (AI) |
POST | /api/scenes/:sceneId/blocks/:blockId/generate-start-frame-from-images | scene:block:frame:generate | Generate start frame from images |
POST | /api/scenes/:sceneId/blocks/:blockId/generate-end-frame-from-images | scene:block:frame:generate | Generate end frame from images |
DELETE | /api/scenes/:sceneId/blocks/:blockId/start-frame | scene:block:frame:delete | Delete start frame |
DELETE | /api/scenes/:sceneId/blocks/:blockId/end-frame | scene:block:frame:delete | Delete end frame |
POST | /api/scenes/:sceneId/blocks/generate-video | scene:block:video:generate | Generate video for blocks |
DELETE | /api/scenes/:sceneId/blocks/:blockId/video | scene:block:video:delete | Delete block video |
Scene Endpointsβ
List all scenesβ
GET /api/scenes β Auth required
Response β 200
{
"scenes": [ /* array of scene objects */ ],
"total": 12
}
List scenes by episodeβ
GET /api/scenes/episode/:episodeId β Auth required
Response β 200
{
"scenes": [
{
"id": 1,
"episodeId": "ep-uuid-001",
"title": "Intro scene",
"index": 0,
"status": "draft",
"mood": "cheerful",
"titleI18n": { "uk": "ΠΡΡΡΠΏΠ½Π° ΡΡΠ΅Π½Π°", "en": "Intro scene", "es": "Escena introductoria" },
"songsCount": 0,
"actionsCount": 3,
"emotionalArc": ["joy", "surprise", "joy"],
"qualityScore": 0,
"blocks": [],
"duration": 45,
"location": null
}
],
"total": 1
}
Get scene by IDβ
GET /api/scenes/:id β Auth required
Response β 200 β single scene object (same shape as list item, with blocks array populated)
A block in the blocks array:
{
"id": "block-uuid-001",
"sceneId": "1",
"pairId": "pair-uuid",
"type": "dialog",
"text": "Hello, world!",
"characterId": "char-uuid-001",
"emotion": "joy",
"startSec": 0,
"endSec": 3.5,
"soundEffects": [
{
"id": "sound-uuid",
"name": "Fanfare",
"url": "/api/sounds/file/fanfare.mp3",
"duration": 2,
"soundStart": 0,
"soundEnd": 2,
"blockStart": 0,
"blockEnd": 2
}
],
"character": { "id": "char-uuid-001", "name": "Mia" },
"media": [],
"comments": [],
"voiceUrl": null,
"textI18n": { "uk": "ΠΡΠΈΠ²ΡΡ, ΡΠ²ΡΡ!", "en": "Hello, world!", "es": "Hola, mundo!" },
"intensity": null,
"startFrameUrl": null,
"endFrameUrl": null,
"startFrameGenerationParams": null,
"endFrameGenerationParams": null,
"videoUrl": null,
"videoGenerationParams": null
}
Create sceneβ
POST /api/scenes β Auth required, Permission: scene:create
Request body
{
"episodeId": "ep-uuid-001",
"title": "Intro scene",
"mood": "cheerful"
}
| Field | Required | Notes |
|---|---|---|
episodeId | yes | UUID of the parent episode |
title | yes | Auto-translated to all locales |
mood | no | Free-text mood description |
Response β 201 β created scene object
Update sceneβ
PUT /api/scenes/:id or PATCH /api/scenes/:id β Auth required, Permission: scene:edit
Request body (all fields optional)
{
"title": "Updated Scene",
"index": 2,
"status": "approved",
"mood": "tense",
"songsCount": 1,
"actionsCount": 4,
"emotionalArc": ["fear", "hope", "relief"],
"qualityScore": 8.5,
"changedBy": "editor@example.com"
}
status values: draft | approved
Response β 200 β updated scene object
Reorder scenes in episodeβ
PUT /api/scenes/episode/:episodeId/reorder β Auth required, Permission: scene:edit
Request body
{ "sceneIds": [3, 1, 2] }
Response β 200 β array of updated scene objects in new order
Delete sceneβ
DELETE /api/scenes/:id β Auth required, Permission: scene:delete
Response β 204
Analyze emotional arcβ
POST /api/scenes/:id/analyze-emotional-arc β Auth required, Permission: scene:emotional_arc:generate
Runs an LLM analysis of the scene's dialog blocks and writes the result to emotionalArc.
Response β 200 β updated scene object with emotionalArc populated
Assign location to sceneβ
PATCH /api/scenes/:sceneId/assign-location β Auth required, Permission: scene:location:assign
Request body
{ "locationId": "loc-uuid-001" }
Pass null for locationId to clear the assignment.
Response β 200 β updated scene object with location populated
Scene Blocksβ
Add blockβ
POST /api/scenes/:sceneId/blocks β Auth required, Permission: scene:block:create
Request body
{
"type": "dialog",
"text": "Hello, world!",
"pairId": null,
"characterId": "char-uuid-001",
"emotion": "joy",
"startSec": 0,
"endSec": 3.5,
"soundEffects": [],
"media": []
}
| Field | Required | Notes |
|---|---|---|
type | yes | dialog | action |
text | yes | Block content; auto-translated |
pairId | no | UUID linking an action+dialog pair |
characterId | no | Required for dialog blocks |
emotion | no | Emotion name/emoji |
startSec | no | Timestamp in seconds; defaults to 0 |
endSec | no | Timestamp in seconds; defaults to 0 |
soundEffects | no | Array of SoundEffectRef objects |
media | no | Array of BlockMedia objects |
Response β 201 β created block object
Add action/dialog pairβ
POST /api/scenes/:sceneId/action-dialog β Auth required, Permission: scene:block:create
Creates an action block and a dialog block together as a pair.
Request body
{
"actionText": "The hero steps forward",
"actionStartSec": 0,
"actionEndSec": 2,
"actionSoundEffects": [],
"dialogCharacter": "char-uuid-001",
"dialogText": "I will save you!",
"dialogEmotion": "determination",
"dialogStartSec": 2,
"dialogEndSec": 5
}
Response β 201
{
"action": { /* block object */ },
"dialog": { /* block object */ }
}
Update blockβ
PUT /api/scenes/:sceneId/blocks/:blockId or PATCH /api/scenes/:sceneId/blocks/:blockId β Auth required, Permission: scene:block:edit
Request body (all fields optional)
{
"type": "action",
"text": "Updated text",
"pairId": "pair-uuid",
"characterId": "char-uuid-001",
"emotion": "calm",
"startSec": 1.0,
"endSec": 4.5,
"soundEffects": [],
"media": [],
"voiceUrl": "/api/voices/file/proj/ep/scene/voices/take1.mp3",
"changedBy": "editor@example.com"
}
Response β 200 β updated block object
Reorder blocks in sceneβ
PUT /api/scenes/:sceneId/blocks/reorder β Auth required, Permission: scene:block:edit
Request body
{ "blockIds": ["block-uuid-003", "block-uuid-001", "block-uuid-002"] }
Response β 200 β array of updated block objects in new order
Delete blockβ
DELETE /api/scenes/:sceneId/blocks/:blockId β Auth required, Permission: scene:block:delete
Response β 204
Block Framesβ
Set start frame (base64)β
POST /api/scenes/:sceneId/blocks/:blockId/set-start-frame β Auth required, Permission: scene:block:edit
Request body
{
"imageBase64": "<base64-encoded-image-data>",
"mimeType": "image/png"
}
Response β 200 β updated block object with startFrameUrl set
Generate start frame (AI)β
POST /api/scenes/:sceneId/blocks/:blockId/generate-start-frame β Auth required, Permission: scene:block:frame:generate
Request body
{
"prompt": "A cheerful girl standing in a sunny meadow",
"width": 832,
"height": 480,
"steps": 28,
"guidanceScale": 3,
"noiseLevel": 0.35,
"seed": 42
}
| Field | Required | Default |
|---|---|---|
prompt | yes | β |
width | no | 832 |
height | no | 480 |
steps | no | 28 |
guidanceScale | no | 3 |
noiseLevel | no | 0.35 |
seed | no | random |
Response β 200 β updated block object with startFrameUrl and startFrameGenerationParams
Generate start frame from imagesβ
POST /api/scenes/:sceneId/blocks/:blockId/generate-start-frame-from-images β Auth required, Permission: scene:block:frame:generate
Request body
{
"prompt": "Combine these reference images into a new scene",
"image1Base64": "<base64>",
"image2Base64": "<base64>",
"image3Base64": null,
"image4Base64": null,
"image5Base64": null,
"steps": 28,
"guidanceScale": 3,
"width": 832,
"height": 480,
"seed": null
}
image1Base64 is required; image2Base64βimage5Base64 are optional.
Response β 200 β updated block object with startFrameUrl set
Generate end frame from imagesβ
POST /api/scenes/:sceneId/blocks/:blockId/generate-end-frame-from-images β Auth required, Permission: scene:block:frame:generate
Same request body shape as generate-start-frame-from-images.
Response β 200 β updated block object with endFrameUrl set
Delete start frameβ
DELETE /api/scenes/:sceneId/blocks/:blockId/start-frame β Auth required, Permission: scene:block:frame:delete
Response β 200 β updated block object with startFrameUrl: null
Delete end frameβ
DELETE /api/scenes/:sceneId/blocks/:blockId/end-frame β Auth required, Permission: scene:block:frame:delete
Response β 200 β updated block object with endFrameUrl: null
Block Videoβ
Generate video for blocks in sceneβ
POST /api/scenes/:sceneId/blocks/generate-video β Auth required, Permission: scene:block:video:generate
Request body
{
"blockId": "block-uuid-001",
"pairId": "pair-uuid",
"prompt": "A girl runs across a meadow in sunlight",
"imageBase64": "<start-frame-base64>",
"image2Base64": "<end-frame-base64>",
"width": 832,
"height": 480,
"duration": 5,
"frameRate": 24,
"steps": 28,
"guidance": 4.0,
"negativePrompt": "",
"useTwoStage": false,
"seed": null
}
| Field | Required | Default |
|---|---|---|
blockId | yes | β |
prompt | yes | β |
imageBase64 | yes | Start frame |
image2Base64 | yes | End frame |
pairId | no | |
width | no | 832 |
height | no | 480 |
duration | no | 5 |
frameRate | no | 24 |
steps | no | 28 |
guidance | no | 4.0 |
negativePrompt | no | "" |
useTwoStage | no | false |
seed | no | random |
Response β 200 β updated block object with videoUrl set
Delete block videoβ
DELETE /api/scenes/:sceneId/blocks/:blockId/video β Auth required, Permission: scene:block:video:delete
Response β 204