feat(video): add video model validation and settings improvements

- Introduce new utility and config files for video model validation
- Refactor ModelSetting component to use centralized video models config
- Update VideoPage to handle video params with proper model validation
This commit is contained in:
icarus 2025-10-12 05:32:26 +08:00
parent 377b2b796f
commit f61cadd5b5
4 changed files with 58 additions and 14 deletions

View File

@ -0,0 +1,6 @@
import { SystemProviderId } from '@renderer/types'
// Hard-encoded for now. We may implement a function to filter video generation model from provider.models.
export const videoModelsMap = {
openai: ['sora-2', 'sora-2-pro'] as const
} as const satisfies Partial<Record<SystemProviderId, string[]>>

View File

@ -4,19 +4,47 @@ import { Divider } from '@heroui/react'
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
import { useProvider } from '@renderer/hooks/useProvider'
import { SystemProviderIds } from '@renderer/types'
import { useState } from 'react'
import { CreateVideoParams } from '@renderer/types/video'
import { isVideoModel } from '@renderer/utils/model/video'
import { DeepPartial } from 'ai'
import { merge } from 'lodash'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ModelSetting } from './settings/ModelSetting'
import { OpenAIParamSettings } from './settings/OpenAIParamSettings'
import { ProviderSetting } from './settings/ProviderSetting'
import { SettingsGroup } from './settings/shared'
import { VideoList } from './VideoList'
import { VideoPanel } from './VideoPanel'
export const VideoPage = () => {
const { t } = useTranslation()
const [providerId, setProviderId] = useState<string>(SystemProviderIds.openai)
const [modelId, setModelId] = useState('sora-2')
const { provider } = useProvider(providerId)
const [params, setParams] = useState<CreateVideoParams>({
type: 'openai',
provider,
params: {
model: 'sora-2',
prompt: ''
},
options: {}
})
const updateParams = useCallback((update: DeepPartial<Omit<CreateVideoParams, 'type'>>) => {
setParams((prev) => merge({}, prev, update))
}, [])
const updateModelId = useCallback(
(id: string) => {
if (isVideoModel(id)) {
updateParams({ params: { model: id } })
}
},
[updateParams]
)
return (
<div className="flex flex-1 flex-col">
<Navbar>
@ -25,8 +53,15 @@ export const VideoPage = () => {
<div id="content-container" className="flex flex-1">
{/* Settings */}
<div className="flex w-70 flex-col p-2">
<ProviderSetting providerId={providerId} setProviderId={setProviderId} />
<ModelSetting providerId={providerId} modelId={modelId} setModelId={setModelId} />
<SettingsGroup>
<ProviderSetting providerId={providerId} setProviderId={setProviderId} />
<ModelSetting
providerId={providerId}
modelId={params.params.model ?? 'sora-2'}
setModelId={updateModelId}
/>
</SettingsGroup>
{provider.type === 'openai-response' && <OpenAIParamSettings params={params} updateParams={updateParams} />}
</div>
<Divider orientation="vertical" />
<VideoPanel provider={provider} />

View File

@ -1,14 +1,14 @@
import { Select, SelectItem } from '@heroui/react'
import { Model, SystemProviderId } from '@renderer/types'
import { Dispatch, SetStateAction } from 'react'
import { videoModelsMap } from '@renderer/config/models/video'
import { Model } from '@renderer/types'
import { useTranslation } from 'react-i18next'
import { SettingItem, SettingTitle } from './shared'
import { SettingItem } from './shared'
export interface ModelSettingProps {
providerId: string
modelId: string
setModelId: Dispatch<SetStateAction<string>>
setModelId: (id: string) => void
}
interface ModelSelectItem extends Model {
@ -16,11 +16,6 @@ interface ModelSelectItem extends Model {
label: string
}
// Hard-encoded for now. We may implement a function to filter video generation model from provider.models.
const videoModelsMap = {
openai: ['sora-2', 'sora-2-pro'] as const
} as const satisfies Partial<Record<SystemProviderId, string[]>>
export const ModelSetting = ({ providerId, modelId, setModelId }: ModelSettingProps) => {
const { t } = useTranslation()
@ -28,8 +23,9 @@ export const ModelSetting = ({ providerId, modelId, setModelId }: ModelSettingPr
return (
<SettingItem>
<SettingTitle name={t('common.model')} />
<Select
label={t('common.model')}
labelPlacement="outside"
selectionMode="single"
items={items}
defaultSelectedKeys={[modelId]}

View File

@ -0,0 +1,7 @@
import { VideoModel } from '@cherrystudio/openai/resources'
import { videoModelsMap } from '@renderer/config/models/video'
// Only for openai, use hard-encoded values
export const isVideoModel = (modelId: string): modelId is VideoModel => {
return videoModelsMap.openai.some((v) => v === modelId)
}