Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ val model = RealtimeModels.LUCY_2_1
val localStream = realtime.createLocalVideoStream(model) // uses model.width/model.height
```

The Lucy 2.1 realtime model configs use `1088x624`. The default LiveKit publisher codec is VP8; override it only when needed via `RealtimeConfiguration.VideoConfig(preferredCodec = ...)`.
The Lucy 2.1 realtime model configs use `1280x720`. The default LiveKit publisher codec is VP8; override it only when needed via `RealtimeConfiguration.VideoConfig(preferredCodec = ...)`.

### Realtime camera mirroring

Expand Down Expand Up @@ -313,7 +313,7 @@ client.queue.submit(VideoModels.LUCY_RESTYLE_2, restyle)

| Model | Constant | Resolution | FPS |
|-------|----------|-----------|-----|
| Lucy 2.1 | `RealtimeModels.LUCY_2_1` | 1088x624 | 30 |
| Lucy 2.1 | `RealtimeModels.LUCY_2_1` | 1280x720 | 30 |
| Lucy 2.5 | `RealtimeModels.LUCY_2_5` | 1280x720 | 30 |
| Lucy VTON 3.5 | `RealtimeModels.LUCY_VTON_3_5` | 1280x720 | 30 |
| Lucy VTON 3.6 | `RealtimeModels.LUCY_VTON_3_6` | 1280x720 | 30 |
Expand All @@ -323,16 +323,15 @@ client.queue.submit(VideoModels.LUCY_RESTYLE_2, restyle)

| Model | Constant | Queue Path | Resolution | FPS |
|-------|----------|------------|------------|-----|
| Lucy Clip | `VideoModels.LUCY_CLIP` | `/v1/jobs/lucy-clip` | 1280x704 | 25 |
| Lucy 2.1 | `VideoModels.LUCY_2_1` | `/v1/jobs/lucy-2.1` | 1088x624 | 20 |
| Lucy 2.1 | `VideoModels.LUCY_2_1` | `/v1/jobs/lucy-2.1` | 1280x720 | 20 |
| Lucy 2.5 | `VideoModels.LUCY_2_5` | `/v1/jobs/lucy-2.5` | 1280x720 | 20 |
| Lucy VTON 3.5 | `VideoModels.LUCY_VTON_3_5` | `/v1/jobs/lucy-vton-3.5` | 1280x720 | 20 |
| Lucy VTON 3.6 | `VideoModels.LUCY_VTON_3_6` | `/v1/jobs/lucy-vton-3.6` | 1280x720 | 20 |
| Lucy Restyle 2 | `VideoModels.LUCY_RESTYLE_2` | `/v1/jobs/lucy-restyle-2` | 1280x704 | 22 |

Typed input helpers:

- `VideoEditInput` (`lucy-2.1`, `lucy-2.5`, `lucy-vton-3.5`, `lucy-vton-3.6`, `lucy-clip`)
- `VideoEditInput` (`lucy-2.1`, `lucy-2.5`, `lucy-vton-3.5`, `lucy-vton-3.6`)
- `VideoRestyleInput` (`lucy-restyle-2`)

## API Reference
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/main/java/ai/decart/sdk/RealtimeModels.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ data class RealtimeModel(

object RealtimeModels {
// Canonical models
val LUCY_2_1 = RealtimeModel("lucy-2.1", "/v1/stream", 30, 1088, 624)
val LUCY_2_1 = RealtimeModel("lucy-2.1", "/v1/stream", 30, 1280, 720)
val LUCY_2_5 = RealtimeModel("lucy-2.5", "/v1/stream", 30, 1280, 720, setOf(Speed.FAST))
val LUCY_VTON_3_5 = RealtimeModel("lucy-vton-3.5", "/v1/stream", 30, 1280, 720, setOf(Speed.FAST))
val LUCY_VTON_3_6 = RealtimeModel("lucy-vton-3.6", "/v1/stream", 30, 1280, 720, setOf(Speed.FAST))
val LUCY_RESTYLE_2 = RealtimeModel("lucy-restyle-2", "/v1/stream", 30, 1280, 704)

// Latest aliases (server-side resolution; lucy-vton-latest -> lucy-vton-3.6)
val LUCY_LATEST = RealtimeModel("lucy-latest", "/v1/stream", 30, 1088, 624, setOf(Speed.FAST))
val LUCY_LATEST = RealtimeModel("lucy-latest", "/v1/stream", 30, 1280, 720, setOf(Speed.FAST))
val LUCY_VTON_LATEST = RealtimeModel("lucy-vton-latest", "/v1/stream", 30, 1280, 720, setOf(Speed.FAST))
val LUCY_RESTYLE_LATEST = RealtimeModel("lucy-restyle-latest", "/v1/stream", 30, 1280, 704)

Expand Down
21 changes: 6 additions & 15 deletions sdk/src/main/java/ai/decart/sdk/VideoModels.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,8 @@ data class VideoModel(
*/
object VideoModels {
// Canonical models
/** Video-to-video clip editing. Output: 1280x704, 25fps. */
val LUCY_CLIP = VideoModel("lucy-clip", "/v1/jobs/lucy-clip", 25, 1280, 704, ModelInputType.VIDEO_EDIT)

/** Lucy 2.1 video editing with optional reference image. Output: 1088x624, 20fps. */
val LUCY_2_1 = VideoModel("lucy-2.1", "/v1/jobs/lucy-2.1", 20, 1088, 624, ModelInputType.VIDEO_EDIT)
/** Lucy 2.1 video editing with optional reference image. Output: 1280x720, 20fps. */
val LUCY_2_1 = VideoModel("lucy-2.1", "/v1/jobs/lucy-2.1", 20, 1280, 720, ModelInputType.VIDEO_EDIT)

/** Lucy 2.5 video editing with optional reference image. Output: 1280x720, 20fps. */
val LUCY_2_5 = VideoModel("lucy-2.5", "/v1/jobs/lucy-2.5", 20, 1280, 720, ModelInputType.VIDEO_EDIT)
Expand All @@ -60,15 +57,11 @@ object VideoModels {
val LUCY_RESTYLE_2 = VideoModel("lucy-restyle-2", "/v1/jobs/lucy-restyle-2", 22, 1280, 704, ModelInputType.VIDEO_RESTYLE)

// Latest aliases (server-side resolution; lucy-vton-latest -> lucy-vton-3.6)
val LUCY_LATEST = VideoModel("lucy-latest", "/v1/jobs/lucy-latest", 20, 1088, 624, ModelInputType.VIDEO_EDIT)
val LUCY_LATEST = VideoModel("lucy-latest", "/v1/jobs/lucy-latest", 20, 1280, 720, ModelInputType.VIDEO_EDIT)
val LUCY_VTON_LATEST = VideoModel("lucy-vton-latest", "/v1/jobs/lucy-vton-latest", 20, 1280, 720, ModelInputType.VIDEO_EDIT)
val LUCY_RESTYLE_LATEST = VideoModel("lucy-restyle-latest", "/v1/jobs/lucy-restyle-latest", 22, 1280, 704, ModelInputType.VIDEO_RESTYLE)
val LUCY_CLIP_LATEST = VideoModel("lucy-clip-latest", "/v1/jobs/lucy-clip-latest", 25, 1280, 704, ModelInputType.VIDEO_EDIT)

// Deprecated models (old names, still work on the API)
@Deprecated("Use LUCY_CLIP instead", replaceWith = ReplaceWith("LUCY_CLIP"))
val LUCY_PRO_V2V = VideoModel("lucy-pro-v2v", "/v1/jobs/lucy-pro-v2v", 25, 1280, 704, ModelInputType.VIDEO_EDIT)

@Deprecated("Use LUCY_RESTYLE_2 instead", replaceWith = ReplaceWith("LUCY_RESTYLE_2"))
val LUCY_RESTYLE_V2V = VideoModel("lucy-restyle-v2v", "/v1/jobs/lucy-restyle-v2v", 22, 1280, 704, ModelInputType.VIDEO_RESTYLE)

Expand All @@ -77,7 +70,6 @@ object VideoModels {

/** All available video models (canonical + latest) */
val all: List<VideoModel> = listOf(
LUCY_CLIP,
LUCY_2_1,
LUCY_2_5,
LUCY_VTON_3_5,
Expand All @@ -86,14 +78,13 @@ object VideoModels {
LUCY_LATEST,
LUCY_VTON_LATEST,
LUCY_RESTYLE_LATEST,
LUCY_CLIP_LATEST,
)

/** All models including deprecated names */
@Suppress("DEPRECATION")
val allIncludingDeprecated: List<VideoModel> = listOf(
LUCY_CLIP, LUCY_2_1, LUCY_2_5, LUCY_VTON_3_5, LUCY_VTON_3_6, LUCY_RESTYLE_2,
LUCY_LATEST, LUCY_VTON_LATEST, LUCY_RESTYLE_LATEST, LUCY_CLIP_LATEST,
LUCY_PRO_V2V, LUCY_RESTYLE_V2V,
LUCY_2_1, LUCY_2_5, LUCY_VTON_3_5, LUCY_VTON_3_6, LUCY_RESTYLE_2,
LUCY_LATEST, LUCY_VTON_LATEST, LUCY_RESTYLE_LATEST,
LUCY_RESTYLE_V2V,
)
}
23 changes: 12 additions & 11 deletions sdk/src/test/java/ai/decart/sdk/RealtimeModelsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,9 @@ class RealtimeModelsTest {


@Test
fun `lucy realtime model dimensions match encoder contract`() {
val expectedWidth = 1088
val expectedHeight = 624

listOf(
RealtimeModels.LUCY_2_1,
RealtimeModels.LUCY_LATEST,
).forEach { model ->
assertEquals("${model.name} width", expectedWidth, model.width)
assertEquals("${model.name} height", expectedHeight, model.height)
}
fun `lucy 2_1 outputs 720p`() {
assertEquals(1280, RealtimeModels.LUCY_2_1.width)
assertEquals(720, RealtimeModels.LUCY_2_1.height)
}

@Test
Expand All @@ -69,6 +61,15 @@ class RealtimeModelsTest {
assertEquals(720, RealtimeModels.LUCY_2_5.height)
}

// lucy-latest resolves server-side to lucy-2.5, so it shares its 720p geometry.
@Test
fun `lucy latest matches lucy 2_5 geometry`() {
assertEquals(1280, RealtimeModels.LUCY_LATEST.width)
assertEquals(720, RealtimeModels.LUCY_LATEST.height)
assertEquals(RealtimeModels.LUCY_2_5.width, RealtimeModels.LUCY_LATEST.width)
assertEquals(RealtimeModels.LUCY_2_5.height, RealtimeModels.LUCY_LATEST.height)
}

@Test
fun `lucy vton 3_5 outputs 720p`() {
assertEquals(1280, RealtimeModels.LUCY_VTON_3_5.width)
Expand Down
19 changes: 16 additions & 3 deletions sdk/src/test/java/ai/decart/sdk/VideoModelsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import org.junit.Test
class VideoModelsTest {
@Test
fun `video models match JS SDK registry`() {
assertEquals(10, VideoModels.all.size)
assertEquals(8, VideoModels.all.size)
assertEquals(VideoModels.LUCY_2_1, VideoModels.fromName("lucy-2.1"))
assertEquals(20, VideoModels.LUCY_2_1.fps)
assertEquals(1088, VideoModels.LUCY_2_1.width)
assertEquals(624, VideoModels.LUCY_2_1.height)
assertEquals(1280, VideoModels.LUCY_2_1.width)
assertEquals(720, VideoModels.LUCY_2_1.height)
assertEquals(ModelInputType.VIDEO_EDIT, VideoModels.LUCY_2_1.inputType)
}

Expand All @@ -24,6 +24,19 @@ class VideoModelsTest {
assertEquals(ModelInputType.VIDEO_EDIT, VideoModels.LUCY_2_5.inputType)
}

// lucy-latest resolves server-side to lucy-2.5, so it shares its 720p geometry.
@Test
fun `lucy-latest matches JS SDK registry`() {
assertEquals(VideoModels.LUCY_LATEST, VideoModels.fromName("lucy-latest"))
assertEquals("/v1/jobs/lucy-latest", VideoModels.LUCY_LATEST.jobsUrlPath)
assertEquals(20, VideoModels.LUCY_LATEST.fps)
assertEquals(1280, VideoModels.LUCY_LATEST.width)
assertEquals(720, VideoModels.LUCY_LATEST.height)
assertEquals(ModelInputType.VIDEO_EDIT, VideoModels.LUCY_LATEST.inputType)
assertEquals(VideoModels.LUCY_2_5.width, VideoModels.LUCY_LATEST.width)
assertEquals(VideoModels.LUCY_2_5.height, VideoModels.LUCY_LATEST.height)
}

@Test
fun `lucy-vton-3_5 matches JS SDK registry`() {
assertEquals(VideoModels.LUCY_VTON_3_5, VideoModels.fromName("lucy-vton-3.5"))
Expand Down