diff --git a/README.md b/README.md index 68fa14d..4bbed1e 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 | @@ -323,8 +323,7 @@ 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 | @@ -332,7 +331,7 @@ client.queue.submit(VideoModels.LUCY_RESTYLE_2, restyle) 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 diff --git a/sdk/src/main/java/ai/decart/sdk/RealtimeModels.kt b/sdk/src/main/java/ai/decart/sdk/RealtimeModels.kt index db22199..899b564 100644 --- a/sdk/src/main/java/ai/decart/sdk/RealtimeModels.kt +++ b/sdk/src/main/java/ai/decart/sdk/RealtimeModels.kt @@ -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) diff --git a/sdk/src/main/java/ai/decart/sdk/VideoModels.kt b/sdk/src/main/java/ai/decart/sdk/VideoModels.kt index 1df5e7e..ee355f4 100644 --- a/sdk/src/main/java/ai/decart/sdk/VideoModels.kt +++ b/sdk/src/main/java/ai/decart/sdk/VideoModels.kt @@ -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) @@ -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) @@ -77,7 +70,6 @@ object VideoModels { /** All available video models (canonical + latest) */ val all: List = listOf( - LUCY_CLIP, LUCY_2_1, LUCY_2_5, LUCY_VTON_3_5, @@ -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 = 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, ) } diff --git a/sdk/src/test/java/ai/decart/sdk/RealtimeModelsTest.kt b/sdk/src/test/java/ai/decart/sdk/RealtimeModelsTest.kt index 904f8a8..b73c58e 100644 --- a/sdk/src/test/java/ai/decart/sdk/RealtimeModelsTest.kt +++ b/sdk/src/test/java/ai/decart/sdk/RealtimeModelsTest.kt @@ -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 @@ -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) diff --git a/sdk/src/test/java/ai/decart/sdk/VideoModelsTest.kt b/sdk/src/test/java/ai/decart/sdk/VideoModelsTest.kt index 69aa33e..10ad5ec 100644 --- a/sdk/src/test/java/ai/decart/sdk/VideoModelsTest.kt +++ b/sdk/src/test/java/ai/decart/sdk/VideoModelsTest.kt @@ -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) } @@ -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"))