@@ -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 }
@@ -2007,7 +2014,11 @@ export const VideoGeneratorV3Block: BlockConfig = {
20072014 if ( ! model ) return { ...falParams , visualReference : undefined }
20082015 const withImage = Boolean ( model . image && falParams . visualReference )
20092016 return {
2010- ...keepFalSettingsAllowed ( falParams , getFalVideoVariant ( params . model , withImage ) ) ,
2017+ ...keepFalSettingsAllowed (
2018+ falParams ,
2019+ getFalVideoVariant ( params . model , withImage ) ,
2020+ getFalVideoVariant ( params . model , ! withImage )
2021+ ) ,
20112022 visualReference : withImage ? falParams . visualReference : undefined ,
20122023 }
20132024 }
@@ -2016,21 +2027,35 @@ export const VideoGeneratorV3Block: BlockConfig = {
20162027 ? normalizeFileInput ( params . visualReference , { single : true } )
20172028 : undefined
20182029 const model = getDirectVideoModel ( params . provider , params . model , Boolean ( visualReference ) )
2030+ const other = getDirectVideoModel ( params . provider , params . model , ! visualReference ) ?. settings
20192031 const setting = ( key : string , supported : unknown , fallbackKey ?: string ) => {
20202032 if ( ! supported ) return undefined
20212033 const value = params [ key ] ?? ( fallbackKey ? params [ fallbackKey ] : undefined )
20222034 return value === FAL_MODEL_DEFAULT . id ? undefined : value
20232035 }
2024- const duration = setting ( 'duration' , model ?. settings ?. durations )
2036+ const duration = dropStaleSetting (
2037+ setting ( 'duration' , model ?. settings ?. durations ) ,
2038+ model ?. settings ?. durations ,
2039+ other ?. durations ,
2040+ true
2041+ )
20252042 return {
20262043 provider : params . provider ,
20272044 model : params . model ,
20282045 apiKey : params . apiKey ,
20292046 prompt : params . prompt ,
20302047 visualReference,
20312048 duration : duration ? Number ( duration ) : undefined ,
2032- aspectRatio : setting ( 'aspectRatio' , model ?. settings ?. aspectRatios ) ,
2033- resolution : setting ( 'resolution' , model ?. settings ?. resolutions ) ,
2049+ aspectRatio : dropStaleSetting (
2050+ setting ( 'aspectRatio' , model ?. settings ?. aspectRatios ) ,
2051+ model ?. settings ?. aspectRatios ,
2052+ other ?. aspectRatios
2053+ ) ,
2054+ resolution : dropStaleSetting (
2055+ setting ( 'resolution' , model ?. settings ?. resolutions ) ,
2056+ model ?. settings ?. resolutions ,
2057+ other ?. resolutions
2058+ ) ,
20342059 generateAudio : parseOptionalBooleanInput (
20352060 setting ( 'directGenerateAudio' , model ?. settings ?. audio , 'generateAudio' )
20362061 ) ,
0 commit comments