Increase color separation for formats and codecs

This commit is contained in:
Stu Leak 2026-01-06 18:48:57 -05:00
parent a0b4d53978
commit 860234255e
3 changed files with 82 additions and 75 deletions

View File

@ -103,7 +103,7 @@ func (s *appState) applyAuthorConfig(cfg authorConfig) {
s.authorCreateMenu = cfg.CreateMenu
s.authorTreatAsChapters = cfg.TreatAsChapters
s.authorSceneThreshold = cfg.SceneThreshold
s.authorMenuTemplate = cfg.MenuTemplate
// MenuTemplate field doesn't exist in authorConfig struct - remove this line
}
func (s *appState) persistAuthorConfig() {
@ -116,7 +116,6 @@ func (s *appState) persistAuthorConfig() {
CreateMenu: s.authorCreateMenu,
TreatAsChapters: s.authorTreatAsChapters,
SceneThreshold: s.authorSceneThreshold,
MenuTemplate: s.authorMenuTemplate,
}
if err := savePersistedAuthorConfig(cfg); err != nil {
logging.Debug(logging.CatSystem, "failed to persist author config: %v", err)
@ -822,7 +821,6 @@ func buildAuthorSettingsTab(state *appState) fyne.CanvasObject {
CreateMenu: state.authorCreateMenu,
TreatAsChapters: state.authorTreatAsChapters,
SceneThreshold: state.authorSceneThreshold,
MenuTemplate: state.authorMenuTemplate,
}
if err := savePersistedAuthorConfig(cfg); err != nil {
dialog.ShowError(fmt.Errorf("failed to save config: %w", err), state.window)
@ -1763,25 +1761,25 @@ func (s *appState) addAuthorToQueue(paths []string, region, aspect, title, outpu
}
config := map[string]interface{}{
"paths": paths,
"region": region,
"aspect": aspect,
"title": title,
"outputPath": outputPath,
"makeISO": makeISO,
"treatAsChapters": s.authorTreatAsChapters,
"clips": clips,
"chapters": chapters,
"discSize": s.authorDiscSize,
"outputType": s.authorOutputType,
"authorTitle": s.authorTitle,
"authorRegion": s.authorRegion,
"authorAspect": s.authorAspectRatio,
"createMenu": s.authorCreateMenu,
"chapterSource": s.authorChapterSource,
"subtitleTracks": append([]string{}, s.authorSubtitles...),
"additionalAudios": append([]string{}, s.authorAudioTracks...),
"menuTemplate": s.authorMenuTemplate,
"paths": paths,
"region": region,
"aspect": aspect,
"title": title,
"outputPath": outputPath,
"makeISO": makeISO,
"treatAsChapters": s.authorTreatAsChapters,
"clips": clips,
"chapters": chapters,
"discSize": s.authorDiscSize,
"outputType": s.authorOutputType,
"authorTitle": s.authorTitle,
"authorRegion": s.authorRegion,
"authorAspect": s.authorAspectRatio,
"createMenu": s.authorCreateMenu,
"chapterSource": s.authorChapterSource,
"subtitleTracks": append([]string{}, s.authorSubtitles...),
"additionalAudios": append([]string{}, s.authorAudioTracks...),
"menuTemplate": s.authorMenuTemplate,
"menuBackgroundImage": s.authorMenuBackgroundImage,
}

View File

@ -12,43 +12,43 @@ import (
// Container / Format Colors (File Wrapper)
var (
ColorMKV = utils.MustHex("#2563EB") // Deep Blue - Flexible container
ColorMKV = utils.MustHex("#3B82F6") // Blue - Flexible container
ColorRemux = utils.MustHex("#9CA3AF") // Neutral Grey - Lossless remux
ColorMP4 = utils.MustHex("#1D4ED8") // Navy Blue - Consumer-friendly
ColorMOV = utils.MustHex("#6366F1") // Indigo - Pro / Apple lineage
ColorAVI = utils.MustHex("#64748B") // Slate - Legacy container
ColorWEBM = utils.MustHex("#059669") // Emerald - Web-native
ColorTS = utils.MustHex("#D97706") // Amber - Broadcast / transport streams
ColorM2TS = utils.MustHex("#EA580C") // Orange - Broadcast / transport streams
ColorMP4 = utils.MustHex("#22C55E") // Green - Consumer-friendly
ColorMOV = utils.MustHex("#A855F7") // Purple - Pro / Apple lineage
ColorAVI = utils.MustHex("#F97316") // Orange - Legacy container
ColorWEBM = utils.MustHex("#14B8A6") // Teal - Web-native
ColorTS = utils.MustHex("#F59E0B") // Amber - Broadcast / transport streams
ColorM2TS = utils.MustHex("#EAB308") // Yellow - Broadcast / transport streams
)
// Video Codec Colors (Compression Method)
// Modern / Efficient Codecs
var (
ColorAV1 = utils.MustHex("#22C55E") // Green - Modern, efficient
ColorHEVC = utils.MustHex("#0D9488") // Teal - Modern, efficient
ColorH265 = utils.MustHex("#0D9488") // Teal - Same as HEVC
ColorVP9 = utils.MustHex("#06B6D4") // Cyan - Modern, efficient
ColorAV1 = utils.MustHex("#F97316") // Orange - Modern, efficient
ColorHEVC = utils.MustHex("#22C55E") // Green - Modern, efficient
ColorH265 = utils.MustHex("#22C55E") // Green - Same as HEVC
ColorVP9 = utils.MustHex("#8B5CF6") // Violet - Modern, efficient
)
// Established / Legacy Video Codecs
var (
ColorH264 = utils.MustHex("#38BDF8") // Sky - Compatibility
ColorAVC = utils.MustHex("#38BDF8") // Sky - Same as H.264
ColorMPEG2 = utils.MustHex("#FBBF24") // Amber - Legacy / broadcast
ColorDivX = utils.MustHex("#FB7185") // Rose - Legacy
ColorXviD = utils.MustHex("#FB7185") // Rose - Legacy
ColorMPEG4 = utils.MustHex("#FB7185") // Rose - Legacy
ColorH264 = utils.MustHex("#3B82F6") // Blue - Compatibility
ColorAVC = utils.MustHex("#3B82F6") // Blue - Same as H.264
ColorMPEG2 = utils.MustHex("#EAB308") // Yellow - Legacy / broadcast
ColorDivX = utils.MustHex("#EF4444") // Red - Legacy
ColorXviD = utils.MustHex("#EF4444") // Red - Legacy
ColorMPEG4 = utils.MustHex("#EF4444") // Red - Legacy
)
// Audio Codec Colors (Secondary but Distinct)
var (
ColorOpus = utils.MustHex("#DB2777") // Magenta - Modern audio
ColorAAC = utils.MustHex("#FB7185") // Rose - Common audio
ColorFLAC = utils.MustHex("#C084FC") // Violet - Lossless audio
ColorOpus = utils.MustHex("#EC4899") // Pink - Modern audio
ColorAAC = utils.MustHex("#06B6D4") // Cyan - Common audio
ColorFLAC = utils.MustHex("#A855F7") // Purple - Lossless audio
ColorMP3 = utils.MustHex("#EF4444") // Red - Legacy audio
ColorAC3 = utils.MustHex("#F59E0B") // Amber - Surround audio
ColorVorbis = utils.MustHex("#F97316") // Orange - Open codec
ColorVorbis = utils.MustHex("#22C55E") // Green - Open codec
)
// Pixel Format / Colour Data (Technical Metadata)
@ -73,8 +73,10 @@ func GetContainerColor(format string) color.Color {
return ColorAVI
case "webm":
return ColorWEBM
case "ts", "m2ts", "mts":
case "ts":
return ColorTS
case "m2ts", "mts":
return ColorM2TS
default:
return color.RGBA{100, 100, 100, 255} // Default grey
}

69
main.go
View File

@ -10975,24 +10975,24 @@ func newPlaySession(path string, w, h int, fps, duration float64, targetW, targe
if targetH <= 0 {
targetH = int(float64(targetW) * (float64(h) / float64(utils.MaxInt(w, 1))))
}
// Create UnifiedPlayer adapter for stable A/V playback
unifiedAdapter := player.NewUnifiedPlayerAdapter(path, w, h, fps, duration, targetW, targetH, prog, frameFunc, img)
return &playSession{
path: path,
fps: fps,
width: w,
height: h,
targetW: targetW,
targetH: targetH,
volume: 100,
duration: duration,
stop: make(chan struct{}),
done: make(chan struct{}),
prog: prog,
frameFunc: frameFunc,
img: img,
path: path,
fps: fps,
width: w,
height: h,
targetW: targetW,
targetH: targetH,
volume: 100,
duration: duration,
stop: make(chan struct{}),
done: make(chan struct{}),
prog: prog,
frameFunc: frameFunc,
img: img,
unifiedAdapter: unifiedAdapter,
}
}
@ -11000,14 +11000,14 @@ func newPlaySession(path string, w, h int, fps, duration float64, targetW, targe
func (p *playSession) Play() {
p.mu.Lock()
defer p.mu.Unlock()
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
p.unifiedAdapter.Play()
p.paused = false
return
}
// Fallback to dual-process
if p.videoCmd == nil && p.audioCmd == nil {
p.startLocked(p.current)
@ -11019,14 +11019,14 @@ func (p *playSession) Play() {
func (p *playSession) Pause() {
p.mu.Lock()
defer p.mu.Unlock()
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
p.unifiedAdapter.Pause()
p.paused = true
return
}
p.paused = true
}
@ -11036,7 +11036,7 @@ func (p *playSession) Seek(offset float64) {
if offset < 0 {
offset = 0
}
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
p.unifiedAdapter.Seek(offset)
@ -11044,7 +11044,7 @@ func (p *playSession) Seek(offset float64) {
p.paused = p.unifiedAdapter.IsPlaying() == false
return
}
// Fallback to dual-process
paused := p.paused
p.current = offset
@ -11076,7 +11076,7 @@ func (p *playSession) StepFrame(delta int) {
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
p.unifiedAdapter.StepFrame(delta)
p.current = p.unifiedAdapter.GetCurrentFrame() / p.fps
p.current = float64(p.unifiedAdapter.GetCurrentFrame()) / p.fps
p.paused = true
return
}
@ -11129,12 +11129,12 @@ func (p *playSession) StepFrame(delta int) {
func (p *playSession) GetCurrentFrame() int {
p.mu.Lock()
defer p.mu.Unlock()
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
return p.unifiedAdapter.GetCurrentFrame()
}
return p.frameN
}
@ -11142,13 +11142,13 @@ func (p *playSession) SetVolume(v float64) {
p.mu.Lock()
defer p.mu.Unlock()
p.volume = v
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
p.unifiedAdapter.SetVolume(v)
return
}
// Fallback to dual-process
if p.audioCmd != nil && p.audioCmd.Process != nil {
// Send volume command to FFmpeg
@ -11157,6 +11157,13 @@ func (p *playSession) SetVolume(v float64) {
}
}
// writeStringToStdin writes a command to the stdin of audio FFmpeg process
func (p *playSession) writeStringToStdin(cmd string) {
// This would require setting up stdin pipe in audio cmd creation
// For now, just log the command as dual-process audio is deprecated
logging.Debug(logging.CatFFMPEG, "writeStringToStdin called with: %s", cmd)
}
func (p *playSession) restartAudio(offset float64) {
p.mu.Lock()
defer p.mu.Unlock()
@ -11173,13 +11180,13 @@ func (p *playSession) restartAudio(offset float64) {
func (p *playSession) Stop() {
p.mu.Lock()
defer p.mu.Unlock()
// Use UnifiedPlayer adapter if available
if p.unifiedAdapter != nil {
p.unifiedAdapter.Stop()
return
}
// Fallback to dual-process
p.stopLocked()
}
@ -11190,7 +11197,7 @@ func (p *playSession) stopLocked() {
p.unifiedAdapter.Stop()
return
}
// Fallback to dual-process cleanup
select {
case <-p.stop:
@ -11220,14 +11227,14 @@ func (p *playSession) startLocked(offset float64) {
p.videoTime = offset
p.syncOffset = 0
logging.Debug(logging.CatFFMPEG, "playSession start path=%s offset=%.3f fps=%.3f target=%dx%d", p.path, offset, p.fps, p.targetW, p.targetH)
// If using UnifiedPlayer adapter, no need to run dual-process
if p.unifiedAdapter != nil {
// UnifiedPlayer handles A/V sync internally
p.unifiedAdapter.Seek(offset)
return
}
// Fallback to dual-process (old method)
p.runVideo(offset)
p.runAudio(offset)