Simplify merge format dropdown with user-friendly options
Added clearer format descriptions: - "Fast Merge (No Re-encoding)" instead of "MKV (Copy streams)" - "Lossless MKV (Best Quality)" - new option with slow preset, CRF 18, FLAC audio - "High Quality MP4 (H.264/H.265)" instead of technical codec names - "DVD Format" with conditional region/aspect selectors - "Blu-ray Format" instead of "Blu-ray (H.264)" DVD Format improvements: - When "DVD Format" is selected, shows Region (NTSC/PAL) and Aspect (16:9/4:3) options - Options hidden for other formats - Stored in state and passed to merge job config - Updated execution to use DVD region/aspect settings Maintains backward compatibility with legacy DVD format codes.
This commit is contained in:
parent
f6fe8bb61b
commit
f653b2a4ce
114
main.go
114
main.go
|
|
@ -617,6 +617,8 @@ type appState struct {
|
||||||
mergeKeepAll bool
|
mergeKeepAll bool
|
||||||
mergeCodecMode string
|
mergeCodecMode string
|
||||||
mergeChapters bool
|
mergeChapters bool
|
||||||
|
mergeDVDRegion string // "NTSC" or "PAL"
|
||||||
|
mergeDVDAspect string // "16:9" or "4:3"
|
||||||
|
|
||||||
// Thumbnail module state
|
// Thumbnail module state
|
||||||
thumbFile *videoSource
|
thumbFile *videoSource
|
||||||
|
|
@ -2010,6 +2012,12 @@ func (s *appState) showMergeView() {
|
||||||
if s.mergeFormat == "" {
|
if s.mergeFormat == "" {
|
||||||
s.mergeFormat = "mkv-copy"
|
s.mergeFormat = "mkv-copy"
|
||||||
}
|
}
|
||||||
|
if s.mergeDVDRegion == "" {
|
||||||
|
s.mergeDVDRegion = "NTSC"
|
||||||
|
}
|
||||||
|
if s.mergeDVDAspect == "" {
|
||||||
|
s.mergeDVDAspect = "16:9"
|
||||||
|
}
|
||||||
|
|
||||||
backBtn := widget.NewButton("< MERGE", func() {
|
backBtn := widget.NewButton("< MERGE", func() {
|
||||||
s.showMainMenu()
|
s.showMainMenu()
|
||||||
|
|
@ -2150,22 +2158,22 @@ func (s *appState) showMergeView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
formatMap := map[string]string{
|
formatMap := map[string]string{
|
||||||
"MKV (Copy streams)": "mkv-copy",
|
"Fast Merge (No Re-encoding)": "mkv-copy",
|
||||||
"MKV (H.264)": "mkv-h264",
|
"Lossless MKV (Best Quality)": "mkv-lossless",
|
||||||
"MKV (H.265)": "mkv-h265",
|
"High Quality MP4 (H.264)": "mp4-h264",
|
||||||
"MP4 (H.264)": "mp4-h264",
|
"High Quality MP4 (H.265)": "mp4-h265",
|
||||||
"MP4 (H.265)": "mp4-h265",
|
"DVD Format": "dvd",
|
||||||
"DVD NTSC 16:9": "dvd-ntsc-169",
|
"Blu-ray Format": "bd-h264",
|
||||||
"DVD NTSC 4:3": "dvd-ntsc-43",
|
|
||||||
"DVD PAL 16:9": "dvd-pal-169",
|
|
||||||
"DVD PAL 4:3": "dvd-pal-43",
|
|
||||||
"Blu-ray (H.264)": "bd-h264",
|
|
||||||
}
|
}
|
||||||
var formatKeys []string
|
// Maintain order for dropdown
|
||||||
for k := range formatMap {
|
formatKeys := []string{
|
||||||
formatKeys = append(formatKeys, k)
|
"Fast Merge (No Re-encoding)",
|
||||||
|
"Lossless MKV (Best Quality)",
|
||||||
|
"High Quality MP4 (H.264)",
|
||||||
|
"High Quality MP4 (H.265)",
|
||||||
|
"DVD Format",
|
||||||
|
"Blu-ray Format",
|
||||||
}
|
}
|
||||||
slices.Sort(formatKeys)
|
|
||||||
|
|
||||||
keepAllCheck := widget.NewCheck("Keep all audio/subtitle tracks", func(v bool) {
|
keepAllCheck := widget.NewCheck("Keep all audio/subtitle tracks", func(v bool) {
|
||||||
s.mergeKeepAll = v
|
s.mergeKeepAll = v
|
||||||
|
|
@ -2198,19 +2206,49 @@ func (s *appState) showMergeView() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DVD-specific options
|
||||||
|
dvdRegionSelect := widget.NewSelect([]string{"NTSC", "PAL"}, func(val string) {
|
||||||
|
s.mergeDVDRegion = val
|
||||||
|
})
|
||||||
|
dvdRegionSelect.SetSelected(s.mergeDVDRegion)
|
||||||
|
|
||||||
|
dvdAspectSelect := widget.NewSelect([]string{"16:9", "4:3"}, func(val string) {
|
||||||
|
s.mergeDVDAspect = val
|
||||||
|
})
|
||||||
|
dvdAspectSelect.SetSelected(s.mergeDVDAspect)
|
||||||
|
|
||||||
|
dvdOptionsRow := container.NewHBox(
|
||||||
|
widget.NewLabel("Region:"),
|
||||||
|
dvdRegionSelect,
|
||||||
|
widget.NewLabel("Aspect:"),
|
||||||
|
dvdAspectSelect,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Container for DVD options (can be shown/hidden)
|
||||||
|
dvdOptionsContainer := container.NewVBox(dvdOptionsRow)
|
||||||
|
|
||||||
// Create format selector (after outputEntry and updateOutputExt are defined)
|
// Create format selector (after outputEntry and updateOutputExt are defined)
|
||||||
formatSelect := widget.NewSelect(formatKeys, func(val string) {
|
formatSelect := widget.NewSelect(formatKeys, func(val string) {
|
||||||
s.mergeFormat = formatMap[val]
|
s.mergeFormat = formatMap[val]
|
||||||
|
|
||||||
|
// Show/hide DVD options based on selection
|
||||||
|
if s.mergeFormat == "dvd" {
|
||||||
|
dvdOptionsContainer.Show()
|
||||||
|
} else {
|
||||||
|
dvdOptionsContainer.Hide()
|
||||||
|
}
|
||||||
|
|
||||||
// Set default output path if not set
|
// Set default output path if not set
|
||||||
if s.mergeOutput == "" && len(s.mergeClips) > 0 {
|
if s.mergeOutput == "" && len(s.mergeClips) > 0 {
|
||||||
dir := filepath.Dir(s.mergeClips[0].Path)
|
dir := filepath.Dir(s.mergeClips[0].Path)
|
||||||
ext := getExtForFormat(s.mergeFormat)
|
ext := getExtForFormat(s.mergeFormat)
|
||||||
basename := "merged"
|
basename := "merged"
|
||||||
if strings.HasPrefix(s.mergeFormat, "dvd") {
|
if strings.HasPrefix(s.mergeFormat, "dvd") || s.mergeFormat == "dvd" {
|
||||||
basename = "merged-dvd"
|
basename = "merged-dvd"
|
||||||
} else if strings.HasPrefix(s.mergeFormat, "bd") {
|
} else if strings.HasPrefix(s.mergeFormat, "bd") {
|
||||||
basename = "merged-bd"
|
basename = "merged-bd"
|
||||||
|
} else if s.mergeFormat == "mkv-lossless" {
|
||||||
|
basename = "merged-lossless"
|
||||||
}
|
}
|
||||||
s.mergeOutput = filepath.Join(dir, basename+ext)
|
s.mergeOutput = filepath.Join(dir, basename+ext)
|
||||||
outputEntry.SetText(s.mergeOutput)
|
outputEntry.SetText(s.mergeOutput)
|
||||||
|
|
@ -2226,6 +2264,13 @@ func (s *appState) showMergeView() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize DVD options visibility
|
||||||
|
if s.mergeFormat == "dvd" {
|
||||||
|
dvdOptionsContainer.Show()
|
||||||
|
} else {
|
||||||
|
dvdOptionsContainer.Hide()
|
||||||
|
}
|
||||||
|
|
||||||
browseOut := widget.NewButton("Browse", func() {
|
browseOut := widget.NewButton("Browse", func() {
|
||||||
dialog.ShowFileSave(func(writer fyne.URIWriteCloser, err error) {
|
dialog.ShowFileSave(func(writer fyne.URIWriteCloser, err error) {
|
||||||
if err != nil || writer == nil {
|
if err != nil || writer == nil {
|
||||||
|
|
@ -2292,6 +2337,7 @@ func (s *appState) showMergeView() {
|
||||||
widget.NewLabelWithStyle("Output Options", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
widget.NewLabelWithStyle("Output Options", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
||||||
widget.NewLabel("Format"),
|
widget.NewLabel("Format"),
|
||||||
formatSelect,
|
formatSelect,
|
||||||
|
dvdOptionsContainer,
|
||||||
keepAllCheck,
|
keepAllCheck,
|
||||||
chapterCheck,
|
chapterCheck,
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
|
|
@ -2358,6 +2404,8 @@ func (s *appState) addMergeToQueue(startNow bool) error {
|
||||||
"chapters": s.mergeChapters,
|
"chapters": s.mergeChapters,
|
||||||
"codecMode": s.mergeCodecMode,
|
"codecMode": s.mergeCodecMode,
|
||||||
"outputPath": s.mergeOutput,
|
"outputPath": s.mergeOutput,
|
||||||
|
"dvdRegion": s.mergeDVDRegion,
|
||||||
|
"dvdAspect": s.mergeDVDAspect,
|
||||||
}
|
}
|
||||||
|
|
||||||
job := &queue.Job{
|
job := &queue.Job{
|
||||||
|
|
@ -2503,7 +2551,35 @@ func (s *appState) executeMergeJob(ctx context.Context, job *queue.Job, progress
|
||||||
|
|
||||||
// Output profile
|
// Output profile
|
||||||
switch format {
|
switch format {
|
||||||
|
case "dvd":
|
||||||
|
// Get DVD-specific settings from config
|
||||||
|
dvdRegion, _ := cfg["dvdRegion"].(string)
|
||||||
|
dvdAspect, _ := cfg["dvdAspect"].(string)
|
||||||
|
if dvdRegion == "" {
|
||||||
|
dvdRegion = "NTSC"
|
||||||
|
}
|
||||||
|
if dvdAspect == "" {
|
||||||
|
dvdAspect = "16:9"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force MPEG-2 / AC-3
|
||||||
|
args = append(args,
|
||||||
|
"-c:v", "mpeg2video",
|
||||||
|
"-c:a", "ac3",
|
||||||
|
"-b:a", "192k",
|
||||||
|
"-max_muxing_queue_size", "1024",
|
||||||
|
)
|
||||||
|
|
||||||
|
if dvdRegion == "NTSC" {
|
||||||
|
args = append(args, "-vf", "scale=720:480,setsar=1", "-r", "30000/1001", "-pix_fmt", "yuv420p", "-aspect", dvdAspect)
|
||||||
|
args = append(args, "-target", "ntsc-dvd")
|
||||||
|
} else {
|
||||||
|
args = append(args, "-vf", "scale=720:576,setsar=1", "-r", "25", "-pix_fmt", "yuv420p", "-aspect", dvdAspect)
|
||||||
|
args = append(args, "-target", "pal-dvd")
|
||||||
|
}
|
||||||
|
|
||||||
case "dvd-ntsc-169", "dvd-ntsc-43", "dvd-pal-169", "dvd-pal-43":
|
case "dvd-ntsc-169", "dvd-ntsc-43", "dvd-pal-169", "dvd-pal-43":
|
||||||
|
// Legacy DVD formats for backward compatibility
|
||||||
// Force MPEG-2 / AC-3
|
// Force MPEG-2 / AC-3
|
||||||
args = append(args,
|
args = append(args,
|
||||||
"-c:v", "mpeg2video",
|
"-c:v", "mpeg2video",
|
||||||
|
|
@ -2549,6 +2625,14 @@ func (s *appState) executeMergeJob(ctx context.Context, job *queue.Job, progress
|
||||||
"-crf", "28",
|
"-crf", "28",
|
||||||
"-c:a", "copy",
|
"-c:a", "copy",
|
||||||
)
|
)
|
||||||
|
case "mkv-lossless":
|
||||||
|
// Lossless MKV with best quality settings
|
||||||
|
args = append(args,
|
||||||
|
"-c:v", "libx264",
|
||||||
|
"-preset", "slow",
|
||||||
|
"-crf", "18",
|
||||||
|
"-c:a", "flac",
|
||||||
|
)
|
||||||
case "mp4-h264":
|
case "mp4-h264":
|
||||||
args = append(args,
|
args = append(args,
|
||||||
"-c:v", "libx264",
|
"-c:v", "libx264",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user