venice-video-harness 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +598 -0
  4. package/dist/assembly/manifest-builder.d.ts +8 -0
  5. package/dist/assembly/manifest-builder.d.ts.map +1 -0
  6. package/dist/assembly/manifest-builder.js +196 -0
  7. package/dist/assembly/manifest-builder.js.map +1 -0
  8. package/dist/assembly/remotion-scaffold.d.ts +14 -0
  9. package/dist/assembly/remotion-scaffold.d.ts.map +1 -0
  10. package/dist/assembly/remotion-scaffold.js +292 -0
  11. package/dist/assembly/remotion-scaffold.js.map +1 -0
  12. package/dist/assembly/types.d.ts +67 -0
  13. package/dist/assembly/types.d.ts.map +1 -0
  14. package/dist/assembly/types.js +5 -0
  15. package/dist/assembly/types.js.map +1 -0
  16. package/dist/characters/describer.d.ts +32 -0
  17. package/dist/characters/describer.d.ts.map +1 -0
  18. package/dist/characters/describer.js +309 -0
  19. package/dist/characters/describer.js.map +1 -0
  20. package/dist/characters/extractor.d.ts +27 -0
  21. package/dist/characters/extractor.d.ts.map +1 -0
  22. package/dist/characters/extractor.js +274 -0
  23. package/dist/characters/extractor.js.map +1 -0
  24. package/dist/characters/reference-manager.d.ts +95 -0
  25. package/dist/characters/reference-manager.d.ts.map +1 -0
  26. package/dist/characters/reference-manager.js +346 -0
  27. package/dist/characters/reference-manager.js.map +1 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +310 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/config.d.ts +22 -0
  33. package/dist/config.d.ts.map +1 -0
  34. package/dist/config.js +66 -0
  35. package/dist/config.js.map +1 -0
  36. package/dist/editing/aligner.d.ts +44 -0
  37. package/dist/editing/aligner.d.ts.map +1 -0
  38. package/dist/editing/aligner.js +201 -0
  39. package/dist/editing/aligner.js.map +1 -0
  40. package/dist/editing/edl.d.ts +45 -0
  41. package/dist/editing/edl.d.ts.map +1 -0
  42. package/dist/editing/edl.js +133 -0
  43. package/dist/editing/edl.js.map +1 -0
  44. package/dist/editing/overlays.d.ts +97 -0
  45. package/dist/editing/overlays.d.ts.map +1 -0
  46. package/dist/editing/overlays.js +41 -0
  47. package/dist/editing/overlays.js.map +1 -0
  48. package/dist/editing/packer.d.ts +52 -0
  49. package/dist/editing/packer.d.ts.map +1 -0
  50. package/dist/editing/packer.js +170 -0
  51. package/dist/editing/packer.js.map +1 -0
  52. package/dist/editing/providers/whisper-cpp.d.ts +32 -0
  53. package/dist/editing/providers/whisper-cpp.d.ts.map +1 -0
  54. package/dist/editing/providers/whisper-cpp.js +239 -0
  55. package/dist/editing/providers/whisper-cpp.js.map +1 -0
  56. package/dist/editing/render.d.ts +36 -0
  57. package/dist/editing/render.d.ts.map +1 -0
  58. package/dist/editing/render.js +227 -0
  59. package/dist/editing/render.js.map +1 -0
  60. package/dist/editing/self-eval.d.ts +48 -0
  61. package/dist/editing/self-eval.d.ts.map +1 -0
  62. package/dist/editing/self-eval.js +293 -0
  63. package/dist/editing/self-eval.js.map +1 -0
  64. package/dist/editing/silence.d.ts +76 -0
  65. package/dist/editing/silence.d.ts.map +1 -0
  66. package/dist/editing/silence.js +189 -0
  67. package/dist/editing/silence.js.map +1 -0
  68. package/dist/editing/types.d.ts +178 -0
  69. package/dist/editing/types.d.ts.map +1 -0
  70. package/dist/editing/types.js +13 -0
  71. package/dist/editing/types.js.map +1 -0
  72. package/dist/index.d.ts +6 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +5 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/interactive.d.ts +12 -0
  77. package/dist/interactive.d.ts.map +1 -0
  78. package/dist/interactive.js +78 -0
  79. package/dist/interactive.js.map +1 -0
  80. package/dist/mini-drama/assembler.d.ts +61 -0
  81. package/dist/mini-drama/assembler.d.ts.map +1 -0
  82. package/dist/mini-drama/assembler.js +466 -0
  83. package/dist/mini-drama/assembler.js.map +1 -0
  84. package/dist/mini-drama/audio-mix.d.ts +65 -0
  85. package/dist/mini-drama/audio-mix.d.ts.map +1 -0
  86. package/dist/mini-drama/audio-mix.js +118 -0
  87. package/dist/mini-drama/audio-mix.js.map +1 -0
  88. package/dist/mini-drama/cli.d.ts +3 -0
  89. package/dist/mini-drama/cli.d.ts.map +1 -0
  90. package/dist/mini-drama/cli.js +2869 -0
  91. package/dist/mini-drama/cli.js.map +1 -0
  92. package/dist/mini-drama/fcpxml-export.d.ts +2 -0
  93. package/dist/mini-drama/fcpxml-export.d.ts.map +1 -0
  94. package/dist/mini-drama/fcpxml-export.js +5 -0
  95. package/dist/mini-drama/fcpxml-export.js.map +1 -0
  96. package/dist/mini-drama/generation-planner.d.ts +24 -0
  97. package/dist/mini-drama/generation-planner.d.ts.map +1 -0
  98. package/dist/mini-drama/generation-planner.js +304 -0
  99. package/dist/mini-drama/generation-planner.js.map +1 -0
  100. package/dist/mini-drama/location-generator.d.ts +23 -0
  101. package/dist/mini-drama/location-generator.d.ts.map +1 -0
  102. package/dist/mini-drama/location-generator.js +144 -0
  103. package/dist/mini-drama/location-generator.js.map +1 -0
  104. package/dist/mini-drama/music-cues.d.ts +96 -0
  105. package/dist/mini-drama/music-cues.d.ts.map +1 -0
  106. package/dist/mini-drama/music-cues.js +332 -0
  107. package/dist/mini-drama/music-cues.js.map +1 -0
  108. package/dist/mini-drama/panel-fixer.d.ts +12 -0
  109. package/dist/mini-drama/panel-fixer.d.ts.map +1 -0
  110. package/dist/mini-drama/panel-fixer.js +319 -0
  111. package/dist/mini-drama/panel-fixer.js.map +1 -0
  112. package/dist/mini-drama/prompt-builder.d.ts +149 -0
  113. package/dist/mini-drama/prompt-builder.d.ts.map +1 -0
  114. package/dist/mini-drama/prompt-builder.js +722 -0
  115. package/dist/mini-drama/prompt-builder.js.map +1 -0
  116. package/dist/mini-drama/reference-slots.d.ts +31 -0
  117. package/dist/mini-drama/reference-slots.d.ts.map +1 -0
  118. package/dist/mini-drama/reference-slots.js +161 -0
  119. package/dist/mini-drama/reference-slots.js.map +1 -0
  120. package/dist/mini-drama/shot-paths.d.ts +77 -0
  121. package/dist/mini-drama/shot-paths.d.ts.map +1 -0
  122. package/dist/mini-drama/shot-paths.js +101 -0
  123. package/dist/mini-drama/shot-paths.js.map +1 -0
  124. package/dist/mini-drama/storyboard-reference-generator.d.ts +47 -0
  125. package/dist/mini-drama/storyboard-reference-generator.d.ts.map +1 -0
  126. package/dist/mini-drama/storyboard-reference-generator.js +293 -0
  127. package/dist/mini-drama/storyboard-reference-generator.js.map +1 -0
  128. package/dist/mini-drama/subtitle-generator.d.ts +12 -0
  129. package/dist/mini-drama/subtitle-generator.d.ts.map +1 -0
  130. package/dist/mini-drama/subtitle-generator.js +139 -0
  131. package/dist/mini-drama/subtitle-generator.js.map +1 -0
  132. package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts +3 -0
  133. package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts.map +1 -0
  134. package/dist/mini-drama/timeline-export/davinci-fcpxml.js +150 -0
  135. package/dist/mini-drama/timeline-export/davinci-fcpxml.js.map +1 -0
  136. package/dist/mini-drama/timeline-export/fcpxml.d.ts +11 -0
  137. package/dist/mini-drama/timeline-export/fcpxml.d.ts.map +1 -0
  138. package/dist/mini-drama/timeline-export/fcpxml.js +140 -0
  139. package/dist/mini-drama/timeline-export/fcpxml.js.map +1 -0
  140. package/dist/mini-drama/timeline-export/index.d.ts +13 -0
  141. package/dist/mini-drama/timeline-export/index.d.ts.map +1 -0
  142. package/dist/mini-drama/timeline-export/index.js +26 -0
  143. package/dist/mini-drama/timeline-export/index.js.map +1 -0
  144. package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts +3 -0
  145. package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts.map +1 -0
  146. package/dist/mini-drama/timeline-export/premiere-xmeml.js +211 -0
  147. package/dist/mini-drama/timeline-export/premiere-xmeml.js.map +1 -0
  148. package/dist/mini-drama/timeline-export/probe.d.ts +53 -0
  149. package/dist/mini-drama/timeline-export/probe.d.ts.map +1 -0
  150. package/dist/mini-drama/timeline-export/probe.js +89 -0
  151. package/dist/mini-drama/timeline-export/probe.js.map +1 -0
  152. package/dist/mini-drama/timeline-export/types.d.ts +57 -0
  153. package/dist/mini-drama/timeline-export/types.d.ts.map +1 -0
  154. package/dist/mini-drama/timeline-export/types.js +14 -0
  155. package/dist/mini-drama/timeline-export/types.js.map +1 -0
  156. package/dist/mini-drama/video-generator.d.ts +22 -0
  157. package/dist/mini-drama/video-generator.d.ts.map +1 -0
  158. package/dist/mini-drama/video-generator.js +1305 -0
  159. package/dist/mini-drama/video-generator.js.map +1 -0
  160. package/dist/mini-drama/voice-reference.d.ts +42 -0
  161. package/dist/mini-drama/voice-reference.d.ts.map +1 -0
  162. package/dist/mini-drama/voice-reference.js +170 -0
  163. package/dist/mini-drama/voice-reference.js.map +1 -0
  164. package/dist/output/html-renderer.d.ts +2 -0
  165. package/dist/output/html-renderer.d.ts.map +1 -0
  166. package/dist/output/html-renderer.js +37 -0
  167. package/dist/output/html-renderer.js.map +1 -0
  168. package/dist/parsers/fountain-parser.d.ts +34 -0
  169. package/dist/parsers/fountain-parser.d.ts.map +1 -0
  170. package/dist/parsers/fountain-parser.js +71 -0
  171. package/dist/parsers/fountain-parser.js.map +1 -0
  172. package/dist/parsers/pdf-parser.d.ts +24 -0
  173. package/dist/parsers/pdf-parser.d.ts.map +1 -0
  174. package/dist/parsers/pdf-parser.js +237 -0
  175. package/dist/parsers/pdf-parser.js.map +1 -0
  176. package/dist/parsers/scene-extractor.d.ts +41 -0
  177. package/dist/parsers/scene-extractor.d.ts.map +1 -0
  178. package/dist/parsers/scene-extractor.js +400 -0
  179. package/dist/parsers/scene-extractor.js.map +1 -0
  180. package/dist/series/manager.d.ts +64 -0
  181. package/dist/series/manager.d.ts.map +1 -0
  182. package/dist/series/manager.js +282 -0
  183. package/dist/series/manager.js.map +1 -0
  184. package/dist/series/types.d.ts +641 -0
  185. package/dist/series/types.d.ts.map +1 -0
  186. package/dist/series/types.js +304 -0
  187. package/dist/series/types.js.map +1 -0
  188. package/dist/storyboard/assembler.d.ts +134 -0
  189. package/dist/storyboard/assembler.d.ts.map +1 -0
  190. package/dist/storyboard/assembler.js +319 -0
  191. package/dist/storyboard/assembler.js.map +1 -0
  192. package/dist/storyboard/prompt-builder.d.ts +113 -0
  193. package/dist/storyboard/prompt-builder.d.ts.map +1 -0
  194. package/dist/storyboard/prompt-builder.js +578 -0
  195. package/dist/storyboard/prompt-builder.js.map +1 -0
  196. package/dist/storyboard/shot-planner.d.ts +34 -0
  197. package/dist/storyboard/shot-planner.d.ts.map +1 -0
  198. package/dist/storyboard/shot-planner.js +446 -0
  199. package/dist/storyboard/shot-planner.js.map +1 -0
  200. package/dist/user-config.d.ts +15 -0
  201. package/dist/user-config.d.ts.map +1 -0
  202. package/dist/user-config.js +103 -0
  203. package/dist/user-config.js.map +1 -0
  204. package/dist/venice/audio-preflight.d.ts +80 -0
  205. package/dist/venice/audio-preflight.d.ts.map +1 -0
  206. package/dist/venice/audio-preflight.js +142 -0
  207. package/dist/venice/audio-preflight.js.map +1 -0
  208. package/dist/venice/audio.d.ts +88 -0
  209. package/dist/venice/audio.d.ts.map +1 -0
  210. package/dist/venice/audio.js +234 -0
  211. package/dist/venice/audio.js.map +1 -0
  212. package/dist/venice/client.d.ts +86 -0
  213. package/dist/venice/client.d.ts.map +1 -0
  214. package/dist/venice/client.js +375 -0
  215. package/dist/venice/client.js.map +1 -0
  216. package/dist/venice/edit.d.ts +57 -0
  217. package/dist/venice/edit.d.ts.map +1 -0
  218. package/dist/venice/edit.js +100 -0
  219. package/dist/venice/edit.js.map +1 -0
  220. package/dist/venice/generate.d.ts +47 -0
  221. package/dist/venice/generate.d.ts.map +1 -0
  222. package/dist/venice/generate.js +150 -0
  223. package/dist/venice/generate.js.map +1 -0
  224. package/dist/venice/image-bytes.d.ts +26 -0
  225. package/dist/venice/image-bytes.d.ts.map +1 -0
  226. package/dist/venice/image-bytes.js +101 -0
  227. package/dist/venice/image-bytes.js.map +1 -0
  228. package/dist/venice/models.d.ts +143 -0
  229. package/dist/venice/models.d.ts.map +1 -0
  230. package/dist/venice/models.js +984 -0
  231. package/dist/venice/models.js.map +1 -0
  232. package/dist/venice/multi-edit.d.ts +40 -0
  233. package/dist/venice/multi-edit.d.ts.map +1 -0
  234. package/dist/venice/multi-edit.js +97 -0
  235. package/dist/venice/multi-edit.js.map +1 -0
  236. package/dist/venice/provenance.d.ts +66 -0
  237. package/dist/venice/provenance.d.ts.map +1 -0
  238. package/dist/venice/provenance.js +151 -0
  239. package/dist/venice/provenance.js.map +1 -0
  240. package/dist/venice/recipe.d.ts +69 -0
  241. package/dist/venice/recipe.d.ts.map +1 -0
  242. package/dist/venice/recipe.js +103 -0
  243. package/dist/venice/recipe.js.map +1 -0
  244. package/dist/venice/rejection.d.ts +63 -0
  245. package/dist/venice/rejection.d.ts.map +1 -0
  246. package/dist/venice/rejection.js +111 -0
  247. package/dist/venice/rejection.js.map +1 -0
  248. package/dist/venice/seedance-preflight.d.ts +38 -0
  249. package/dist/venice/seedance-preflight.d.ts.map +1 -0
  250. package/dist/venice/seedance-preflight.js +29 -0
  251. package/dist/venice/seedance-preflight.js.map +1 -0
  252. package/dist/venice/types.d.ts +212 -0
  253. package/dist/venice/types.d.ts.map +1 -0
  254. package/dist/venice/types.js +9 -0
  255. package/dist/venice/types.js.map +1 -0
  256. package/dist/venice/video.d.ts +77 -0
  257. package/dist/venice/video.d.ts.map +1 -0
  258. package/dist/venice/video.js +163 -0
  259. package/dist/venice/video.js.map +1 -0
  260. package/dist/venice/voices.d.ts +40 -0
  261. package/dist/venice/voices.d.ts.map +1 -0
  262. package/dist/venice/voices.js +194 -0
  263. package/dist/venice/voices.js.map +1 -0
  264. package/package.json +79 -0
@@ -0,0 +1,984 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Venice AI Model Registry
3
+ //
4
+ // Canonical source for all available Venice models, their capabilities,
5
+ // and constraints. Updated from the live /api/v1/models endpoint.
6
+ // Last synced: 2026-03-18
7
+ // ---------------------------------------------------------------------------
8
+ // ---- Image generation prompt-length budgets () -----------------------
9
+ /**
10
+ * Per-image-model positive-prompt length caps.
11
+ *
12
+ * Venice silently rejects requests with overly long positive prompts on
13
+ * certain models (observed at ~1800-2200 chars on seedream-v5-lite; the
14
+ * mini-drama character-reference builder used to emit 2400+ char prompts).
15
+ *
16
+ * Default cap is intentionally conservative (300 chars). Callers should
17
+ * keep the most-important style cue + character anchor inline and move
18
+ * everything else to negative_prompt.
19
+ */
20
+ export const DEFAULT_MAX_POSITIVE_PROMPT_CHARS = 300;
21
+ export const MAX_POSITIVE_PROMPT_CHARS = {
22
+ 'seedream-v5-lite': 300,
23
+ 'seedream-v5-lite-edit': 300,
24
+ 'nano-banana-pro': 500,
25
+ 'nano-banana-pro-edit': 500,
26
+ 'gpt-image-2': 600,
27
+ 'gpt-image-2-edit': 600,
28
+ };
29
+ /**
30
+ * Look up the positive-prompt cap for an image-generation model.
31
+ * Falls back to DEFAULT_MAX_POSITIVE_PROMPT_CHARS when unspecified.
32
+ */
33
+ export function getMaxPositivePromptChars(modelId) {
34
+ return MAX_POSITIVE_PROMPT_CHARS[modelId] ?? DEFAULT_MAX_POSITIVE_PROMPT_CHARS;
35
+ }
36
+ export const VIDEO_MODELS = [
37
+ // -- Wan 2.6 --
38
+ {
39
+ id: 'wan-2.6-image-to-video', name: 'Wan 2.6', type: 'image-to-video',
40
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: [],
41
+ audio: true, audioConfigurable: true, audioInput: true, videoInput: false,
42
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
43
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
44
+ },
45
+ {
46
+ id: 'wan-2.6-flash-image-to-video', name: 'Wan 2.6 Flash', type: 'image-to-video',
47
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: [],
48
+ audio: true, audioConfigurable: false, audioInput: true, videoInput: false,
49
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
50
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
51
+ },
52
+ {
53
+ id: 'wan-2.6-text-to-video', name: 'Wan 2.6', type: 'text-to-video',
54
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
55
+ audio: true, audioConfigurable: true, audioInput: true, videoInput: false,
56
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
57
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
58
+ },
59
+ // -- Wan 2.7 (lip-sync via audio_url / per-reference audio) --
60
+ // Live API probed 2026-05-10. Notes:
61
+ // - audio_url minimum duration is 3 seconds (returns HTTP 400 below).
62
+ // - i2v inherits aspect ratio from the input image; passing aspect_ratio
63
+ // yields "This model does not support aspect_ratio" — empty array.
64
+ // - t2v supports aspect_ratio.
65
+ // - R2V uses `per_reference_audio` via elements[].audio_url, not audio_url.
66
+ // - end_image_url is NOT supported: live 2026-07-06 the i2v (incl. Spicy)
67
+ // queue returned HTTP 400 "This model does not support end_image_url".
68
+ // - Cost reference: ~$0.55 per 5s clip at 720p.
69
+ {
70
+ id: 'wan-2-7-image-to-video', name: 'Wan 2.7', type: 'image-to-video',
71
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: [],
72
+ audio: false, audioConfigurable: false, audioInput: true, videoInput: false,
73
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
74
+ maxDurationSec: 15, minAudioInputSec: 3,
75
+ privacy: 'anonymized', offline: false,
76
+ },
77
+ {
78
+ id: 'wan-2-7-text-to-video', name: 'Wan 2.7', type: 'text-to-video',
79
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
80
+ audio: false, audioConfigurable: false, audioInput: true, videoInput: false,
81
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
82
+ maxDurationSec: 15, minAudioInputSec: 3,
83
+ privacy: 'anonymized', offline: false,
84
+ },
85
+ {
86
+ id: 'wan-2-7-reference-to-video', name: 'Wan 2.7 R2V', type: 'image-to-video',
87
+ durations: ['5s', '10s'], resolutions: ['1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
88
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
89
+ supportsElements: true, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
90
+ maxDurationSec: 10, perReferenceAudio: true, minAudioInputSec: 3,
91
+ privacy: 'anonymized', offline: false,
92
+ },
93
+ {
94
+ id: 'wan-2-7-video-to-video', name: 'Wan 2.7 V2V', type: 'image-to-video',
95
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: [],
96
+ audio: false, audioConfigurable: false, audioInput: true, videoInput: true,
97
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
98
+ maxDurationSec: 15, minAudioInputSec: 3,
99
+ privacy: 'anonymized', offline: false,
100
+ },
101
+ // -- Wan 2.5 Preview --
102
+ {
103
+ id: 'wan-2.5-preview-image-to-video', name: 'Wan 2.5 Preview', type: 'image-to-video',
104
+ durations: ['5s', '10s'], resolutions: ['1080p', '720p', '480p'], aspectRatios: [],
105
+ audio: true, audioConfigurable: false, audioInput: true, videoInput: false,
106
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
107
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
108
+ },
109
+ {
110
+ id: 'wan-2.5-preview-text-to-video', name: 'Wan 2.5 Preview', type: 'text-to-video',
111
+ durations: ['5s', '10s'], resolutions: ['1080p', '720p', '480p'], aspectRatios: ['16:9', '9:16', '1:1'],
112
+ audio: true, audioConfigurable: false, audioInput: true, videoInput: false,
113
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
114
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
115
+ },
116
+ // -- Wan 2.2 / 2.1 (legacy) --
117
+ {
118
+ id: 'wan-2.2-a14b-text-to-video', name: 'Wan 2.2 A14B', type: 'text-to-video',
119
+ durations: ['5s'], resolutions: ['720p', '580p', '480p'], aspectRatios: ['16:9', '9:16', '1:1'],
120
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
121
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
122
+ maxDurationSec: 5, privacy: 'private', offline: false,
123
+ },
124
+ {
125
+ id: 'wan-2.1-pro-image-to-video', name: 'Wan 2.1 Pro', type: 'image-to-video',
126
+ durations: ['6s'], resolutions: [], aspectRatios: ['16:9'],
127
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
128
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
129
+ maxDurationSec: 6, privacy: 'private', offline: false,
130
+ },
131
+ // -- Grok Imagine --
132
+ {
133
+ id: 'grok-imagine-text-to-video', name: 'Grok Imagine', type: 'text-to-video',
134
+ durations: ['5s', '10s', '15s'], resolutions: ['480p', '720p'], aspectRatios: ['16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'],
135
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
136
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
137
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
138
+ },
139
+ {
140
+ id: 'grok-imagine-image-to-video', name: 'Grok Imagine', type: 'image-to-video',
141
+ durations: ['5s', '10s', '15s'], resolutions: ['480p', '720p'], aspectRatios: [],
142
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
143
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
144
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
145
+ },
146
+ // -- LTX Video 2.0 --
147
+ {
148
+ id: 'ltx-2-fast-image-to-video', name: 'LTX Video 2.0 Fast', type: 'image-to-video',
149
+ durations: ['6s', '8s', '10s', '12s', '14s', '16s', '18s', '20s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9'],
150
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
151
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
152
+ maxDurationSec: 20, privacy: 'anonymized', offline: false,
153
+ },
154
+ {
155
+ id: 'ltx-2-fast-text-to-video', name: 'LTX Video 2.0 Fast', type: 'text-to-video',
156
+ durations: ['6s', '8s', '10s', '12s', '14s', '16s', '18s', '20s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9'],
157
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
158
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
159
+ maxDurationSec: 20, privacy: 'anonymized', offline: false,
160
+ },
161
+ {
162
+ id: 'ltx-2-full-image-to-video', name: 'LTX Video 2.0 Full', type: 'image-to-video',
163
+ durations: ['6s', '8s', '10s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9'],
164
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
165
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
166
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
167
+ },
168
+ {
169
+ id: 'ltx-2-full-text-to-video', name: 'LTX Video 2.0 Full', type: 'text-to-video',
170
+ durations: ['6s', '8s', '10s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9'],
171
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
172
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
173
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
174
+ },
175
+ // -- LTX Video 2.0 v2.3 --
176
+ {
177
+ id: 'ltx-2-v2-3-fast-image-to-video', name: 'LTX Video 2.0 v2.3 Fast', type: 'image-to-video',
178
+ durations: ['6s', '8s', '10s', '12s', '14s', '16s', '18s', '20s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9', '9:16'],
179
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
180
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
181
+ maxDurationSec: 20, privacy: 'anonymized', offline: false,
182
+ },
183
+ {
184
+ id: 'ltx-2-v2-3-fast-text-to-video', name: 'LTX Video 2.0 v2.3 Fast', type: 'text-to-video',
185
+ durations: ['6s', '8s', '10s', '12s', '14s', '16s', '18s', '20s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9', '9:16'],
186
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
187
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
188
+ maxDurationSec: 20, privacy: 'anonymized', offline: false,
189
+ },
190
+ {
191
+ id: 'ltx-2-v2-3-full-image-to-video', name: 'LTX Video 2.0 v2.3 Full', type: 'image-to-video',
192
+ durations: ['6s', '8s', '10s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9', '9:16'],
193
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
194
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
195
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
196
+ },
197
+ {
198
+ id: 'ltx-2-v2-3-full-text-to-video', name: 'LTX Video 2.0 v2.3 Full', type: 'text-to-video',
199
+ durations: ['6s', '8s', '10s'], resolutions: ['1080p', '1440p', '2160p'], aspectRatios: ['16:9', '9:16'],
200
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
201
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
202
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
203
+ },
204
+ // -- LTX Video 2.0 19B --
205
+ {
206
+ id: 'ltx-2-19b-full-text-to-video', name: 'LTX Video 2.0 19B Full', type: 'text-to-video',
207
+ durations: ['5s', '8s', '10s', '15s', '18s'], resolutions: ['720p'], aspectRatios: ['16:9', '4:3', '1:1', '3:4', '9:16'],
208
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
209
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
210
+ maxDurationSec: 18, privacy: 'anonymized', offline: false,
211
+ },
212
+ {
213
+ id: 'ltx-2-19b-full-image-to-video', name: 'LTX Video 2.0 19B Full', type: 'image-to-video',
214
+ durations: ['5s', '8s', '10s', '15s', '18s'], resolutions: ['720p'], aspectRatios: ['16:9', '4:3', '1:1', '3:4', '9:16'],
215
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
216
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
217
+ maxDurationSec: 18, privacy: 'anonymized', offline: false,
218
+ },
219
+ {
220
+ id: 'ltx-2-19b-distilled-text-to-video', name: 'LTX Video 2.0 19B Distilled', type: 'text-to-video',
221
+ durations: ['5s', '8s', '10s', '15s', '18s'], resolutions: ['720p'], aspectRatios: ['16:9', '4:3', '1:1', '3:4', '9:16'],
222
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
223
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
224
+ maxDurationSec: 18, privacy: 'anonymized', offline: false,
225
+ },
226
+ {
227
+ id: 'ltx-2-19b-distilled-image-to-video', name: 'LTX Video 2.0 19B Distilled', type: 'image-to-video',
228
+ durations: ['5s', '8s', '10s', '15s', '18s'], resolutions: ['720p'], aspectRatios: ['16:9', '4:3', '1:1', '3:4', '9:16'],
229
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
230
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
231
+ maxDurationSec: 18, privacy: 'anonymized', offline: false,
232
+ },
233
+ // -- OVI --
234
+ {
235
+ id: 'ovi-image-to-video', name: 'OVI', type: 'image-to-video',
236
+ durations: ['5s'], resolutions: [], aspectRatios: [],
237
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
238
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
239
+ maxDurationSec: 5, privacy: 'anonymized', offline: false,
240
+ },
241
+ // -- Kling 2.6 --
242
+ {
243
+ id: 'kling-2.6-pro-text-to-video', name: 'Kling 2.6 Pro', type: 'text-to-video',
244
+ durations: ['5s', '10s'], resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
245
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
246
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
247
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
248
+ },
249
+ {
250
+ id: 'kling-2.6-pro-image-to-video', name: 'Kling 2.6 Pro', type: 'image-to-video',
251
+ durations: ['5s', '10s'], resolutions: [], aspectRatios: [],
252
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
253
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
254
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
255
+ },
256
+ // -- Kling 2.5 Turbo Pro --
257
+ {
258
+ id: 'kling-2.5-turbo-pro-text-to-video', name: 'Kling 2.5 Turbo Pro', type: 'text-to-video',
259
+ durations: ['5s', '10s'], resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
260
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
261
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
262
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
263
+ },
264
+ {
265
+ id: 'kling-2.5-turbo-pro-image-to-video', name: 'Kling 2.5 Turbo Pro', type: 'image-to-video',
266
+ durations: ['5s', '10s'], resolutions: [], aspectRatios: [],
267
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
268
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
269
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
270
+ },
271
+ // -- Kling O3 --
272
+ {
273
+ id: 'kling-o3-pro-text-to-video', name: 'Kling O3 Pro', type: 'text-to-video',
274
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
275
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
276
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
277
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
278
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
279
+ },
280
+ {
281
+ id: 'kling-o3-pro-image-to-video', name: 'Kling O3 Pro', type: 'image-to-video',
282
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
283
+ resolutions: [], aspectRatios: [],
284
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
285
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
286
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
287
+ },
288
+ {
289
+ id: 'kling-o3-pro-reference-to-video', name: 'Kling O3 Pro R2V', type: 'image-to-video',
290
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
291
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
292
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
293
+ supportsElements: true, supportsReferenceImages: true, supportsSceneImages: true, supportsEndImage: true,
294
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
295
+ },
296
+ {
297
+ id: 'kling-o3-standard-text-to-video', name: 'Kling O3 Standard', type: 'text-to-video',
298
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
299
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
300
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
301
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
302
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
303
+ },
304
+ {
305
+ id: 'kling-o3-standard-image-to-video', name: 'Kling O3 Standard', type: 'image-to-video',
306
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
307
+ resolutions: [], aspectRatios: [],
308
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
309
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
310
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
311
+ },
312
+ {
313
+ id: 'kling-o3-standard-reference-to-video', name: 'Kling O3 Standard R2V', type: 'image-to-video',
314
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
315
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
316
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
317
+ supportsElements: true, supportsReferenceImages: true, supportsSceneImages: true, supportsEndImage: true,
318
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
319
+ },
320
+ // -- Kling O3 4K (not in registry sync 2026-03-18 — added by hand) --
321
+ {
322
+ id: 'kling-o3-4k-text-to-video', name: 'Kling O3 4K', type: 'text-to-video',
323
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
324
+ resolutions: ['4K', '1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
325
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
326
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
327
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
328
+ },
329
+ {
330
+ id: 'kling-o3-4k-image-to-video', name: 'Kling O3 4K', type: 'image-to-video',
331
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
332
+ resolutions: ['4K', '1080p', '720p'], aspectRatios: [],
333
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
334
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
335
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
336
+ },
337
+ {
338
+ id: 'kling-o3-4k-reference-to-video', name: 'Kling O3 4K R2V', type: 'image-to-video',
339
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
340
+ resolutions: ['4K', '1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
341
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
342
+ supportsElements: true, supportsReferenceImages: true, supportsSceneImages: true, supportsEndImage: true,
343
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
344
+ },
345
+ // -- HappyHorse 1.0 (not in registry sync 2026-03-18 — added by hand) --
346
+ {
347
+ id: 'happyhorse-1-0-text-to-video', name: 'HappyHorse 1.0', type: 'text-to-video',
348
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
349
+ resolutions: ['1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
350
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
351
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
352
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
353
+ },
354
+ {
355
+ id: 'happyhorse-1-0-image-to-video', name: 'HappyHorse 1.0', type: 'image-to-video',
356
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
357
+ resolutions: ['1080p', '720p'], aspectRatios: [],
358
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
359
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
360
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
361
+ },
362
+ {
363
+ id: 'happyhorse-1-0-reference-to-video', name: 'HappyHorse 1.0 R2V', type: 'image-to-video',
364
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
365
+ resolutions: ['1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4'],
366
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
367
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
368
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
369
+ },
370
+ // -- HappyHorse 1.1 (live registry sync 2026-07-06) --
371
+ // Alibaba's 15B model, #1 on the Artificial Analysis Video Arena (T2V + I2V)
372
+ // by blind human preference. Joint single-pass video+audio with phoneme-level
373
+ // lip-sync across 7 languages (EN, Mandarin, Cantonese, JA, KO, DE, FR).
374
+ // 1.1 adds reference-to-video with up to 9 reference images and widens the
375
+ // aspect-ratio menu to nine ratios. Draft on 720p, finalize keepers on 1080p.
376
+ {
377
+ id: 'happyhorse-1-1-text-to-video', name: 'HappyHorse 1.1', type: 'text-to-video',
378
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
379
+ resolutions: ['1080p', '720p'],
380
+ aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9', '9:21', '5:4', '4:5'],
381
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
382
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
383
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
384
+ },
385
+ {
386
+ id: 'happyhorse-1-1-image-to-video', name: 'HappyHorse 1.1', type: 'image-to-video',
387
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
388
+ resolutions: ['1080p', '720p'], aspectRatios: [],
389
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
390
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
391
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
392
+ },
393
+ {
394
+ id: 'happyhorse-1-1-reference-to-video', name: 'HappyHorse 1.1 R2V', type: 'image-to-video',
395
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
396
+ resolutions: ['1080p', '720p'],
397
+ aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9', '9:21', '5:4', '4:5'],
398
+ // Top-level audio_url is rejected ("This model does not support audio input",
399
+ // probe 2026-07-23), but per-reference audio via
400
+ // image_references[{image_url, audio_url}] IS accepted (paid job queued same
401
+ // probe). Requires the object-form builder; audioInput stays false.
402
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
403
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
404
+ maxDurationSec: 15, perReferenceAudio: true, supportsReferenceAudio: true,
405
+ privacy: 'anonymized', offline: false,
406
+ },
407
+ // -- Kling V3 --
408
+ {
409
+ id: 'kling-v3-pro-text-to-video', name: 'Kling V3 Pro', type: 'text-to-video',
410
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
411
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
412
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
413
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
414
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
415
+ },
416
+ {
417
+ id: 'kling-v3-pro-image-to-video', name: 'Kling V3 Pro', type: 'image-to-video',
418
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
419
+ resolutions: [], aspectRatios: [],
420
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
421
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
422
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
423
+ },
424
+ {
425
+ id: 'kling-v3-standard-text-to-video', name: 'Kling V3 Standard', type: 'text-to-video',
426
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
427
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1'],
428
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
429
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
430
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
431
+ },
432
+ {
433
+ id: 'kling-v3-standard-image-to-video', name: 'Kling V3 Standard', type: 'image-to-video',
434
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
435
+ resolutions: [], aspectRatios: [],
436
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
437
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
438
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
439
+ },
440
+ // -- Longcat --
441
+ {
442
+ id: 'longcat-distilled-image-to-video', name: 'Longcat Distilled', type: 'image-to-video',
443
+ durations: ['5s', '10s', '15s', '20s', '30s'], resolutions: ['720p'], aspectRatios: [],
444
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
445
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
446
+ maxDurationSec: 30, privacy: 'anonymized', offline: false,
447
+ },
448
+ {
449
+ id: 'longcat-distilled-text-to-video', name: 'Longcat Distilled', type: 'text-to-video',
450
+ durations: ['5s', '10s', '15s', '20s', '30s'], resolutions: ['720p'], aspectRatios: ['16:9', '9:16', '1:1'],
451
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
452
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
453
+ maxDurationSec: 30, privacy: 'anonymized', offline: false,
454
+ },
455
+ {
456
+ id: 'longcat-image-to-video', name: 'Longcat', type: 'image-to-video',
457
+ durations: ['5s', '10s', '15s', '20s', '30s'], resolutions: ['720p'], aspectRatios: [],
458
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
459
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
460
+ maxDurationSec: 30, privacy: 'anonymized', offline: false,
461
+ },
462
+ {
463
+ id: 'longcat-text-to-video', name: 'Longcat', type: 'text-to-video',
464
+ durations: ['5s', '10s', '15s', '20s', '30s'], resolutions: ['720p'], aspectRatios: ['16:9', '9:16', '1:1'],
465
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
466
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
467
+ maxDurationSec: 30, privacy: 'anonymized', offline: false,
468
+ },
469
+ // -- Veo 3 --
470
+ {
471
+ id: 'veo3-fast-text-to-video', name: 'Veo 3 Fast', type: 'text-to-video',
472
+ durations: ['4s', '6s', '8s'], resolutions: ['720p', '1080p'], aspectRatios: ['16:9', '9:16'],
473
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
474
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
475
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
476
+ },
477
+ {
478
+ id: 'veo3-fast-image-to-video', name: 'Veo 3 Fast', type: 'image-to-video',
479
+ durations: ['8s'], resolutions: [], aspectRatios: ['16:9'],
480
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
481
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
482
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
483
+ },
484
+ {
485
+ id: 'veo3-full-text-to-video', name: 'Veo 3 Full', type: 'text-to-video',
486
+ durations: ['4s', '6s', '8s'], resolutions: ['720p', '1080p'], aspectRatios: ['16:9', '9:16'],
487
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
488
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
489
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
490
+ },
491
+ {
492
+ id: 'veo3-full-image-to-video', name: 'Veo 3 Full', type: 'image-to-video',
493
+ durations: ['8s'], resolutions: [], aspectRatios: ['16:9'],
494
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
495
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
496
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
497
+ },
498
+ // -- Veo 3.1 --
499
+ {
500
+ id: 'veo3.1-fast-text-to-video', name: 'Veo 3.1 Fast', type: 'text-to-video',
501
+ durations: ['4s', '6s', '8s'], resolutions: ['720p', '1080p', '4k'], aspectRatios: ['16:9', '9:16'],
502
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
503
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
504
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
505
+ },
506
+ {
507
+ id: 'veo3.1-fast-image-to-video', name: 'Veo 3.1 Fast', type: 'image-to-video',
508
+ durations: ['4s', '6s', '8s'], resolutions: ['720p', '1080p', '4k'], aspectRatios: [],
509
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
510
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
511
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
512
+ },
513
+ {
514
+ id: 'veo3.1-full-text-to-video', name: 'Veo 3.1 Full', type: 'text-to-video',
515
+ durations: ['4s', '6s', '8s'], resolutions: ['720p', '1080p', '4k'], aspectRatios: ['16:9', '9:16'],
516
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
517
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
518
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
519
+ },
520
+ {
521
+ id: 'veo3.1-full-image-to-video', name: 'Veo 3.1 Full', type: 'image-to-video',
522
+ durations: ['4s', '6s', '8s'], resolutions: ['720p', '1080p', '4k'], aspectRatios: [],
523
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
524
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
525
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
526
+ },
527
+ // -- Seedance 2.0 --
528
+ {
529
+ id: 'seedance-2-0-image-to-video', name: 'Seedance 2.0', type: 'image-to-video',
530
+ durations: ['4s', '5s', '8s', '10s', '12s', '15s'],
531
+ resolutions: ['480p', '720p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
532
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
533
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
534
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
535
+ },
536
+ {
537
+ id: 'seedance-2-0-text-to-video', name: 'Seedance 2.0', type: 'text-to-video',
538
+ durations: ['4s', '5s', '8s', '10s', '12s', '15s'],
539
+ resolutions: ['480p', '720p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
540
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
541
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
542
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
543
+ },
544
+ // Seedance R2V variants accept audio_url despite /models reporting
545
+ // audio_input: false — live probe 2026-07-23 (queue accepted audio_url on all
546
+ // four R2V variants, real job completed on Fast R2V; i2v/t2v rejected with
547
+ // "This model does not support audio input"). reference_audio_urls (≤3) also
548
+ // validates on R2V only.
549
+ {
550
+ id: 'seedance-2-0-reference-to-video', name: 'Seedance 2.0 R2V', type: 'image-to-video',
551
+ durations: ['4s', '5s', '8s', '10s', '12s', '15s'],
552
+ resolutions: ['480p', '720p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
553
+ audio: true, audioConfigurable: true, audioInput: true, videoInput: false,
554
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
555
+ maxDurationSec: 15, supportsReferenceAudio: true, privacy: 'anonymized', offline: false,
556
+ },
557
+ // Delisted from GET /models (2026-07 sync) but still live on the queue/quote
558
+ // endpoints — probed 2026-07-15 (quote OK at 5/8/10/15s, 720p + 1080p).
559
+ // Higher-fidelity "enhanced" render path of Seedance 2.0 R2V; same duration
560
+ // ladder, roughly ~1.5x the standard R2V price per clip.
561
+ {
562
+ id: 'seedance-2-0-enhanced-reference-to-video', name: 'Seedance 2.0 R2V Enhanced', type: 'image-to-video',
563
+ durations: ['4s', '5s', '8s', '10s', '12s', '15s'],
564
+ resolutions: ['480p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
565
+ // audioInput probe 2026-07-23: queue validator accepted audio_url (R2V family).
566
+ audio: true, audioConfigurable: true, audioInput: true, videoInput: false,
567
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
568
+ maxDurationSec: 15, supportsReferenceAudio: true, privacy: 'anonymized', offline: false,
569
+ },
570
+ // -- Sora 2 --
571
+ {
572
+ id: 'sora-2-image-to-video', name: 'Sora 2', type: 'image-to-video',
573
+ durations: ['4s', '8s', '12s'], resolutions: ['720p'], aspectRatios: ['16:9', '9:16'],
574
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
575
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
576
+ maxDurationSec: 12, privacy: 'anonymized', offline: false,
577
+ },
578
+ {
579
+ // Sora 2 Pro: durations expanded to 20s as of 2026-05; 'true_1080p' added.
580
+ id: 'sora-2-pro-image-to-video', name: 'Sora 2 Pro', type: 'image-to-video',
581
+ durations: ['4s', '8s', '12s', '16s', '20s'],
582
+ resolutions: ['720p', '1080p', 'true_1080p'], aspectRatios: ['16:9', '9:16'],
583
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
584
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
585
+ maxDurationSec: 20, privacy: 'anonymized', offline: false,
586
+ },
587
+ {
588
+ id: 'sora-2-text-to-video', name: 'Sora 2', type: 'text-to-video',
589
+ durations: ['4s', '8s', '12s'], resolutions: ['720p'], aspectRatios: ['16:9', '9:16'],
590
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
591
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
592
+ maxDurationSec: 12, privacy: 'anonymized', offline: false,
593
+ },
594
+ {
595
+ id: 'sora-2-pro-text-to-video', name: 'Sora 2 Pro', type: 'text-to-video',
596
+ durations: ['4s', '8s', '12s', '16s', '20s'],
597
+ resolutions: ['720p', '1080p', 'true_1080p'], aspectRatios: ['16:9', '9:16'],
598
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
599
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
600
+ maxDurationSec: 20, privacy: 'anonymized', offline: false,
601
+ },
602
+ // -- PixVerse v5.6 --
603
+ {
604
+ id: 'pixverse-v5.6-text-to-video', name: 'PixVerse v5.6', type: 'text-to-video',
605
+ durations: ['5s', '8s'], resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4'],
606
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
607
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
608
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
609
+ },
610
+ {
611
+ id: 'pixverse-v5.6-image-to-video', name: 'PixVerse v5.6', type: 'image-to-video',
612
+ durations: ['5s', '8s'], resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: [],
613
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
614
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
615
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
616
+ },
617
+ {
618
+ id: 'pixverse-v5.6-transition', name: 'PixVerse v5.6 Transition', type: 'image-to-video',
619
+ durations: ['5s', '8s'], resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4'],
620
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
621
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
622
+ maxDurationSec: 8, privacy: 'anonymized', offline: false,
623
+ },
624
+ // -- Vidu Q3 --
625
+ {
626
+ id: 'vidu-q3-text-to-video', name: 'Vidu Q3', type: 'text-to-video',
627
+ durations: ['3s', '5s', '8s', '10s', '12s', '14s', '16s'], resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
628
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
629
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
630
+ maxDurationSec: 16, privacy: 'anonymized', offline: false,
631
+ },
632
+ {
633
+ id: 'vidu-q3-image-to-video', name: 'Vidu Q3', type: 'image-to-video',
634
+ durations: ['3s', '5s', '8s', '10s', '12s', '14s', '16s'], resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: [],
635
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
636
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
637
+ maxDurationSec: 16, privacy: 'anonymized', offline: false,
638
+ },
639
+ // -- Runway Gen-4.5 (added 2026-05 sync) --
640
+ // Runway's family on Venice: all variants top out at 10s, silent (audio:false,
641
+ // not configurable), no end_image_url, no R2V identity refs. Pick when the
642
+ // user wants Runway's signature motion physics, not when they need
643
+ // character identity locks.
644
+ {
645
+ id: 'runway-gen4-5', name: 'Runway Gen-4.5', type: 'image-to-video',
646
+ durations: ['2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s'],
647
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'],
648
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
649
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
650
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
651
+ },
652
+ {
653
+ id: 'runway-gen4-5-text', name: 'Runway Gen-4.5', type: 'text-to-video',
654
+ durations: ['2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s'],
655
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'],
656
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
657
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
658
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
659
+ },
660
+ {
661
+ id: 'runway-gen4-turbo', name: 'Runway Gen-4 Turbo', type: 'image-to-video',
662
+ durations: ['2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s'],
663
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'],
664
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
665
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
666
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
667
+ },
668
+ {
669
+ id: 'runway-gen4-aleph', name: 'Runway Gen-4 Aleph', type: 'image-to-video',
670
+ durations: ['2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s'],
671
+ resolutions: [], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'],
672
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
673
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
674
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
675
+ },
676
+ // -- Seedance 2.0 Fast (added 2026-05 sync) --
677
+ // Cheaper / quicker Seedance 2.0 variants. Same i2v / t2v / R2V split as
678
+ // the regular Seedance 2.0 line, same 4-15s ladder, same image provenance
679
+ // gate. Pick when iterating or when the per-second cost of Seedance regular
680
+ // is prohibitive.
681
+ {
682
+ id: 'seedance-2-0-fast-image-to-video', name: 'Seedance 2.0 Fast', type: 'image-to-video',
683
+ durations: ['4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
684
+ resolutions: ['480p', '720p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
685
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
686
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
687
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
688
+ },
689
+ {
690
+ id: 'seedance-2-0-fast-text-to-video', name: 'Seedance 2.0 Fast', type: 'text-to-video',
691
+ durations: ['4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
692
+ resolutions: ['480p', '720p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
693
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
694
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
695
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
696
+ },
697
+ {
698
+ id: 'seedance-2-0-fast-reference-to-video', name: 'Seedance 2.0 Fast R2V', type: 'image-to-video',
699
+ durations: ['4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
700
+ resolutions: ['480p', '720p'], aspectRatios: ['16:9', '9:16', '4:3', '3:4', '1:1'],
701
+ // audioInput probe 2026-07-23: real audio_url job queued + completed.
702
+ audio: true, audioConfigurable: true, audioInput: true, videoInput: false,
703
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
704
+ maxDurationSec: 15, supportsReferenceAudio: true, privacy: 'anonymized', offline: false,
705
+ },
706
+ // -- PixVerse C1 (added 2026-05 sync) --
707
+ // PixVerse's c1 line. Replaces the v5.6 family for new projects: same four
708
+ // resolutions but 15s native durations (vs v5.6's 8s ceiling) AND a new R2V
709
+ // variant with `reference_image_urls`. Transition variant also gained
710
+ // the 15s ladder.
711
+ {
712
+ id: 'pixverse-c1-text-to-video', name: 'PixVerse C1', type: 'text-to-video',
713
+ durations: ['3s', '5s', '8s', '10s', '15s'],
714
+ resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4'],
715
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
716
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
717
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
718
+ },
719
+ {
720
+ id: 'pixverse-c1-image-to-video', name: 'PixVerse C1', type: 'image-to-video',
721
+ durations: ['3s', '5s', '8s', '10s', '15s'],
722
+ resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: [],
723
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
724
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
725
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
726
+ },
727
+ {
728
+ id: 'pixverse-c1-reference-to-video', name: 'PixVerse C1 R2V', type: 'image-to-video',
729
+ durations: ['3s', '5s', '8s', '10s', '15s'],
730
+ resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4'],
731
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
732
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
733
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
734
+ },
735
+ {
736
+ id: 'pixverse-c1-transition', name: 'PixVerse C1 Transition', type: 'image-to-video',
737
+ durations: ['3s', '5s', '8s', '10s', '15s'],
738
+ resolutions: ['360p', '540p', '720p', '1080p'], aspectRatios: ['16:9', '9:16', '1:1', '4:3', '3:4'],
739
+ audio: true, audioConfigurable: true, audioInput: false, videoInput: false,
740
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: true,
741
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
742
+ },
743
+ // -- DaVinci MagiHuman: REMOVED 2026-07-06 --
744
+ // Venice pulled `davinci-magihuman-image-to-video` from the live catalog
745
+ // (`/models?type=all` no longer lists it). Entry removed here and the matching
746
+ // magihuman branches dropped from the app's VideoModelCapabilities in the same
747
+ // change (per harness↔app capability-sync rule). Restore both if Venice re-adds it.
748
+ // -- Wan 2.7 Spicy + Wan 2.6 R2V (added 2026-05 sync) --
749
+ // wan-2-7-spicy-image-to-video is an uncensored Wan 2.7 i2v variant; same
750
+ // 5/10/15s ladder. wan-2.6-reference-to-video is the new R2V variant of
751
+ // the Wan 2.6 family.
752
+ {
753
+ id: 'wan-2-7-spicy-image-to-video', name: 'Wan 2.7 Spicy', type: 'image-to-video',
754
+ durations: ['5s', '10s', '15s'], resolutions: ['1080p', '720p'], aspectRatios: [],
755
+ audio: false, audioConfigurable: false, audioInput: true, videoInput: false,
756
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
757
+ maxDurationSec: 15, minAudioInputSec: 3,
758
+ privacy: 'anonymized', offline: false,
759
+ },
760
+ {
761
+ id: 'wan-2.6-reference-to-video', name: 'Wan 2.6 R2V', type: 'image-to-video',
762
+ durations: ['5s', '10s'], resolutions: ['1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
763
+ audio: true, audioConfigurable: true, audioInput: true, videoInput: false,
764
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
765
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
766
+ },
767
+ // -- Kling V3 4K (added 2026-05 sync) --
768
+ // 4K-resolution variants of Kling V3 R2V and t2v.
769
+ {
770
+ id: 'kling-v3-4k-text-to-video', name: 'Kling V3 4K', type: 'text-to-video',
771
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
772
+ resolutions: ['4K', '1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
773
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
774
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
775
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
776
+ },
777
+ {
778
+ id: 'kling-v3-4k-reference-to-video', name: 'Kling V3 4K R2V', type: 'image-to-video',
779
+ durations: ['3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s', '11s', '12s', '13s', '14s', '15s'],
780
+ resolutions: ['4K', '1080p', '720p'], aspectRatios: ['16:9', '9:16', '1:1'],
781
+ audio: true, audioConfigurable: false, audioInput: false, videoInput: false,
782
+ supportsElements: true, supportsReferenceImages: true, supportsSceneImages: true, supportsEndImage: true,
783
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
784
+ },
785
+ // -- Grok Imagine R2V + V2V (added 2026-05 sync) --
786
+ // Grok Imagine gained R2V (with reference_image_urls) and V2V (video input)
787
+ // variants. R2V durations are stepped: 5s/8s/10s only.
788
+ {
789
+ id: 'grok-imagine-reference-to-video', name: 'Grok Imagine R2V', type: 'image-to-video',
790
+ durations: ['5s', '8s', '10s'], resolutions: ['480p', '720p'],
791
+ aspectRatios: ['16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'],
792
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: false,
793
+ supportsElements: false, supportsReferenceImages: true, supportsSceneImages: false, supportsEndImage: false,
794
+ maxDurationSec: 10, privacy: 'anonymized', offline: false,
795
+ },
796
+ {
797
+ id: 'grok-imagine-video-to-video', name: 'Grok Imagine V2V', type: 'image-to-video',
798
+ durations: ['5s', '10s', '15s'], resolutions: ['480p', '720p'],
799
+ aspectRatios: ['16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'],
800
+ audio: false, audioConfigurable: false, audioInput: false, videoInput: true,
801
+ supportsElements: false, supportsReferenceImages: false, supportsSceneImages: false, supportsEndImage: false,
802
+ maxDurationSec: 15, privacy: 'anonymized', offline: false,
803
+ },
804
+ ];
805
+ export const IMAGE_GENERATION_MODELS = [
806
+ // Registry refreshed 2026-05-20 against live /models?type=image (28 models).
807
+ // `qwen-image` was sunset in favour of `qwen-image-2`; new entries below are
808
+ // marked in trailing comments.
809
+ { id: 'venice-sd35', name: 'Venice SD 3.5', type: 'generation', offline: false },
810
+ { id: 'hidream', name: 'HiDream', type: 'generation', offline: false },
811
+ { id: 'flux-2-pro', name: 'Flux 2 Pro', type: 'generation', offline: false },
812
+ { id: 'flux-2-max', name: 'Flux 2 Max', type: 'generation', offline: false },
813
+ { id: 'gpt-image-1-5', name: 'GPT Image 1.5', type: 'generation', offline: false },
814
+ { id: 'gpt-image-2', name: 'GPT Image 2', type: 'generation', offline: false },
815
+ // Grok Imagine image-gen split into two endpoints (2026-05+):
816
+ { id: 'grok-imagine-image', name: 'Grok Imagine', type: 'generation', offline: false },
817
+ { id: 'grok-imagine-image-quality', name: 'Grok Imagine Quality', type: 'generation', offline: false },
818
+ { id: 'hunyuan-image-v3', name: 'Hunyuan Image V3', type: 'generation', offline: false },
819
+ { id: 'imagineart-1.5-pro', name: 'ImagineArt 1.5 Pro', type: 'generation', offline: false },
820
+ { id: 'nano-banana-2', name: 'Nano Banana 2', type: 'generation', offline: false },
821
+ { id: 'nano-banana-pro', name: 'Nano Banana Pro', type: 'generation', offline: false },
822
+ { id: 'recraft-v4', name: 'Recraft V4', type: 'generation', offline: false },
823
+ { id: 'recraft-v4-pro', name: 'Recraft V4 Pro', type: 'generation', offline: false },
824
+ { id: 'seedream-v4', name: 'SeedReam V4', type: 'generation', offline: false },
825
+ { id: 'seedream-v5-lite', name: 'SeedReam V5 Lite', type: 'generation', offline: false },
826
+ { id: 'qwen-image-2', name: 'Qwen Image 2', type: 'generation', offline: false },
827
+ { id: 'qwen-image-2-pro', name: 'Qwen Image 2 Pro', type: 'generation', offline: false },
828
+ { id: 'lustify-sdxl', name: 'Lustify SDXL', type: 'generation', offline: false },
829
+ { id: 'lustify-v7', name: 'Lustify V7', type: 'generation', offline: false },
830
+ { id: 'lustify-v8', name: 'Lustify V8', type: 'generation', offline: false },
831
+ { id: 'wai-Illustrious', name: 'WAI Illustrious', type: 'generation', offline: false },
832
+ { id: 'z-image-turbo', name: 'Z Image Turbo', type: 'generation', offline: false },
833
+ { id: 'chroma', name: 'Chroma', type: 'generation', offline: false },
834
+ // Ernie joins the Venice image catalog (2026-05+):
835
+ { id: 'ernie-image', name: 'Ernie Image', type: 'generation', offline: false },
836
+ { id: 'ernie-image-turbo', name: 'Ernie Image Turbo', type: 'generation', offline: false },
837
+ // Wan 2.7 also offers text-to-image (separate from the video-gen pipeline):
838
+ { id: 'wan-2-7-text-to-image', name: 'Wan 2.7 Text-to-Image', type: 'generation', offline: false },
839
+ { id: 'wan-2-7-pro-text-to-image', name: 'Wan 2.7 Pro Text-to-Image', type: 'generation', offline: false },
840
+ { id: 'bria-bg-remover', name: 'Bria Background Remover', type: 'background-remove', offline: false },
841
+ ];
842
+ export const MULTI_EDIT_MODELS = [
843
+ 'qwen-edit',
844
+ 'qwen-image-2-edit',
845
+ 'qwen-image-2-pro-edit',
846
+ 'flux-2-max-edit',
847
+ 'gpt-image-1-5-edit',
848
+ 'gpt-image-2-edit',
849
+ 'grok-imagine-edit',
850
+ 'nano-banana-2-edit',
851
+ 'nano-banana-pro-edit',
852
+ 'seedream-v4-edit',
853
+ 'seedream-v5-lite-edit',
854
+ ];
855
+ export const MUSIC_MODELS = [
856
+ { id: 'ace-step-15', name: 'ACE Step 1.5', type: 'music', offline: false },
857
+ { id: 'elevenlabs-music', name: 'ElevenLabs Music', type: 'music', offline: false },
858
+ { id: 'minimax-music-v2', name: 'MiniMax Music V2', type: 'music', offline: false },
859
+ { id: 'minimax-music-v25', name: 'MiniMax Music V2.5', type: 'music', offline: false },
860
+ { id: 'minimax-music-v26', name: 'MiniMax Music V2.6', type: 'music', offline: false },
861
+ { id: 'lyria-3-pro', name: 'Lyria 3 Pro', type: 'music', offline: false },
862
+ { id: 'stable-audio-25', name: 'Stable Audio 2.5', type: 'music', offline: false },
863
+ // Seed Audio 1.0 (BytePlus) — expressive speech + audio from a text prompt.
864
+ // A `music`-type (async queue) model, not a synchronous /audio/speech TTS:
865
+ // it carries named voices, speed control, and a 2048-char prompt, so treat
866
+ // it as premium prompt-driven narration/VO delivered through the audio queue.
867
+ {
868
+ id: 'seed-audio-1-0',
869
+ name: 'Seed Audio 1.0',
870
+ type: 'music',
871
+ offline: false,
872
+ voices: [
873
+ 'Describe in prompt', 'Tim', 'Stokie', 'Dacey', 'Vivi', 'Mindy', 'Kian',
874
+ 'Jess', 'Vienna', 'Cedric', 'Magnus', 'Quentin', 'Wukong', 'Gigi',
875
+ 'Celeste', 'Esther', 'Tracy', 'Sven', 'Felipe', 'Usseau', 'Enzo',
876
+ 'Minimi', 'Jihoon', 'Martins', 'Han',
877
+ ],
878
+ defaultVoice: 'Describe in prompt',
879
+ supportsSpeed: true,
880
+ minSpeed: 0.5,
881
+ maxSpeed: 2,
882
+ defaultSpeed: 1,
883
+ supportsLyrics: false,
884
+ lyricsRequired: false,
885
+ supportsForceInstrumental: false,
886
+ supportsLanguageCode: false,
887
+ supportedFormats: ['mp3', 'wav'],
888
+ defaultFormat: 'mp3',
889
+ promptCharacterLimit: 2048,
890
+ minPromptLength: 1,
891
+ defaultDurationSec: 120,
892
+ pricingPerSecondUsd: 0.0028750000000000004,
893
+ description: 'Generate expressive speech and audio from a text prompt with BytePlus Seed Audio 1.0.',
894
+ },
895
+ { id: 'elevenlabs-sound-effects-v2', name: 'ElevenLabs Sound Effects V2', type: 'sound-effects', offline: false },
896
+ { id: 'mmaudio-v2-text-to-audio', name: 'MMAudio V2', type: 'sound-effects', offline: false },
897
+ { id: 'elevenlabs-tts-v3', name: 'ElevenLabs TTS V3', type: 'tts', offline: false },
898
+ { id: 'elevenlabs-tts-multilingual-v2', name: 'ElevenLabs TTS Multilingual V2', type: 'tts', offline: false },
899
+ ];
900
+ export const TTS_MODELS = ['tts-kokoro', 'tts-qwen3-0-6b', 'tts-qwen3-1-7b'];
901
+ // ---- Lookup helpers -------------------------------------------------------
902
+ const _videoIndex = new Map(VIDEO_MODELS.map(m => [m.id, m]));
903
+ export function getVideoModel(id) {
904
+ return _videoIndex.get(id);
905
+ }
906
+ const _musicIndex = new Map(MUSIC_MODELS.map(m => [m.id, m]));
907
+ export function getMusicModel(id) {
908
+ return _musicIndex.get(id);
909
+ }
910
+ export function listMusicModels(filter) {
911
+ let models = MUSIC_MODELS.filter(m => !m.offline);
912
+ if (filter?.type)
913
+ models = models.filter(m => m.type === filter.type);
914
+ return models;
915
+ }
916
+ export function listVideoModels(filter) {
917
+ let models = VIDEO_MODELS.filter(m => !m.offline);
918
+ if (filter?.type)
919
+ models = models.filter(m => m.type === filter.type);
920
+ if (filter?.audio !== undefined)
921
+ models = models.filter(m => m.audio === filter.audio);
922
+ if (filter?.minDurationSec)
923
+ models = models.filter(m => m.maxDurationSec >= filter.minDurationSec);
924
+ if (filter?.supportsElements)
925
+ models = models.filter(m => m.supportsElements);
926
+ if (filter?.supportsReferenceImages)
927
+ models = models.filter(m => m.supportsReferenceImages);
928
+ if (filter?.supportsEndImage)
929
+ models = models.filter(m => m.supportsEndImage);
930
+ if (filter?.imageToVideo)
931
+ models = models.filter(m => m.type === 'image-to-video');
932
+ return models;
933
+ }
934
+ /**
935
+ * Check if a model supports a given duration string (e.g. "8s").
936
+ * Falls back to checking max duration if the duration is within range.
937
+ */
938
+ export function modelSupportsDuration(modelId, duration) {
939
+ const model = getVideoModel(modelId);
940
+ if (!model)
941
+ return false;
942
+ if (model.durations.includes(duration))
943
+ return true;
944
+ const sec = parseInt(duration, 10);
945
+ return !isNaN(sec) && sec <= model.maxDurationSec;
946
+ }
947
+ /**
948
+ * For a given model, return the closest valid duration to the requested one.
949
+ */
950
+ export function closestValidDuration(modelId, requestedSec) {
951
+ const model = getVideoModel(modelId);
952
+ if (!model || model.durations.length === 0)
953
+ return undefined;
954
+ const parsed = model.durations.map(d => ({ label: d, sec: parseInt(d, 10) }));
955
+ parsed.sort((a, b) => Math.abs(a.sec - requestedSec) - Math.abs(b.sec - requestedSec));
956
+ return parsed[0]?.label;
957
+ }
958
+ /**
959
+ * Build the model-specific parameters for a video queue request.
960
+ * Handles resolution, aspect_ratio, and end_image_url based on model capabilities.
961
+ */
962
+ export function buildModelParams(modelId, opts) {
963
+ const model = getVideoModel(modelId);
964
+ const params = {};
965
+ if (!model)
966
+ return params;
967
+ if (opts.resolution && model.resolutions.length > 0) {
968
+ const validRes = model.resolutions.includes(opts.resolution) ? opts.resolution : model.resolutions[0];
969
+ params.resolution = validRes;
970
+ }
971
+ if (opts.aspectRatio && model.aspectRatios.length > 0) {
972
+ if (model.aspectRatios.includes(opts.aspectRatio)) {
973
+ params.aspect_ratio = opts.aspectRatio;
974
+ }
975
+ }
976
+ else if (model.type === 'image-to-video' && model.id.includes('reference-to-video') && model.aspectRatios.length > 0) {
977
+ params.aspect_ratio = opts.aspectRatio ?? '16:9';
978
+ }
979
+ if (opts.endImageUrl && model.supportsEndImage) {
980
+ params.end_image_url = opts.endImageUrl;
981
+ }
982
+ return params;
983
+ }
984
+ //# sourceMappingURL=models.js.map