This commit is contained in:
ct
2025-06-17 21:25:33 +08:00
parent 886d20a793
commit f61f95d6d1
4 changed files with 175 additions and 23 deletions

View File

@@ -63,9 +63,9 @@ const sampleTimelineElements = [
fontWeight: 'bold',
fontFamily: 'Montserrat',
fontStyle: 'normal',
fill: 'white',
stroke: 'black',
strokeWidth: 1,
fill: '#ffffff',
stroke: '#000000',
strokeWidth: 3,
rotation: 0,
},
{
@@ -81,8 +81,8 @@ const sampleTimelineElements = [
fontWeight: 'bold',
fontFamily: 'Montserrat',
fontStyle: 'normal',
fill: 'yellow',
stroke: 'red',
fill: '#ffff00',
stroke: '#ff0000',
strokeWidth: 2,
rotation: 0,
},

View File

@@ -44,6 +44,25 @@ const useVideoExport = ({ timelineElements, dimensions, totalDuration }) => {
}
};
// Helper function to convert color format for FFmpeg
const formatColorForFFmpeg = (color) => {
// Handle hex colors (e.g., #ffffff or #fff)
if (color && color.startsWith('#')) {
// Remove the # and ensure it's 6 characters
let hex = color.slice(1);
if (hex.length === 3) {
// Convert short hex to full hex (e.g., fff -> ffffff)
hex = hex
.split('')
.map((char) => char + char)
.join('');
}
return `0x${hex}`;
}
// Handle named colors or other formats - fallback to original
return color || '0xffffff';
};
const generateFFmpegCommand = useCallback(
(is_string = true, useLocalFiles = false) => {
showConsoleLogs && console.log('🎬 STARTING FFmpeg generation');
@@ -134,7 +153,7 @@ const useVideoExport = ({ timelineElements, dimensions, totalDuration }) => {
showConsoleLogs && console.log('🎵 Audio args:', audioArgs);
// Process text elements with proper font support
// Process text elements with proper font support and color handling
texts.forEach((t, i) => {
const escapedText = t.text.replace(/'/g, is_string ? "\\'" : "'").replace(/:/g, '\\:');
@@ -146,11 +165,22 @@ const useVideoExport = ({ timelineElements, dimensions, totalDuration }) => {
const centerX = Math.round(t.x);
const centerY = Math.round(t.y + t.fontSize * 0.3); // Adjust for text baseline
filters.push(
`[${videoLayer}]drawtext=fontfile=/${fontFileName}:text='${escapedText}':x=${centerX}:y=${centerY}:fontsize=${t.fontSize}:fontcolor=${t.fill}:borderw=${t.strokeWidth}:bordercolor=${
t.stroke
}:text_align=center:enable='between(t,${t.startTime},${t.startTime + t.duration})'[t${i}]`,
);
// Format colors for FFmpeg
const fontColor = formatColorForFFmpeg(t.fill);
const borderColor = formatColorForFFmpeg(t.stroke);
const borderWidth = Math.max(0, t.strokeWidth || 0); // Ensure non-negative
// Build drawtext filter with proper border handling
let drawTextFilter = `[${videoLayer}]drawtext=fontfile=/${fontFileName}:text='${escapedText}':x=${centerX}:y=${centerY}:fontsize=${t.fontSize}:fontcolor=${fontColor}`;
// Only add border if strokeWidth > 0
if (borderWidth > 0) {
drawTextFilter += `:borderw=${borderWidth}:bordercolor=${borderColor}`;
}
drawTextFilter += `:text_align=center:enable='between(t,${t.startTime},${t.startTime + t.duration})'[t${i}]`;
filters.push(drawTextFilter);
videoLayer = `t${i}`;
});

View File

@@ -476,9 +476,11 @@ const VideoPreview = ({
fontSize={element.fontSize}
fontStyle={getTextFontStyle(element)}
fontFamily={element.fontFamily || 'Arial'}
fill={element.fill}
stroke={element.stroke}
strokeWidth={element.strokeWidth}
fill={element.fill || '#ffffff'}
stroke={element.strokeWidth > 0 ? element.stroke || '#000000' : undefined}
strokeWidth={element.strokeWidth || 0}
fillAfterStrokeEnabled={true}
strokeScaleEnabled={false}
rotation={element.rotation || 0}
// Center the text horizontally
align="center"