Improve benchmark results sorting and cancel flow
This commit is contained in:
parent
73e527048a
commit
5b76da0fdf
55
DONE.md
55
DONE.md
|
|
@ -2,9 +2,59 @@
|
|||
|
||||
This file tracks completed features, fixes, and milestones.
|
||||
|
||||
## Version 0.1.0-dev19 (2025-12-18) - Convert Module Cleanup & UX Polish
|
||||
## Version 0.1.0-dev19 (2025-12-18 to 2025-12-20) - Convert Module Cleanup & UX Polish
|
||||
|
||||
### Features
|
||||
### Features (2025-12-20 Session)
|
||||
- ✅ **History Sidebar - In Progress Tab**
|
||||
- Added "In Progress" tab to history sidebar
|
||||
- Shows running and pending jobs without opening queue
|
||||
- Animated striped progress bars per module color
|
||||
- Real-time progress updates (0-100%)
|
||||
- No delete button on active jobs (only completed/failed)
|
||||
- Dynamic status text ("Running..." or "Pending")
|
||||
|
||||
- ✅ **Benchmark System Overhaul**
|
||||
- **Hardware Detection Module** (`internal/sysinfo/sysinfo.go`)
|
||||
- Cross-platform CPU detection (model, cores, clock speed)
|
||||
- GPU detection with driver version (NVIDIA via nvidia-smi)
|
||||
- RAM detection with human-readable formatting
|
||||
- Linux, Windows, macOS support
|
||||
- **Hardware Info Display**
|
||||
- Shown immediately in benchmark progress view (before tests run)
|
||||
- Displayed in benchmark results view
|
||||
- Saved with each benchmark run for history
|
||||
- **Settings Persistence**
|
||||
- Hardware acceleration settings saved with benchmarks
|
||||
- Settings persist between sessions via config file
|
||||
- GPU automatically detected and used
|
||||
- **UI Polish**
|
||||
- "Run Benchmark" button highlighted (HighImportance) on first run
|
||||
- Returns to normal styling after initial benchmark
|
||||
- Guides new users to run initial benchmark
|
||||
|
||||
- ✅ **Bitrate Preset Simplification**
|
||||
- Reduced from 13 confusing options to 6 clear presets
|
||||
- Removed resolution references (no more "1440p" confusion)
|
||||
- Codec-agnostic (presets don't change selected codec)
|
||||
- Quality-based naming: Low/Medium/Good/High/Very High Quality
|
||||
- Focused on common use cases (1.5-8 Mbps range)
|
||||
- Presets only set bitrate and switch to CBR mode
|
||||
- User codec choice (H.264, VP9, AV1, etc.) preserved
|
||||
|
||||
- ✅ **Quality Preset Codec Compatibility**
|
||||
- "Lossless" quality option only available for H.265 and AV1
|
||||
- Dynamic quality dropdown based on selected codec
|
||||
- Automatic fallback to "Near-Lossless" when switching to non-lossless codec
|
||||
- Lossless + Target Size bitrate mode now supported for H.265/AV1
|
||||
- Prevents invalid codec/quality combinations
|
||||
|
||||
- ✅ **App Icon Improvements**
|
||||
- Regenerated VT_Icon.ico with transparent background
|
||||
- Updated LoadAppIcon() to search PNG first (better Linux support)
|
||||
- Searches both current directory and executable directory
|
||||
- Added debug logging for icon loading troubleshooting
|
||||
|
||||
### Features (2025-12-18 Session)
|
||||
- ✅ **History Sidebar Enhancements**
|
||||
- Delete button ("×") on each history entry
|
||||
- Remove individual entries from history
|
||||
|
|
@ -715,6 +765,7 @@ This file tracks completed features, fixes, and milestones.
|
|||
|
||||
### Recent Fixes
|
||||
- ✅ Fixed aspect ratio default from 16:9 to Source (dev7)
|
||||
- ✅ Ranked benchmark results by score and added cancel confirmation
|
||||
- ✅ Stabilized video seeking and embedded rendering
|
||||
- ✅ Improved player window positioning
|
||||
- ✅ Fixed clear video functionality
|
||||
|
|
|
|||
29
TODO.md
29
TODO.md
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
This file tracks upcoming features, improvements, and known issues.
|
||||
|
||||
## Current Focus: dev19 - Convert Module Cleanup & Polish
|
||||
## Current Focus: dev20+ - Feature Development
|
||||
|
||||
### In Progress
|
||||
- [ ] **AI Frame Interpolation Support**
|
||||
- [ ] **AI Frame Interpolation Support** (Deferred to dev20+)
|
||||
- RIFE (Real-Time Intermediate Flow Estimation) - https://github.com/hzwer/ECCV2022-RIFE
|
||||
- FILM (Frame Interpolation for Large Motion) - https://github.com/google-research/frame-interpolation
|
||||
- DAIN (Depth-Aware Video Frame Interpolation) - https://github.com/baowenbo/DAIN
|
||||
|
|
@ -14,11 +14,34 @@ This file tracks upcoming features, improvements, and known issues.
|
|||
- Model download/management system
|
||||
- UI controls for model selection
|
||||
|
||||
- [ ] **Color Space Preservation**
|
||||
- [ ] **Color Space Preservation** (Deferred to dev20+)
|
||||
- Fix color space preservation in upscale module
|
||||
- Ensure all conversions preserve color metadata (color_space, color_primaries, color_trc, color_range)
|
||||
- Test with HDR content
|
||||
|
||||
### Completed in dev19 (2025-12-20)
|
||||
- [x] **History Sidebar - In Progress Tab** ✅ COMPLETED
|
||||
- Shows running/pending jobs without opening full queue
|
||||
- Animated progress bars per module color
|
||||
- Real-time progress updates
|
||||
|
||||
- [x] **Benchmark System Overhaul** ✅ COMPLETED
|
||||
- Hardware detection module (CPU, GPU, RAM, drivers)
|
||||
- Hardware info displayed in progress and results views
|
||||
- Settings persistence across sessions
|
||||
- First-run button highlighting
|
||||
- Results ranked by score with cancel confirmation
|
||||
|
||||
- [x] **Bitrate Preset Simplification** ✅ COMPLETED
|
||||
- Codec-agnostic quality-based presets
|
||||
- Removed confusing resolution references
|
||||
- 6 clear presets: Manual, Low, Medium, Good, High, Very High
|
||||
|
||||
- [x] **Quality Preset Codec Compatibility** ✅ COMPLETED
|
||||
- Lossless option only for H.265/AV1
|
||||
- Dynamic dropdown based on codec
|
||||
- Lossless + Target Size mode support
|
||||
|
||||
## Priority Features for dev20+
|
||||
|
||||
### Quality & Polish Improvements
|
||||
|
|
|
|||
|
|
@ -3,20 +3,24 @@ package ui
|
|||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"sort"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/benchmark"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/sysinfo"
|
||||
)
|
||||
|
||||
// BuildBenchmarkProgressView creates the benchmark progress UI
|
||||
func BuildBenchmarkProgressView(
|
||||
hwInfo sysinfo.HardwareInfo,
|
||||
onCancel func(),
|
||||
titleColor, bgColor, textColor color.Color,
|
||||
) *BenchmarkProgressView {
|
||||
view := &BenchmarkProgressView{
|
||||
hwInfo: hwInfo,
|
||||
titleColor: titleColor,
|
||||
bgColor: bgColor,
|
||||
textColor: textColor,
|
||||
|
|
@ -28,6 +32,7 @@ func BuildBenchmarkProgressView(
|
|||
|
||||
// BenchmarkProgressView shows real-time benchmark progress
|
||||
type BenchmarkProgressView struct {
|
||||
hwInfo sysinfo.HardwareInfo
|
||||
titleColor color.Color
|
||||
bgColor color.Color
|
||||
textColor color.Color
|
||||
|
|
@ -57,6 +62,37 @@ func (v *BenchmarkProgressView) build() {
|
|||
container.NewCenter(title),
|
||||
)
|
||||
|
||||
// Hardware info section
|
||||
hwInfoTitle := widget.NewLabel("System Hardware")
|
||||
hwInfoTitle.TextStyle = fyne.TextStyle{Bold: true}
|
||||
hwInfoTitle.Alignment = fyne.TextAlignCenter
|
||||
|
||||
cpuLabel := widget.NewLabel(fmt.Sprintf("CPU: %s (%d cores @ %s)", v.hwInfo.CPU, v.hwInfo.CPUCores, v.hwInfo.CPUMHz))
|
||||
cpuLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
gpuLabel := widget.NewLabel(fmt.Sprintf("GPU: %s", v.hwInfo.GPU))
|
||||
gpuLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
ramLabel := widget.NewLabel(fmt.Sprintf("RAM: %s", v.hwInfo.RAM))
|
||||
|
||||
driverLabel := widget.NewLabel(fmt.Sprintf("Driver: %s", v.hwInfo.GPUDriver))
|
||||
driverLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
hwCard := canvas.NewRectangle(color.RGBA{R: 34, G: 38, B: 48, A: 255})
|
||||
hwCard.CornerRadius = 8
|
||||
|
||||
hwContent := container.NewVBox(
|
||||
hwInfoTitle,
|
||||
cpuLabel,
|
||||
gpuLabel,
|
||||
ramLabel,
|
||||
driverLabel,
|
||||
)
|
||||
|
||||
hwInfoSection := container.NewPadded(
|
||||
container.NewMax(hwCard, hwContent),
|
||||
)
|
||||
|
||||
// Status section
|
||||
v.statusLabel = widget.NewLabel("Initializing benchmark...")
|
||||
v.statusLabel.TextStyle = fyne.TextStyle{Bold: true}
|
||||
|
|
@ -96,6 +132,8 @@ func (v *BenchmarkProgressView) build() {
|
|||
header,
|
||||
nil, nil, nil,
|
||||
container.NewVBox(
|
||||
hwInfoSection,
|
||||
widget.NewSeparator(),
|
||||
statusSection,
|
||||
widget.NewSeparator(),
|
||||
resultsSection,
|
||||
|
|
@ -188,6 +226,7 @@ func (v *BenchmarkProgressView) SetComplete() {
|
|||
func BuildBenchmarkResultsView(
|
||||
results []benchmark.Result,
|
||||
recommendation benchmark.Result,
|
||||
hwInfo sysinfo.HardwareInfo,
|
||||
onApply func(),
|
||||
onClose func(),
|
||||
titleColor, bgColor, textColor color.Color,
|
||||
|
|
@ -207,6 +246,37 @@ func BuildBenchmarkResultsView(
|
|||
container.NewCenter(title),
|
||||
)
|
||||
|
||||
// Hardware info section
|
||||
hwInfoTitle := widget.NewLabel("System Hardware")
|
||||
hwInfoTitle.TextStyle = fyne.TextStyle{Bold: true}
|
||||
hwInfoTitle.Alignment = fyne.TextAlignCenter
|
||||
|
||||
cpuLabel := widget.NewLabel(fmt.Sprintf("CPU: %s (%d cores @ %s)", hwInfo.CPU, hwInfo.CPUCores, hwInfo.CPUMHz))
|
||||
cpuLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
gpuLabel := widget.NewLabel(fmt.Sprintf("GPU: %s", hwInfo.GPU))
|
||||
gpuLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
ramLabel := widget.NewLabel(fmt.Sprintf("RAM: %s", hwInfo.RAM))
|
||||
|
||||
driverLabel := widget.NewLabel(fmt.Sprintf("Driver: %s", hwInfo.GPUDriver))
|
||||
driverLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
hwCard := canvas.NewRectangle(color.RGBA{R: 34, G: 38, B: 48, A: 255})
|
||||
hwCard.CornerRadius = 8
|
||||
|
||||
hwContent := container.NewVBox(
|
||||
hwInfoTitle,
|
||||
cpuLabel,
|
||||
gpuLabel,
|
||||
ramLabel,
|
||||
driverLabel,
|
||||
)
|
||||
|
||||
hwInfoSection := container.NewPadded(
|
||||
container.NewMax(hwCard, hwContent),
|
||||
)
|
||||
|
||||
// Recommendation section
|
||||
if recommendation.Encoder != "" {
|
||||
recTitle := widget.NewLabel("RECOMMENDED ENCODER")
|
||||
|
|
@ -243,12 +313,19 @@ func BuildBenchmarkResultsView(
|
|||
topResultsTitle.TextStyle = fyne.TextStyle{Bold: true}
|
||||
topResultsTitle.Alignment = fyne.TextAlignCenter
|
||||
|
||||
var resultItems []fyne.CanvasObject
|
||||
for i, result := range results {
|
||||
if result.Error != "" {
|
||||
continue
|
||||
var filtered []benchmark.Result
|
||||
for _, result := range results {
|
||||
if result.Error == "" {
|
||||
filtered = append(filtered, result)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(filtered, func(i, j int) bool {
|
||||
return filtered[i].Score > filtered[j].Score
|
||||
})
|
||||
|
||||
var resultItems []fyne.CanvasObject
|
||||
for i, result := range filtered {
|
||||
rankLabel := widget.NewLabel(fmt.Sprintf("#%d", i+1))
|
||||
rankLabel.TextStyle = fyne.TextStyle{Bold: true}
|
||||
|
||||
|
|
@ -290,6 +367,8 @@ func BuildBenchmarkResultsView(
|
|||
header,
|
||||
nil, nil, nil,
|
||||
container.NewVBox(
|
||||
hwInfoSection,
|
||||
widget.NewSeparator(),
|
||||
recommendationSection,
|
||||
widget.NewSeparator(),
|
||||
resultsSection,
|
||||
|
|
|
|||
110
main.go
110
main.go
|
|
@ -44,6 +44,7 @@ import (
|
|||
"git.leaktechnologies.dev/stu/VideoTools/internal/modules"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/player"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/queue"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/sysinfo"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/thumbnail"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/ui"
|
||||
"git.leaktechnologies.dev/stu/VideoTools/internal/utils"
|
||||
|
|
@ -81,16 +82,17 @@ var (
|
|||
nvencRuntimeOK bool
|
||||
|
||||
modulesList = []Module{
|
||||
{"convert", "Convert", utils.MustHex("#8B44FF"), "Convert", modules.HandleConvert}, // Violet
|
||||
{"merge", "Merge", utils.MustHex("#4488FF"), "Convert", modules.HandleMerge}, // Blue
|
||||
{"trim", "Trim", utils.MustHex("#44DDFF"), "Convert", modules.HandleTrim}, // Cyan
|
||||
{"filters", "Filters", utils.MustHex("#44FF88"), "Convert", modules.HandleFilters}, // Green
|
||||
{"upscale", "Upscale", utils.MustHex("#AAFF44"), "Advanced", modules.HandleUpscale}, // Yellow-Green
|
||||
{"audio", "Audio", utils.MustHex("#FFD744"), "Convert", modules.HandleAudio}, // Yellow
|
||||
{"thumb", "Thumb", utils.MustHex("#FF8844"), "Screenshots", modules.HandleThumb}, // Orange
|
||||
{"compare", "Compare", utils.MustHex("#FF44AA"), "Inspect", modules.HandleCompare}, // Pink
|
||||
{"inspect", "Inspect", utils.MustHex("#FF4444"), "Inspect", modules.HandleInspect}, // Red
|
||||
{"player", "Player", utils.MustHex("#44FFDD"), "Playback", modules.HandlePlayer}, // Teal
|
||||
{"convert", "Convert", utils.MustHex("#8B44FF"), "Convert", modules.HandleConvert}, // Violet
|
||||
{"merge", "Merge", utils.MustHex("#4488FF"), "Convert", modules.HandleMerge}, // Blue
|
||||
{"trim", "Trim", utils.MustHex("#44DDFF"), "Convert", modules.HandleTrim}, // Cyan
|
||||
{"filters", "Filters", utils.MustHex("#44FF88"), "Convert", modules.HandleFilters}, // Green
|
||||
{"upscale", "Upscale", utils.MustHex("#AAFF44"), "Advanced", modules.HandleUpscale}, // Yellow-Green
|
||||
{"audio", "Audio", utils.MustHex("#FFD744"), "Convert", modules.HandleAudio}, // Yellow
|
||||
{"subtitles", "Subtitles", utils.MustHex("#44A6FF"), "Convert", modules.HandleSubtitles}, // Azure
|
||||
{"thumb", "Thumb", utils.MustHex("#FF8844"), "Screenshots", modules.HandleThumb}, // Orange
|
||||
{"compare", "Compare", utils.MustHex("#FF44AA"), "Inspect", modules.HandleCompare}, // Pink
|
||||
{"inspect", "Inspect", utils.MustHex("#FF4444"), "Inspect", modules.HandleInspect}, // Red
|
||||
{"player", "Player", utils.MustHex("#44FFDD"), "Playback", modules.HandlePlayer}, // Teal
|
||||
}
|
||||
|
||||
// Platform-specific configuration
|
||||
|
|
@ -557,12 +559,13 @@ func savePersistedConvertConfig(cfg convertConfig) error {
|
|||
|
||||
// benchmarkRun represents a single benchmark test run
|
||||
type benchmarkRun struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Results []benchmark.Result `json:"results"`
|
||||
RecommendedEncoder string `json:"recommended_encoder"`
|
||||
RecommendedPreset string `json:"recommended_preset"`
|
||||
RecommendedHWAccel string `json:"recommended_hwaccel"`
|
||||
RecommendedFPS float64 `json:"recommended_fps"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Results []benchmark.Result `json:"results"`
|
||||
RecommendedEncoder string `json:"recommended_encoder"`
|
||||
RecommendedPreset string `json:"recommended_preset"`
|
||||
RecommendedHWAccel string `json:"recommended_hwaccel"`
|
||||
RecommendedFPS float64 `json:"recommended_fps"`
|
||||
HardwareInfo sysinfo.HardwareInfo `json:"hardware_info"`
|
||||
}
|
||||
|
||||
// benchmarkConfig holds benchmark history
|
||||
|
|
@ -1355,7 +1358,7 @@ func (s *appState) showMainMenu() {
|
|||
Label: m.Label,
|
||||
Color: m.Color,
|
||||
Category: m.Category,
|
||||
Enabled: m.ID == "convert" || m.ID == "compare" || m.ID == "inspect" || m.ID == "merge" || m.ID == "thumb" || m.ID == "player" || m.ID == "filters" || m.ID == "upscale", // Enabled modules
|
||||
Enabled: m.ID == "convert" || m.ID == "compare" || m.ID == "inspect" || m.ID == "merge" || m.ID == "thumb" || m.ID == "player" || m.ID == "filters" || m.ID == "upscale", // Enabled modules (subtitles placeholder stays disabled)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1408,11 +1411,17 @@ func (s *appState) showMainMenu() {
|
|||
)
|
||||
}
|
||||
|
||||
// Check if benchmark has been run
|
||||
hasBenchmark := false
|
||||
if cfg, err := loadBenchmarkConfig(); err == nil && len(cfg.History) > 0 {
|
||||
hasBenchmark = true
|
||||
}
|
||||
|
||||
menu := ui.BuildMainMenu(mods, s.showModule, s.handleModuleDrop, s.showQueue, nil, s.showBenchmark, s.showBenchmarkHistory, func() {
|
||||
// Toggle sidebar
|
||||
s.sidebarVisible = !s.sidebarVisible
|
||||
s.showMainMenu()
|
||||
}, s.sidebarVisible, sidebar, titleColor, queueColor, textColor, queueCompleted, queueTotal)
|
||||
}, s.sidebarVisible, sidebar, titleColor, queueColor, textColor, queueCompleted, queueTotal, hasBenchmark)
|
||||
|
||||
// Update stats bar
|
||||
s.updateStatsBar()
|
||||
|
|
@ -1733,17 +1742,35 @@ func (s *appState) showBenchmark() {
|
|||
s.stopPlayer()
|
||||
s.active = "benchmark"
|
||||
|
||||
// Detect hardware info upfront
|
||||
hwInfo := sysinfo.Detect()
|
||||
logging.Debug(logging.CatSystem, "detected hardware for benchmark: %s", hwInfo.Summary())
|
||||
|
||||
// Create benchmark suite
|
||||
tmpDir := filepath.Join(os.TempDir(), "videotools-benchmark")
|
||||
_ = os.MkdirAll(tmpDir, 0o755)
|
||||
|
||||
suite := benchmark.NewSuite(platformConfig.FFmpegPath, tmpDir)
|
||||
|
||||
// Build progress view
|
||||
benchComplete := atomic.Bool{}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// Build progress view with hardware info
|
||||
view := ui.BuildBenchmarkProgressView(
|
||||
hwInfo,
|
||||
func() {
|
||||
// Cancel benchmark
|
||||
s.showMainMenu()
|
||||
if benchComplete.Load() {
|
||||
s.showMainMenu()
|
||||
return
|
||||
}
|
||||
|
||||
dialog.ShowConfirm("Cancel Benchmark?", "The benchmark is still running. Cancel it now?", func(ok bool) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
cancel()
|
||||
s.showMainMenu()
|
||||
}, s.window)
|
||||
},
|
||||
utils.MustHex("#4CE870"),
|
||||
utils.MustHex("#1E1E1E"),
|
||||
|
|
@ -1754,12 +1781,13 @@ func (s *appState) showBenchmark() {
|
|||
|
||||
// Run benchmark in background
|
||||
go func() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Generate test video
|
||||
view.UpdateProgress(0, 100, "Generating test video", "")
|
||||
testPath, err := suite.GenerateTestVideo(ctx, 30)
|
||||
if err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return
|
||||
}
|
||||
logging.Debug(logging.CatSystem, "failed to generate test video: %v", err)
|
||||
dialog.ShowError(fmt.Errorf("failed to generate test video: %w", err), s.window)
|
||||
s.showMainMenu()
|
||||
|
|
@ -1780,6 +1808,9 @@ func (s *appState) showBenchmark() {
|
|||
// Run benchmark suite
|
||||
err = suite.RunFullSuite(ctx, availableEncoders)
|
||||
if err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return
|
||||
}
|
||||
logging.Debug(logging.CatSystem, "benchmark failed: %v", err)
|
||||
dialog.ShowError(fmt.Errorf("benchmark failed: %w", err), s.window)
|
||||
s.showMainMenu()
|
||||
|
|
@ -1793,6 +1824,7 @@ func (s *appState) showBenchmark() {
|
|||
|
||||
// Mark complete
|
||||
view.SetComplete()
|
||||
benchComplete.Store(true)
|
||||
|
||||
// Get recommendation
|
||||
encoder, preset, rec := suite.GetRecommendation()
|
||||
|
|
@ -1807,10 +1839,13 @@ func (s *appState) showBenchmark() {
|
|||
|
||||
// Show results dialog with option to apply
|
||||
go func() {
|
||||
// Detect hardware info for display
|
||||
hwInfo := sysinfo.Detect()
|
||||
allResults := suite.Results // Show all results, not just top 10
|
||||
resultsView := ui.BuildBenchmarkResultsView(
|
||||
allResults,
|
||||
rec,
|
||||
hwInfo,
|
||||
func() {
|
||||
// Apply recommended settings
|
||||
s.applyBenchmarkRecommendation(encoder, preset)
|
||||
|
|
@ -1876,6 +1911,10 @@ func (s *appState) saveBenchmarkRun(results []benchmark.Result, encoder, preset
|
|||
hwAccel = "none"
|
||||
}
|
||||
|
||||
// Detect hardware info
|
||||
hwInfo := sysinfo.Detect()
|
||||
logging.Debug(logging.CatSystem, "detected hardware: %s", hwInfo.Summary())
|
||||
|
||||
// Load existing config
|
||||
cfg, err := loadBenchmarkConfig()
|
||||
if err != nil {
|
||||
|
|
@ -1891,6 +1930,7 @@ func (s *appState) saveBenchmarkRun(results []benchmark.Result, encoder, preset
|
|||
RecommendedPreset: preset,
|
||||
RecommendedHWAccel: hwAccel,
|
||||
RecommendedFPS: fps,
|
||||
HardwareInfo: hwInfo,
|
||||
}
|
||||
|
||||
// Add to history (keep last 10 runs)
|
||||
|
|
@ -1991,6 +2031,7 @@ func (s *appState) showBenchmarkHistory() {
|
|||
resultsView := ui.BuildBenchmarkResultsView(
|
||||
run.Results,
|
||||
rec,
|
||||
run.HardwareInfo,
|
||||
func() {
|
||||
// Apply this recommendation
|
||||
s.applyBenchmarkRecommendation(run.RecommendedEncoder, run.RecommendedPreset)
|
||||
|
|
@ -5786,9 +5827,9 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
|||
"Target Size (Calculate from file size)",
|
||||
}
|
||||
bitrateModeMap := map[string]string{
|
||||
"CRF (Constant Rate Factor)": "CRF",
|
||||
"CBR (Constant Bitrate)": "CBR",
|
||||
"VBR (Variable Bitrate)": "VBR",
|
||||
"CRF (Constant Rate Factor)": "CRF",
|
||||
"CBR (Constant Bitrate)": "CBR",
|
||||
"VBR (Variable Bitrate)": "VBR",
|
||||
"Target Size (Calculate from file size)": "Target Size",
|
||||
}
|
||||
reverseMap := map[string]string{
|
||||
|
|
@ -5857,18 +5898,11 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
|||
|
||||
presets := []bitratePreset{
|
||||
{Label: "Manual", Bitrate: "", Codec: ""},
|
||||
{Label: "AV1 1080p - 1200k (smallest)", Bitrate: "1200k", Codec: "AV1"},
|
||||
{Label: "AV1 1080p - 1400k (sweet spot)", Bitrate: "1400k", Codec: "AV1"},
|
||||
{Label: "AV1 1080p - 1800k (headroom)", Bitrate: "1800k", Codec: "AV1"},
|
||||
{Label: "H.265 1080p - 2000k (balanced)", Bitrate: "2000k", Codec: "H.265"},
|
||||
{Label: "H.265 1080p - 2400k (noisy sources)", Bitrate: "2400k", Codec: "H.265"},
|
||||
{Label: "AV1 1440p - 2600k (balanced)", Bitrate: "2600k", Codec: "AV1"},
|
||||
{Label: "H.265 1440p - 3200k (balanced)", Bitrate: "3200k", Codec: "H.265"},
|
||||
{Label: "H.265 1440p - 4000k (noisy sources)", Bitrate: "4000k", Codec: "H.265"},
|
||||
{Label: "AV1 4K - 5M (balanced)", Bitrate: "5000k", Codec: "AV1"},
|
||||
{Label: "H.265 4K - 6M (balanced)", Bitrate: "6000k", Codec: "H.265"},
|
||||
{Label: "AV1 4K - 7M (archive)", Bitrate: "7000k", Codec: "AV1"},
|
||||
{Label: "H.265 4K - 9M (fast/Topaz)", Bitrate: "9000k", Codec: "H.265"},
|
||||
{Label: "1.5 Mbps - Low Quality", Bitrate: "1500k", Codec: ""},
|
||||
{Label: "2.5 Mbps - Medium Quality", Bitrate: "2500k", Codec: ""},
|
||||
{Label: "4.0 Mbps - Good Quality", Bitrate: "4000k", Codec: ""},
|
||||
{Label: "6.0 Mbps - High Quality", Bitrate: "6000k", Codec: ""},
|
||||
{Label: "8.0 Mbps - Very High Quality", Bitrate: "8000k", Codec: ""},
|
||||
}
|
||||
|
||||
bitratePresetLookup := make(map[string]bitratePreset)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user