The caption model selector now sits directly under the dictation model in the STT tab's Local Whisper card, where people look for it, and stays in the General tab's caption section as well; both use one shared component. The first selector is renamed to 'Dictation model' so the two are told apart.
41 lines
1.6 KiB
TypeScript
41 lines
1.6 KiB
TypeScript
// 실시간 자막 전용 로컬 Whisper 모델 선택 — STT 탭과 일반 탭 자막 섹션이 함께 쓴다.
|
|
|
|
import { FormControl, InputLabel, MenuItem, Select, Typography } from '@mui/material'
|
|
import { d3roPalette, d3roTypo } from '@d3ro/ui/theme'
|
|
import { useI18n } from '@d3ro/i18n'
|
|
import type { STTModel } from '@d3ro/core/types'
|
|
|
|
/** "받아쓰기와 같게" — 설정에는 null 로 저장한다 */
|
|
const SAME_AS_DICTATION = '__same__'
|
|
|
|
interface CaptionModelSelectProps {
|
|
value: string | null | undefined
|
|
/** 선택지로 보일 모델 — 받아 둔 모델만 넘긴다 */
|
|
models: readonly STTModel[]
|
|
onChange: (modelId: string | null) => void
|
|
fullWidth?: boolean
|
|
}
|
|
|
|
export function CaptionModelSelect({ value, models, onChange, fullWidth }: CaptionModelSelectProps): React.ReactElement {
|
|
const { t } = useI18n()
|
|
return (
|
|
<FormControl size="small" fullWidth={fullWidth}>
|
|
<InputLabel>{t('settings.captionModel')}</InputLabel>
|
|
<Select
|
|
label={t('settings.captionModel')}
|
|
value={value ?? SAME_AS_DICTATION}
|
|
onChange={(e) => onChange(e.target.value === SAME_AS_DICTATION ? null : e.target.value)}
|
|
>
|
|
<MenuItem value={SAME_AS_DICTATION}>{t('settings.captionModel.same')}</MenuItem>
|
|
{models.map((m) => (
|
|
<MenuItem key={m.id} value={m.id}>
|
|
{m.name}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
<Typography sx={{ mt: 0.5, fontSize: d3roTypo.meta.size, color: d3roPalette.text.secondary }}>
|
|
{t('settings.captionModel.desc')}
|
|
</Typography>
|
|
</FormControl>
|
|
)
|
|
}
|