This commit is contained in:
Kevin Wong
2026-02-26 10:14:41 +08:00
parent 1717635bfd
commit 42b5cc0c02
11 changed files with 299 additions and 39 deletions

View File

@@ -16,9 +16,9 @@ export const RemotionRoot: React.FC = () => {
fps={25}
width={1080}
height={1920}
calculateMetadata={async ({ props }) => ({
width: props.width || 1080,
height: props.height || 1920,
calculateMetadata={async ({ props }: { props: Record<string, unknown> }) => ({
width: (props.width as number) || 1080,
height: (props.height as number) || 1920,
})}
defaultProps={{
videoSrc: '',
@@ -32,7 +32,7 @@ export const RemotionRoot: React.FC = () => {
secondaryTitleStyle: undefined,
width: 1080,
height: 1920,
}}
} satisfies VideoProps}
/>
</>
);

View File

@@ -19,6 +19,7 @@ export interface VideoProps {
secondaryTitleStyle?: TitleStyle;
width?: number;
height?: number;
[key: string]: unknown;
}
/**

View File

@@ -38,16 +38,14 @@ const getFontFormat = (fontFile?: string) => {
return 'truetype';
};
const buildTextShadow = (color: string, size: number) => {
return [
`-${size}px -${size}px 0 ${color}`,
`${size}px -${size}px 0 ${color}`,
`-${size}px ${size}px 0 ${color}`,
`${size}px ${size}px 0 ${color}`,
`0 0 ${size * 4}px rgba(0,0,0,0.9)`,
`0 4px 8px rgba(0,0,0,0.6)`
].join(',');
};
/**
* 构建描边样式(使用 CSS 原生描边,避免 textShadow 重影)
*/
const buildStrokeStyle = (color: string, size: number): React.CSSProperties => ({
WebkitTextStroke: `${size}px ${color}`,
paintOrder: 'stroke fill',
textShadow: `0 2px 4px rgba(0,0,0,0.4)`,
});
export const Subtitles: React.FC<SubtitlesProps> = ({ captions, style }) => {
const frame = useCurrentFrame();
@@ -133,7 +131,7 @@ export const Subtitles: React.FC<SubtitlesProps> = ({ captions, style }) => {
key={`${word.word}-${index}`}
style={{
color: isHighlighted ? highlightColor : normalColor,
textShadow: buildTextShadow(strokeColor, strokeSize),
...buildStrokeStyle(strokeColor, strokeSize),
transition: 'color 0.05s ease',
}}
>

View File

@@ -44,16 +44,15 @@ const getFontFormat = (fontFile?: string) => {
return 'truetype';
};
const buildTextShadow = (color: string, size: number) => {
return [
`-${size}px -${size}px 0 ${color}`,
`${size}px -${size}px 0 ${color}`,
`-${size}px ${size}px 0 ${color}`,
`${size}px ${size}px 0 ${color}`,
`0 0 ${size * 2}px rgba(0,0,0,0.5)`,
`0 2px 4px rgba(0,0,0,0.3)`
].join(',');
};
/**
* 构建描边样式(使用 CSS 原生描边,避免 textShadow 重影)
* 返回需要合并到 style 对象上的属性
*/
const buildStrokeStyle = (color: string, size: number): React.CSSProperties => ({
WebkitTextStroke: `${size}px ${color}`,
paintOrder: 'stroke fill',
textShadow: `0 2px 4px rgba(0,0,0,0.3)`,
});
export const Title: React.FC<TitleProps> = ({
title,
@@ -194,7 +193,7 @@ export const Title: React.FC<TitleProps> = ({
fontSize: `${fontSize}px`,
fontWeight,
fontFamily: fontFamilyCss,
textShadow: buildTextShadow(strokeColor, strokeSize),
...buildStrokeStyle(strokeColor, strokeSize),
margin: 0,
width: '100%',
boxSizing: 'border-box',
@@ -217,7 +216,7 @@ export const Title: React.FC<TitleProps> = ({
fontSize: `${stFontSize}px`,
fontWeight: stFontWeight,
fontFamily: stFontFile && stFontFile !== fontFile ? stFontFamilyCss : fontFamilyCss,
textShadow: buildTextShadow(stStrokeColor, stStrokeSize),
...buildStrokeStyle(stStrokeColor, stStrokeSize),
margin: 0,
marginTop: `${stMarginTop}px`,
width: '100%',

View File

@@ -21,7 +21,6 @@ export const VideoLayer: React.FC<VideoLayerProps> = ({
<AbsoluteFill>
<OffthreadVideo
src={videoUrl}
loop
style={{
width: '100%',
height: '100%',