@@ -141,27 +141,34 @@ const LEGACY_FAL_SETTING_KEYS: Record<string, keyof FalVideoSettings> = {
141141}
142142
143143/**
144- * Drops stored settings the endpoint a run calls does not accept, so the model default applies.
145- * Attaching or removing a start frame switches endpoints without clearing the settings chosen for
146- * the other one: Seedance 2.5 takes `16:9` from a prompt but only `auto` from a start frame.
144+ * Drops a stored setting the endpoint a run calls rejects but the model's other endpoint accepts,
145+ * so the model default applies. Attaching or removing a start frame switches endpoints without
146+ * clearing settings picked for the other one: Seedance 2.5 takes `16:9` from a prompt but only
147+ * `auto` from a start frame. Any other value passes through to the request's own legacy mapping
148+ * and validation.
147149 */
150+ function dropStaleSetting (
151+ value : unknown ,
152+ allowed : readonly ( number | string ) [ ] | undefined ,
153+ otherAllowed : readonly ( number | string ) [ ] | undefined ,
154+ numeric = false
155+ ) {
156+ const normalize = ( choice : unknown ) => ( numeric ? Number . parseFloat ( String ( choice ) ) : choice )
157+ const accepts = ( choices ?: readonly ( number | string ) [ ] ) =>
158+ choices ?. some ( ( choice ) => normalize ( choice ) === normalize ( value ) ) ?? false
159+ return value !== undefined && ! accepts ( allowed ) && accepts ( otherAllowed ) ? undefined : value
160+ }
161+
148162function keepFalSettingsAllowed (
149163 params : Record < string , unknown > ,
150- settings : FalVideoSettings | undefined
164+ settings : FalVideoSettings | undefined ,
165+ other : FalVideoSettings | undefined
151166) {
152- const { duration, aspectRatio, resolution } = params
153- const durations = settings ?. durations ?. map ( ( value ) => Number . parseFloat ( String ( value ) ) )
154167 return {
155168 ...params ,
156- duration : typeof duration === 'number' && durations ?. includes ( duration ) ? duration : undefined ,
157- aspectRatio :
158- typeof aspectRatio === 'string' && settings ?. aspectRatios ?. includes ( aspectRatio )
159- ? aspectRatio
160- : undefined ,
161- resolution :
162- typeof resolution === 'string' && settings ?. resolutions ?. includes ( resolution )
163- ? resolution
164- : undefined ,
169+ duration : dropStaleSetting ( params . duration , settings ?. durations , other ?. durations , true ) ,
170+ aspectRatio : dropStaleSetting ( params . aspectRatio , settings ?. aspectRatios , other ?. aspectRatios ) ,
171+ resolution : dropStaleSetting ( params . resolution , settings ?. resolutions , other ?. resolutions ) ,
165172 generateAudio : settings ?. audioField ? params . generateAudio : undefined ,
166173 promptOptimizer : settings ?. promptOptimizer ? params . promptOptimizer : undefined ,
167174 }
@@ -2029,7 +2036,11 @@ export const VideoGeneratorV3Block: BlockConfig = {
20292036 if ( ! model ) return { ...falParams , visualReference : undefined }
20302037 const withImage = Boolean ( model . image && falParams . visualReference )
20312038 return {
2032- ...keepFalSettingsAllowed ( falParams , getFalVideoVariant ( params . model , withImage ) ) ,
2039+ ...keepFalSettingsAllowed (
2040+ falParams ,
2041+ getFalVideoVariant ( params . model , withImage ) ,
2042+ getFalVideoVariant ( params . model , ! withImage )
2043+ ) ,
20332044 visualReference : withImage ? falParams . visualReference : undefined ,
20342045 }
20352046 }
@@ -2038,21 +2049,35 @@ export const VideoGeneratorV3Block: BlockConfig = {
20382049 ? normalizeFileInput ( params . visualReference , { single : true } )
20392050 : undefined
20402051 const model = getDirectVideoModel ( params . provider , params . model , Boolean ( visualReference ) )
2052+ const other = getDirectVideoModel ( params . provider , params . model , ! visualReference ) ?. settings
20412053 const setting = ( key : string , supported : unknown , fallbackKey ?: string ) => {
20422054 if ( ! supported ) return undefined
20432055 const value = params [ key ] ?? ( fallbackKey ? params [ fallbackKey ] : undefined )
20442056 return value === FAL_MODEL_DEFAULT . id ? undefined : value
20452057 }
2046- const duration = setting ( 'duration' , model ?. settings ?. durations )
2058+ const duration = dropStaleSetting (
2059+ setting ( 'duration' , model ?. settings ?. durations ) ,
2060+ model ?. settings ?. durations ,
2061+ other ?. durations ,
2062+ true
2063+ )
20472064 return {
20482065 provider : params . provider ,
20492066 model : params . model ,
20502067 apiKey : params . apiKey ,
20512068 prompt : params . prompt ,
20522069 visualReference,
20532070 duration : duration ? Number ( duration ) : undefined ,
2054- aspectRatio : setting ( 'aspectRatio' , model ?. settings ?. aspectRatios ) ,
2055- resolution : setting ( 'resolution' , model ?. settings ?. resolutions ) ,
2071+ aspectRatio : dropStaleSetting (
2072+ setting ( 'aspectRatio' , model ?. settings ?. aspectRatios ) ,
2073+ model ?. settings ?. aspectRatios ,
2074+ other ?. aspectRatios
2075+ ) ,
2076+ resolution : dropStaleSetting (
2077+ setting ( 'resolution' , model ?. settings ?. resolutions ) ,
2078+ model ?. settings ?. resolutions ,
2079+ other ?. resolutions
2080+ ) ,
20562081 generateAudio : parseOptionalBooleanInput (
20572082 setting ( 'directGenerateAudio' , model ?. settings ?. audio , 'generateAudio' )
20582083 ) ,
0 commit comments