@@ -30,6 +30,25 @@ function safePricingExecution(
30
30
}
31
31
}
32
32
33
+ /**
34
+ * Helper function to calculate Runway duration-based pricing
35
+ * @param node - The LiteGraph node
36
+ * @returns Formatted price string
37
+ */
38
+ const calculateRunwayDurationPrice = ( node : LGraphNode ) : string => {
39
+ const durationWidget = node . widgets ?. find (
40
+ ( w ) => w . name === 'duration'
41
+ ) as IComboWidget
42
+
43
+ if ( ! durationWidget ) return '$0.05/second'
44
+
45
+ const duration = Number ( durationWidget . value )
46
+ // If duration is 0 or NaN, don't fall back to 5 seconds - just use 0
47
+ const validDuration = isNaN ( duration ) ? 5 : duration
48
+ const cost = ( 0.05 * validDuration ) . toFixed ( 2 )
49
+ return `$${ cost } /Run`
50
+ }
51
+
33
52
const pixversePricingCalculator = ( node : LGraphNode ) : string => {
34
53
const durationWidget = node . widgets ?. find (
35
54
( w ) => w . name === 'duration_seconds'
@@ -1007,43 +1026,13 @@ const apiNodeCosts: Record<string, { displayPrice: string | PricingFunction }> =
1007
1026
displayPrice : '$0.08/Run'
1008
1027
} ,
1009
1028
RunwayImageToVideoNodeGen3a : {
1010
- displayPrice : ( node : LGraphNode ) : string => {
1011
- const durationWidget = node . widgets ?. find (
1012
- ( w ) => w . name === 'duration'
1013
- ) as IComboWidget
1014
-
1015
- if ( ! durationWidget ) return '$0.05/second'
1016
-
1017
- const duration = Number ( durationWidget . value ) || 5
1018
- const cost = ( 0.05 * duration ) . toFixed ( 2 )
1019
- return `$${ cost } /Run`
1020
- }
1029
+ displayPrice : calculateRunwayDurationPrice
1021
1030
} ,
1022
1031
RunwayImageToVideoNodeGen4 : {
1023
- displayPrice : ( node : LGraphNode ) : string => {
1024
- const durationWidget = node . widgets ?. find (
1025
- ( w ) => w . name === 'duration'
1026
- ) as IComboWidget
1027
-
1028
- if ( ! durationWidget ) return '$0.05/second'
1029
-
1030
- const duration = Number ( durationWidget . value ) || 5
1031
- const cost = ( 0.05 * duration ) . toFixed ( 2 )
1032
- return `$${ cost } /Run`
1033
- }
1032
+ displayPrice : calculateRunwayDurationPrice
1034
1033
} ,
1035
1034
RunwayFirstLastFrameNode : {
1036
- displayPrice : ( node : LGraphNode ) : string => {
1037
- const durationWidget = node . widgets ?. find (
1038
- ( w ) => w . name === 'duration'
1039
- ) as IComboWidget
1040
-
1041
- if ( ! durationWidget ) return '$0.05/second'
1042
-
1043
- const duration = Number ( durationWidget . value ) || 5
1044
- const cost = ( 0.05 * duration ) . toFixed ( 2 )
1045
- return `$${ cost } /Run`
1046
- }
1035
+ displayPrice : calculateRunwayDurationPrice
1047
1036
} ,
1048
1037
// Rodin nodes - all have the same pricing structure
1049
1038
Rodin3D_Regular : {
@@ -1186,6 +1175,68 @@ const apiNodeCosts: Record<string, { displayPrice: string | PricingFunction }> =
1186
1175
return textureQuality . includes ( 'detailed' ) ? '$0.2/Run' : '$0.1/Run'
1187
1176
}
1188
1177
} ,
1178
+ TripoConvertModelNode : {
1179
+ displayPrice : '$0.10/Run'
1180
+ } ,
1181
+ TripoRetargetRiggedModelNode : {
1182
+ displayPrice : '$0.10/Run'
1183
+ } ,
1184
+ TripoMultiviewToModelNode : {
1185
+ displayPrice : ( node : LGraphNode ) : string => {
1186
+ const quadWidget = node . widgets ?. find (
1187
+ ( w ) => w . name === 'quad'
1188
+ ) as IComboWidget
1189
+ const styleWidget = node . widgets ?. find (
1190
+ ( w ) => w . name === 'style'
1191
+ ) as IComboWidget
1192
+ const textureWidget = node . widgets ?. find (
1193
+ ( w ) => w . name === 'texture'
1194
+ ) as IComboWidget
1195
+ const textureQualityWidget = node . widgets ?. find (
1196
+ ( w ) => w . name === 'texture_quality'
1197
+ ) as IComboWidget
1198
+
1199
+ if ( ! quadWidget || ! styleWidget || ! textureWidget )
1200
+ return '$0.2-0.5/Run (varies with quad, style, texture & quality)'
1201
+
1202
+ const quad = String ( quadWidget . value ) . toLowerCase ( ) === 'true'
1203
+ const style = String ( styleWidget . value ) . toLowerCase ( )
1204
+ const texture = String ( textureWidget . value ) . toLowerCase ( ) === 'true'
1205
+ const textureQuality = String (
1206
+ textureQualityWidget ?. value || 'standard'
1207
+ ) . toLowerCase ( )
1208
+
1209
+ // Pricing logic based on CSV data for Multiview to Model (same as Image to Model)
1210
+ if ( style . includes ( 'none' ) ) {
1211
+ if ( ! quad ) {
1212
+ if ( ! texture ) return '$0.20/Run'
1213
+ else return '$0.25/Run'
1214
+ } else {
1215
+ if ( textureQuality . includes ( 'detailed' ) ) {
1216
+ if ( ! texture ) return '$0.40/Run'
1217
+ else return '$0.45/Run'
1218
+ } else {
1219
+ if ( ! texture ) return '$0.30/Run'
1220
+ else return '$0.35/Run'
1221
+ }
1222
+ }
1223
+ } else {
1224
+ // any style
1225
+ if ( ! quad ) {
1226
+ if ( ! texture ) return '$0.25/Run'
1227
+ else return '$0.30/Run'
1228
+ } else {
1229
+ if ( textureQuality . includes ( 'detailed' ) ) {
1230
+ if ( ! texture ) return '$0.45/Run'
1231
+ else return '$0.50/Run'
1232
+ } else {
1233
+ if ( ! texture ) return '$0.35/Run'
1234
+ else return '$0.40/Run'
1235
+ }
1236
+ }
1237
+ }
1238
+ }
1239
+ } ,
1189
1240
// Google/Gemini nodes
1190
1241
GeminiNode : {
1191
1242
displayPrice : ( node : LGraphNode ) : string => {
0 commit comments