diff --git a/author_module.go b/author_module.go index 9e8c959..ae93e5c 100644 --- a/author_module.go +++ b/author_module.go @@ -406,6 +406,8 @@ func buildChaptersTab(state *appState) fyne.CanvasObject { sourceLabel.SetText("Source: Embedded chapters") case "scenes": sourceLabel.SetText("Source: Scene detection") + case "videots": + sourceLabel.SetText("Source: VIDEO_TS chapters") default: sourceLabel.SetText("Source: Chapters") } @@ -981,6 +983,8 @@ func (s *appState) authorChapterSummary() (int, string) { return len(s.authorChapters), "Embedded Chapters" case "scenes": return len(s.authorChapters), "Scene Chapters" + case "videots": + return len(s.authorChapters), "VIDEO_TS Chapters" default: return len(s.authorChapters), "Chapters" } @@ -1076,6 +1080,28 @@ func (s *appState) loadEmbeddedChapters(path string) { } } +func (s *appState) loadVideoTSChapters(videoTSPath string) { + chapters, err := extractChaptersFromVideoTS(videoTSPath) + if err != nil || len(chapters) == 0 { + // No chapters found, clear if previously set + if s.authorChapterSource == "videots" { + s.authorChapters = nil + s.authorChapterSource = "" + s.updateAuthorSummary() + if s.authorChaptersRefresh != nil { + s.authorChaptersRefresh() + } + } + return + } + s.authorChapters = chapters + s.authorChapterSource = "videots" + s.updateAuthorSummary() + if s.authorChaptersRefresh != nil { + s.authorChaptersRefresh() + } +} + func chaptersFromClips(clips []authorClip) []authorChapter { if len(clips) == 0 { return nil @@ -1222,6 +1248,27 @@ func extractChaptersFromFile(path string) ([]authorChapter, error) { return chapters, nil } +func extractChaptersFromVideoTS(videoTSPath string) ([]authorChapter, error) { + // Try to find the main title VOB files + // Usually VTS_01_1.VOB contains the main content + vobFiles, err := filepath.Glob(filepath.Join(videoTSPath, "VTS_*_1.VOB")) + if err != nil || len(vobFiles) == 0 { + return nil, fmt.Errorf("no VOB files found in VIDEO_TS") + } + + // Sort to get the first title set (usually the main feature) + sort.Strings(vobFiles) + mainVOB := vobFiles[0] + + // Try to extract chapters from the main VOB using ffprobe + chapters, err := extractChaptersFromFile(mainVOB) + if err != nil { + return nil, err + } + + return chapters, nil +} + func chaptersToDVDAuthor(chapters []authorChapter) string { if len(chapters) == 0 { return "" diff --git a/main.go b/main.go index 6498625..a342b3a 100644 --- a/main.go +++ b/main.go @@ -10483,6 +10483,7 @@ func (s *appState) handleDrop(pos fyne.Position, items []fyne.URI) { s.authorClips = nil s.authorFile = nil s.authorOutputType = "iso" + s.loadVideoTSChapters(videoTSPath) s.showAuthorView() return }