Fix thumbnail generation and add preview window

Fixed Issues:
- Exit 234 error: Added font parameter to drawtext filter for individual
  thumbnails (was missing, causing FFmpeg to fail)
- Output directory: Changed from temp to video's directory, creating a
  folder named "{video}_thumbnails" next to the source file

New Features:
- Added video preview window to thumbnail module (640x360)
- Split layout: preview on left (55%), settings on right (45%)
- Preview uses same buildVideoPane as other modules for consistency

The thumbnail module now has a proper preview window for reviewing
the loaded video before generating thumbnails, and outputs are saved
in a logical location next to the source file.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Stu Leak 2025-12-13 20:40:06 -05:00
parent 37fa9d1a5c
commit a40f7ad795
2 changed files with 23 additions and 6 deletions

View File

@ -234,7 +234,7 @@ func (g *Generator) generateIndividual(ctx context.Context, config Config, durat
seconds := int(ts) % 60
timeStr := fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
drawTextFilter := fmt.Sprintf("scale=%d:%d,drawtext=text='%s':fontcolor=white:fontsize=20:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=h-th-10",
drawTextFilter := fmt.Sprintf("scale=%d:%d,drawtext=text='%s':fontcolor=white:fontsize=20:font='DejaVu Sans Mono':box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=h-th-10",
thumbWidth, thumbHeight, timeStr)
// Replace scale filter with combined filter

27
main.go
View File

@ -9504,12 +9504,16 @@ func buildThumbView(state *appState) fyne.CanvasObject {
state.thumbRows = 6 // 4x6 = 24 thumbnails
}
// File label
// File label and video preview
fileLabel := widget.NewLabel("No file loaded")
fileLabel.TextStyle = fyne.TextStyle{Bold: true}
var videoContainer fyne.CanvasObject
if state.thumbFile != nil {
fileLabel.SetText(fmt.Sprintf("File: %s", filepath.Base(state.thumbFile.Path)))
videoContainer = buildVideoPane(state, fyne.NewSize(640, 360), state.thumbFile, nil)
} else {
videoContainer = container.NewCenter(widget.NewLabel("No video loaded"))
}
// Load button
@ -9623,8 +9627,10 @@ func buildThumbView(state *appState) fyne.CanvasObject {
state.showThumbView()
go func() {
// Create temp directory for thumbnails
outputDir := filepath.Join(os.TempDir(), fmt.Sprintf("videotools_thumbs_%d", time.Now().Unix()))
// Create output directory in same folder as video
videoDir := filepath.Dir(state.thumbFile.Path)
videoBaseName := strings.TrimSuffix(filepath.Base(state.thumbFile.Path), filepath.Ext(state.thumbFile.Path))
outputDir := filepath.Join(videoDir, fmt.Sprintf("%s_thumbnails", videoBaseName))
generator := thumbnail.NewGenerator(platformConfig.FFmpegPath)
@ -9712,13 +9718,24 @@ func buildThumbView(state *appState) fyne.CanvasObject {
generateBtn,
)
// Main content
// Main content - split layout with preview on left, settings on right
leftColumn := container.NewVBox(
videoContainer,
)
rightColumn := container.NewVBox(
settingsPanel,
)
mainContent := container.NewHSplit(leftColumn, rightColumn)
mainContent.Offset = 0.55 // Give more space to preview
content := container.NewBorder(
container.NewVBox(instructions, widget.NewSeparator(), fileLabel, container.NewHBox(loadBtn, clearBtn)),
nil,
nil,
nil,
settingsPanel,
mainContent,
)
return container.NewBorder(topBar, nil, nil, nil, content)