Root Folder Cleanup: - Moved all documentation .md files to docs/ folder - Kept only README.md, TODO.md, DONE.md in root - Cleaner project structure for contributors - Better organization of documentation Files Moved to docs/: - BUILD.md, BUILD_AND_RUN.md, CHANGELOG.md - COMPLETION_SUMMARY.md, DVD_IMPLEMENTATION_SUMMARY.md - DVD_USER_GUIDE.md, INSTALLATION.md, INTEGRATION_GUIDE.md - LATEST_UPDATES.md, QUEUE_SYSTEM_GUIDE.md, QUICKSTART.md - TESTING_DEV13.md, TEST_DVD_CONVERSION.md, WINDOWS_SETUP.md DONE.md Updates: - Added dev19 section (2025-12-18) - Documented history sidebar delete button - Documented command preview improvements - Documented format options reorganization - Documented bitrate mode descriptive labels - Documented critical bug fixes (Convert crash, log viewer) - Documented bitrate control improvements TODO.md Updates: - Updated to dev19+ plan - Added "Current Focus: dev19" section - Added AI frame interpolation task (RIFE, FILM, DAIN, CAIN) - Added color space preservation tasks - Reorganized priority structure This establishes dev19 as the current development focus on Convert module cleanup and polish, with clear tracking of completed work and upcoming priorities. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
547 lines
15 KiB
Markdown
547 lines
15 KiB
Markdown
# VideoTools Integration Guide - DVD Support & Queue System
|
||
|
||
## 📋 Executive Summary
|
||
|
||
This guide explains how to integrate the newly implemented **DVD-NTSC encoding system** with the **queue-based batch processing system** in VideoTools.
|
||
|
||
**Status:** ✅ Both systems are complete, tested, and ready for integration.
|
||
|
||
---
|
||
|
||
## 🎯 What's New
|
||
|
||
### 1. **DVD-NTSC Encoding Package** ✨
|
||
Location: `internal/convert/`
|
||
|
||
**Provides:**
|
||
- MPEG-2 video encoding (720×480 @ 29.97fps)
|
||
- AC-3 Dolby Digital audio (48 kHz stereo)
|
||
- Multi-region support (NTSC, PAL, SECAM)
|
||
- Comprehensive validation system
|
||
- FFmpeg command generation
|
||
|
||
**Key Files:**
|
||
- `types.go` - VideoSource, ConvertConfig, FormatOption types
|
||
- `ffmpeg.go` - Codec mapping, video probing
|
||
- `dvd.go` - NTSC-specific encoding and validation
|
||
- `dvd_regions.go` - PAL, SECAM, and multi-region support
|
||
- `presets.go` - Output format definitions
|
||
|
||
### 2. **Queue System** (Already Integrated)
|
||
Location: `internal/queue/queue.go`
|
||
|
||
**Provides:**
|
||
- Job management and prioritization
|
||
- Pause/resume capabilities
|
||
- Real-time progress tracking
|
||
- Thread-safe operations
|
||
- JSON persistence
|
||
|
||
---
|
||
|
||
## 🔌 Integration Points
|
||
|
||
### Point 1: Format Selection UI
|
||
|
||
**Current State (main.go, line ~1394):**
|
||
```go
|
||
var formatLabels []string
|
||
for _, opt := range formatOptions { // Hardcoded in main.go
|
||
formatLabels = append(formatLabels, opt.Label)
|
||
}
|
||
formatSelect := widget.NewSelect(formatLabels, func(value string) {
|
||
for _, opt := range formatOptions {
|
||
if opt.Label == value {
|
||
state.convert.SelectedFormat = opt
|
||
outputHint.SetText(fmt.Sprintf("Output file: %s", state.convert.OutputFile()))
|
||
break
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
**After Integration:**
|
||
```go
|
||
// Import the convert package
|
||
import "git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
||
|
||
// Use FormatOptions from convert package
|
||
var formatLabels []string
|
||
for _, opt := range convert.FormatOptions {
|
||
formatLabels = append(formatLabels, opt.Label)
|
||
}
|
||
formatSelect := widget.NewSelect(formatLabels, func(value string) {
|
||
for _, opt := range convert.FormatOptions {
|
||
if opt.Label == value {
|
||
state.convert.SelectedFormat = opt
|
||
outputHint.SetText(fmt.Sprintf("Output file: %s", state.convert.OutputFile()))
|
||
|
||
// NEW: Show DVD-specific options if DVD selected
|
||
if opt.Ext == ".mpg" {
|
||
showDVDOptions(state) // New function
|
||
}
|
||
break
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
### Point 2: DVD-Specific Options Panel
|
||
|
||
**New UI Component (main.go, after format selection):**
|
||
|
||
```go
|
||
func showDVDOptions(state *appState) {
|
||
// Show DVD-specific controls only when DVD format selected
|
||
dvdPanel := container.NewVBox(
|
||
// Aspect ratio selector
|
||
widget.NewLabel("Aspect Ratio:"),
|
||
widget.NewSelect([]string{"4:3", "16:9"}, func(val string) {
|
||
state.convert.OutputAspect = val
|
||
}),
|
||
|
||
// Interlacing mode
|
||
widget.NewLabel("Interlacing:"),
|
||
widget.NewSelect([]string{"Auto-detect", "Progressive", "Interlaced"}, func(val string) {
|
||
// Store selection
|
||
}),
|
||
|
||
// Region selector
|
||
widget.NewLabel("Region:"),
|
||
widget.NewSelect([]string{"NTSC", "PAL", "SECAM"}, func(val string) {
|
||
// Switch region presets
|
||
var region convert.DVDRegion
|
||
switch val {
|
||
case "NTSC":
|
||
region = convert.DVDNTSCRegionFree
|
||
case "PAL":
|
||
region = convert.DVDPALRegionFree
|
||
case "SECAM":
|
||
region = convert.DVDSECAMRegionFree
|
||
}
|
||
cfg := convert.PresetForRegion(region)
|
||
state.convert = cfg // Update config
|
||
}),
|
||
)
|
||
// Add to UI
|
||
}
|
||
```
|
||
|
||
### Point 3: Validation Before Queue
|
||
|
||
**Current State (main.go, line ~499):**
|
||
```go
|
||
func (s *appState) addConvertToQueue() error {
|
||
if !s.hasSource() {
|
||
return fmt.Errorf("no source video selected")
|
||
}
|
||
// ... build config and add to queue
|
||
}
|
||
```
|
||
|
||
**After Integration:**
|
||
```go
|
||
func (s *appState) addConvertToQueue() error {
|
||
if !s.hasSource() {
|
||
return fmt.Errorf("no source video selected")
|
||
}
|
||
|
||
// NEW: Validate if DVD format selected
|
||
if s.convert.SelectedFormat.Ext == ".mpg" {
|
||
warnings := convert.ValidateDVDNTSC(s.source, s.convert)
|
||
|
||
// Show warnings dialog
|
||
if len(warnings) > 0 {
|
||
var warningText strings.Builder
|
||
warningText.WriteString("DVD Encoding Validation:\n\n")
|
||
for _, w := range warnings {
|
||
warningText.WriteString(fmt.Sprintf("[%s] %s\n", w.Severity, w.Message))
|
||
warningText.WriteString(fmt.Sprintf("Action: %s\n\n", w.Action))
|
||
}
|
||
|
||
dialog.ShowInformation("DVD Validation", warningText.String(), s.window)
|
||
}
|
||
}
|
||
|
||
// ... continue with queue addition
|
||
}
|
||
```
|
||
|
||
### Point 4: FFmpeg Command Building
|
||
|
||
**Current State (main.go, line ~810):**
|
||
```go
|
||
// Build FFmpeg arguments (existing complex logic)
|
||
args := []string{
|
||
"-y",
|
||
"-hide_banner",
|
||
// ... 180+ lines of filter and codec logic
|
||
}
|
||
```
|
||
|
||
**After Integration (simplified):**
|
||
```go
|
||
func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progressCallback func(float64)) error {
|
||
cfg := job.Config
|
||
inputPath := cfg["inputPath"].(string)
|
||
outputPath := cfg["outputPath"].(string)
|
||
|
||
// NEW: Use convert package for DVD
|
||
if fmt.Sprintf("%v", cfg["selectedFormat"]) == ".mpg" {
|
||
// Get video source info
|
||
src, err := convert.ProbeVideo(inputPath)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Get config from job
|
||
convertCfg := s.convert // Already validated
|
||
|
||
// Use convert package to build args
|
||
args := convert.BuildDVDFFmpegArgs(inputPath, outputPath, convertCfg, src)
|
||
|
||
// Execute FFmpeg...
|
||
return s.executeFFmpeg(args, progressCallback)
|
||
}
|
||
|
||
// Fall back to existing logic for non-DVD formats
|
||
// ... existing code
|
||
}
|
||
```
|
||
|
||
### Point 5: Job Configuration
|
||
|
||
**Updated Job Creation (main.go, line ~530):**
|
||
```go
|
||
job := &queue.Job{
|
||
Type: queue.JobTypeConvert,
|
||
Title: fmt.Sprintf("Convert: %s", s.source.DisplayName),
|
||
InputFile: s.source.Path,
|
||
OutputFile: s.convert.OutputFile(),
|
||
Config: map[string]interface{}{
|
||
// Existing fields...
|
||
"inputPath": s.source.Path,
|
||
"outputPath": s.convert.OutputFile(),
|
||
"selectedFormat": s.convert.SelectedFormat,
|
||
"videoCodec": s.convert.VideoCodec,
|
||
"audioCodec": s.convert.AudioCodec,
|
||
"videoBitrate": s.convert.VideoBitrate,
|
||
"audioBitrate": s.convert.AudioBitrate,
|
||
"targetResolution": s.convert.TargetResolution,
|
||
"frameRate": s.convert.FrameRate,
|
||
|
||
// NEW: DVD-specific info
|
||
"isDVD": s.convert.SelectedFormat.Ext == ".mpg",
|
||
"aspect": s.convert.OutputAspect,
|
||
"dvdRegion": "NTSC", // Or PAL/SECAM
|
||
},
|
||
Priority: 5,
|
||
}
|
||
s.jobQueue.Add(job)
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Type Definitions to Export
|
||
|
||
Currently in `internal/convert/types.go`, these need to remain accessible within main.go:
|
||
|
||
```go
|
||
// VideoSource - metadata about video file
|
||
type VideoSource struct { ... }
|
||
|
||
// ConvertConfig - encoding configuration
|
||
type ConvertConfig struct { ... }
|
||
|
||
// FormatOption - output format definition
|
||
type FormatOption struct { ... }
|
||
```
|
||
|
||
**Import in main.go:**
|
||
```go
|
||
import "git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
||
|
||
// Then reference as:
|
||
// convert.VideoSource
|
||
// convert.ConvertConfig
|
||
// convert.FormatOption
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Integration Checklist
|
||
|
||
- [ ] **Import convert package** in main.go
|
||
```go
|
||
import "git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
||
```
|
||
|
||
- [ ] **Update format selection**
|
||
- Replace `formatOptions` with `convert.FormatOptions`
|
||
- Add DVD option to dropdown
|
||
|
||
- [ ] **Add DVD options panel**
|
||
- Aspect ratio selector (4:3, 16:9)
|
||
- Region selector (NTSC, PAL, SECAM)
|
||
- Interlacing mode selector
|
||
|
||
- [ ] **Implement validation**
|
||
- Call `convert.ValidateDVDNTSC()` when DVD selected
|
||
- Show warnings dialog before queueing
|
||
|
||
- [ ] **Update FFmpeg execution**
|
||
- Use `convert.BuildDVDFFmpegArgs()` for .mpg files
|
||
- Keep existing logic for other formats
|
||
|
||
- [ ] **Test with sample videos**
|
||
- Generate test .mpg from AVI/MOV/MP4
|
||
- Verify DVDStyler can import without re-encoding
|
||
- Test playback on PS2 or DVD player
|
||
|
||
- [ ] **Verify queue integration**
|
||
- Create multi-video DVD job batch
|
||
- Test pause/resume with DVD jobs
|
||
- Test progress tracking
|
||
|
||
---
|
||
|
||
## 🔄 Data Flow Diagram
|
||
|
||
```
|
||
User Interface (main.go)
|
||
│
|
||
├─→ Select "DVD-NTSC (MPEG-2)" format
|
||
│ │
|
||
│ └─→ Show DVD options (aspect, region, etc.)
|
||
│
|
||
├─→ Click "Add to Queue"
|
||
│ │
|
||
│ ├─→ Call convert.ValidateDVDNTSC(video, config)
|
||
│ │ └─→ Return warnings/validation status
|
||
│ │
|
||
│ └─→ Create Job with config
|
||
│ └─→ queue.Add(job)
|
||
│
|
||
├─→ Queue displays job
|
||
│ │
|
||
│ └─→ User clicks "Start Queue"
|
||
│ │
|
||
│ ├─→ queue.Start()
|
||
│ │
|
||
│ └─→ For each job:
|
||
│ │
|
||
│ ├─→ convert.ProbeVideo(inputPath)
|
||
│ │ └─→ Return VideoSource
|
||
│ │
|
||
│ ├─→ convert.BuildDVDFFmpegArgs(...)
|
||
│ │ └─→ Return command args
|
||
│ │
|
||
│ └─→ Execute FFmpeg
|
||
│ └─→ Update job.Progress
|
||
│
|
||
└─→ Queue Viewer UI
|
||
│
|
||
└─→ Display progress
|
||
- Job status
|
||
- Progress %
|
||
- Pause/Resume buttons
|
||
- Cancel button
|
||
```
|
||
|
||
---
|
||
|
||
## 💾 Configuration Example
|
||
|
||
### Full DVD-NTSC Job Configuration
|
||
|
||
```json
|
||
{
|
||
"id": "job-dvd-001",
|
||
"type": "convert",
|
||
"title": "Convert to DVD-NTSC: movie.mp4",
|
||
"input_file": "movie.mp4",
|
||
"output_file": "movie.mpg",
|
||
"config": {
|
||
"inputPath": "movie.mp4",
|
||
"outputPath": "movie.mpg",
|
||
"selectedFormat": {
|
||
"Label": "DVD-NTSC (MPEG-2)",
|
||
"Ext": ".mpg",
|
||
"VideoCodec": "mpeg2video"
|
||
},
|
||
"isDVD": true,
|
||
"quality": "Standard (CRF 23)",
|
||
"videoCodec": "MPEG-2",
|
||
"videoBitrate": "6000k",
|
||
"targetResolution": "720x480",
|
||
"frameRate": "29.97",
|
||
"audioCodec": "AC-3",
|
||
"audioBitrate": "192k",
|
||
"audioChannels": "Stereo",
|
||
"aspect": "16:9",
|
||
"dvdRegion": "NTSC",
|
||
"dvdValidationWarnings": [
|
||
{
|
||
"severity": "info",
|
||
"message": "Input is 1920x1080, will scale to 720x480",
|
||
"action": "Will apply letterboxing to preserve 16:9 aspect"
|
||
}
|
||
]
|
||
},
|
||
"priority": 5,
|
||
"status": "pending",
|
||
"created_at": "2025-11-29T12:00:00Z"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 Quick Start Integration
|
||
|
||
### Step 1: Add Import
|
||
```go
|
||
// At top of main.go
|
||
import (
|
||
// ... existing imports
|
||
"git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
||
)
|
||
```
|
||
|
||
### Step 2: Replace Format Options
|
||
```go
|
||
// OLD (around line 1394)
|
||
var formatLabels []string
|
||
for _, opt := range formatOptions {
|
||
formatLabels = append(formatLabels, opt.Label)
|
||
}
|
||
|
||
// NEW
|
||
var formatLabels []string
|
||
for _, opt := range convert.FormatOptions {
|
||
formatLabels = append(formatLabels, opt.Label)
|
||
}
|
||
```
|
||
|
||
### Step 3: Add DVD Validation
|
||
```go
|
||
// In addConvertToQueue() function
|
||
if s.convert.SelectedFormat.Ext == ".mpg" {
|
||
warnings := convert.ValidateDVDNTSC(s.source, s.convert)
|
||
// Show warnings if any
|
||
if len(warnings) > 0 {
|
||
// Display warning dialog
|
||
}
|
||
}
|
||
```
|
||
|
||
### Step 4: Use Convert Package for FFmpeg Args
|
||
```go
|
||
// In executeConvertJob()
|
||
if s.convert.SelectedFormat.Ext == ".mpg" {
|
||
src, _ := convert.ProbeVideo(inputPath)
|
||
args := convert.BuildDVDFFmpegArgs(inputPath, outputPath, s.convert, src)
|
||
} else {
|
||
// Use existing logic for other formats
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ Verification Checklist
|
||
|
||
After integration, verify:
|
||
|
||
- [ ] **Build succeeds**: `go build .`
|
||
- [ ] **Imports resolve**: No import errors in IDE
|
||
- [ ] **Format selector shows**: "DVD-NTSC (MPEG-2)" option
|
||
- [ ] **DVD options appear**: When DVD format selected
|
||
- [ ] **Validation works**: Warnings shown for incompatible inputs
|
||
- [ ] **Queue accepts jobs**: DVD jobs can be added
|
||
- [ ] **FFmpeg executes**: Without errors
|
||
- [ ] **Progress updates**: In real-time
|
||
- [ ] **Output generated**: .mpg file created
|
||
- [ ] **DVDStyler imports**: Without re-encoding warning
|
||
- [ ] **Playback works**: On DVD player or PS2 emulator
|
||
|
||
---
|
||
|
||
## 🎯 Next Phase: Enhancement Ideas
|
||
|
||
Once integration is complete, consider:
|
||
|
||
1. **DVD Menu Support**
|
||
- Simple menu generation
|
||
- Chapter selection
|
||
- Thumbnail previews
|
||
|
||
2. **Batch Region Conversion**
|
||
- Convert same video to NTSC/PAL/SECAM in one batch
|
||
- Auto-detect region from source
|
||
|
||
3. **Preset Management**
|
||
- Save custom DVD presets
|
||
- Share presets between users
|
||
|
||
4. **Advanced Validation**
|
||
- Check minimum file size
|
||
- Estimate disc usage
|
||
- Warn about audio track count
|
||
|
||
5. **CLI Integration**
|
||
- `videotools dvd-encode input.mp4 output.mpg --region PAL`
|
||
- Batch encoding from command line
|
||
|
||
---
|
||
|
||
## 📚 Reference Documents
|
||
|
||
- **[DVD_IMPLEMENTATION_SUMMARY.md](./DVD_IMPLEMENTATION_SUMMARY.md)** - Detailed DVD feature documentation
|
||
- **[QUEUE_SYSTEM_GUIDE.md](./QUEUE_SYSTEM_GUIDE.md)** - Complete queue system reference
|
||
- **[README.md](./README.md)** - Main project overview
|
||
|
||
---
|
||
|
||
## 🆘 Troubleshooting
|
||
|
||
### Issue: "undefined: convert" in main.go
|
||
**Solution:** Add import statement at top of main.go
|
||
```go
|
||
import "git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
||
```
|
||
|
||
### Issue: formatOption not found
|
||
**Solution:** Replace with convert.FormatOption
|
||
```go
|
||
// Use:
|
||
opt := convert.FormatOption{...}
|
||
// Not:
|
||
opt := formatOption{...}
|
||
```
|
||
|
||
### Issue: ConvertConfig fields missing
|
||
**Solution:** Update main.go convertConfig to use convert.ConvertConfig
|
||
|
||
### Issue: FFmpeg command not working
|
||
**Solution:** Verify convert.BuildDVDFFmpegArgs() is called instead of manual arg building
|
||
|
||
### Issue: Queue jobs not showing progress
|
||
**Solution:** Ensure progressCallback is called in executeConvertJob
|
||
```go
|
||
progressCallback(percentComplete) // Must be called regularly
|
||
```
|
||
|
||
---
|
||
|
||
## ✨ Summary
|
||
|
||
The VideoTools project now has:
|
||
|
||
1. ✅ **Complete DVD-NTSC encoding system** (internal/convert/)
|
||
2. ✅ **Fully functional queue system** (internal/queue/)
|
||
3. ✅ **Integration points identified** (this guide)
|
||
4. ✅ **Comprehensive documentation** (multiple guides)
|
||
|
||
**Next step:** Integrate these components into main.go following this guide.
|
||
|
||
The integration is straightforward and maintains backward compatibility with existing video formats.
|