Add upscale quality preset to prevent runaway bitrates
This commit is contained in:
parent
93ec8c7b15
commit
1d18ab2db2
|
|
@ -49,7 +49,7 @@ The Upscale module raises video resolution using traditional FFmpeg scaling or A
|
|||
## Traditional Scaling
|
||||
- **Algorithms:** Lanczos, Bicubic, Spline, Bilinear.
|
||||
- **Target:** Match Source, 2x/4x, or fixed resolutions (720p → 8K).
|
||||
- **Output:** Lossless MKV by default (copy audio).
|
||||
- **Output Quality:** Lossless (CRF 0), Near-lossless (CRF 16, default), High (CRF 18).
|
||||
|
||||
## Filters and Frame Rate
|
||||
- Filters configured in the Filters module can be applied before upscaling.
|
||||
|
|
|
|||
40
main.go
40
main.go
|
|
@ -824,6 +824,7 @@ type appState struct {
|
|||
upscaleTargetRes string // 720p, 1080p, 1440p, 4K, 8K, Custom
|
||||
upscaleCustomWidth int // For custom resolution
|
||||
upscaleCustomHeight int // For custom resolution
|
||||
upscaleQualityPreset string // Lossless, Near-lossless, High
|
||||
upscaleAIEnabled bool // Use AI upscaling if available
|
||||
upscaleAIModel string // realesrgan, realesrgan-anime, none
|
||||
upscaleAIAvailable bool // Runtime detection
|
||||
|
|
@ -4482,6 +4483,7 @@ func (s *appState) executeUpscaleJob(ctx context.Context, job *queue.Job, progre
|
|||
frameRate, _ := cfg["frameRate"].(string)
|
||||
useMotionInterp, _ := cfg["useMotionInterpolation"].(bool)
|
||||
sourceFrameRate := toFloat(cfg["sourceFrameRate"])
|
||||
qualityPreset, _ := cfg["qualityPreset"].(string)
|
||||
|
||||
if progressCallback != nil {
|
||||
progressCallback(0)
|
||||
|
|
@ -4502,6 +4504,16 @@ func (s *appState) executeUpscaleJob(ctx context.Context, job *queue.Job, progre
|
|||
}
|
||||
}
|
||||
|
||||
crfValue := 16
|
||||
switch qualityPreset {
|
||||
case "Lossless (CRF 0)":
|
||||
crfValue = 0
|
||||
case "High (CRF 18)":
|
||||
crfValue = 18
|
||||
case "Near-lossless (CRF 16)":
|
||||
crfValue = 16
|
||||
}
|
||||
|
||||
// Build filter chain
|
||||
var baseFilters []string
|
||||
|
||||
|
|
@ -4749,7 +4761,7 @@ func (s *appState) executeUpscaleJob(ctx context.Context, job *queue.Job, progre
|
|||
reassembleArgs = append(reassembleArgs,
|
||||
"-c:v", "libx264",
|
||||
"-preset", "slow",
|
||||
"-crf", "0",
|
||||
"-crf", strconv.Itoa(crfValue),
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-c:a", "copy",
|
||||
"-shortest",
|
||||
|
|
@ -4808,7 +4820,7 @@ func (s *appState) executeUpscaleJob(ctx context.Context, job *queue.Job, progre
|
|||
args = append(args,
|
||||
"-c:v", "libx264",
|
||||
"-preset", "slow",
|
||||
"-crf", "0", // lossless
|
||||
"-crf", strconv.Itoa(crfValue),
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-c:a", "copy",
|
||||
outputPath,
|
||||
|
|
@ -13152,7 +13164,7 @@ func buildFiltersView(state *appState) fyne.CanvasObject {
|
|||
settingsScroll.SetMinSize(fyne.NewSize(350, 400))
|
||||
|
||||
mainContent := container.NewHSplit(
|
||||
container.NewVBox(leftPanel, videoContainer),
|
||||
container.NewVBox(leftPanel, container.NewCenter(videoContainer)),
|
||||
settingsScroll,
|
||||
)
|
||||
mainContent.SetOffset(0.55) // 55% for video preview, 45% for settings
|
||||
|
|
@ -13201,6 +13213,9 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
if state.upscaleFrameRate == "" {
|
||||
state.upscaleFrameRate = "Source"
|
||||
}
|
||||
if state.upscaleQualityPreset == "" {
|
||||
state.upscaleQualityPreset = "Near-lossless (CRF 16)"
|
||||
}
|
||||
if state.upscaleAIPreset == "" {
|
||||
state.upscaleAIPreset = "Balanced"
|
||||
state.upscaleAIScale = 4.0
|
||||
|
|
@ -13332,6 +13347,23 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
sourceResLabel,
|
||||
))
|
||||
|
||||
qualitySelect := widget.NewSelect([]string{
|
||||
"Lossless (CRF 0)",
|
||||
"Near-lossless (CRF 16)",
|
||||
"High (CRF 18)",
|
||||
}, func(s string) {
|
||||
state.upscaleQualityPreset = s
|
||||
})
|
||||
qualitySelect.SetSelected(state.upscaleQualityPreset)
|
||||
|
||||
qualitySection := widget.NewCard("Output Quality", "", container.NewVBox(
|
||||
container.NewGridWithColumns(2,
|
||||
widget.NewLabel("Quality:"),
|
||||
qualitySelect,
|
||||
),
|
||||
widget.NewLabel("Lower CRF = higher quality/larger files"),
|
||||
))
|
||||
|
||||
// Frame Rate Section
|
||||
frameRateLabel := widget.NewLabel(fmt.Sprintf("Frame Rate: %s", state.upscaleFrameRate))
|
||||
frameRateSelect := widget.NewSelect([]string{"Source", "23.976", "24", "25", "29.97", "30", "50", "59.94", "60"}, func(s string) {
|
||||
|
|
@ -13682,6 +13714,7 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
"preserveAR": preserveAspect,
|
||||
"useAI": state.upscaleAIEnabled && state.upscaleAIAvailable,
|
||||
"aiModel": state.upscaleAIModel,
|
||||
"qualityPreset": state.upscaleQualityPreset,
|
||||
"aiBackend": state.upscaleAIBackend,
|
||||
"aiPreset": state.upscaleAIPreset,
|
||||
"aiScale": state.upscaleAIScale,
|
||||
|
|
@ -13751,6 +13784,7 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
settingsPanel := container.NewVBox(
|
||||
traditionalSection,
|
||||
resolutionSection,
|
||||
qualitySection,
|
||||
frameRateSection,
|
||||
aiSection,
|
||||
filterIntegrationSection,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user