Table of Contents
- VideoTools Integration Guide - DVD Support & Queue System
- Executive Summary
- What's New
- Integration Points
- Point 1: Format Selection UI
- Point 2: DVD-Specific Options Panel
- Point 3: Validation Before Queue
- Point 4: FFmpeg Command Building
- Point 5: Job Configuration
- Type Definitions to Export
- Integration Checklist
- Data Flow Diagram
- Configuration Example
- Quick Start Integration
- Step 1: Add Import
- Step 2: Replace Format Options
- Step 3: Add DVD Validation
- Step 4: Use Convert Package for FFmpeg Args
- Verification Checklist
- Next Phase: Enhancement Ideas
- Reference Documents
- Troubleshooting
- Issue: "undefined: convert" in main.go
- Issue: formatOption not found
- Issue: ConvertConfig fields missing
- Issue: FFmpeg command not working
- Issue: Queue jobs not showing progress
- Summary
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 typesffmpeg.go- Codec mapping, video probingDVD.go- NTSC-specific encoding and validationDVD_regions.go- PAL, SECAM, and multi-region supportpresets.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):
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:
// 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):
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):
func (s *appState) addConvertToQueue() error {
if !s.hasSource() {
return fmt.Errorf("no source video selected")
}
// ... build config and add to queue
}
After Integration:
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):
// Build FFmpeg arguments (existing complex logic)
args := []string{
"-y",
"-hide_banner",
// ... 180+ lines of filter and codec logic
}
After Integration (simplified):
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):
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:
// 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:
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
import "git.leaktechnologies.dev/stu/VideoTools/internal/convert" -
Update format selection
- Replace
formatOptionswithconvert.FormatOptions - Add DVD option to dropdown
- Replace
-
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
- Call
-
Update FFmpeg execution
- Use
convert.BuildDVDFFmpegArgs()for .mpg files - Keep existing logic for other formats
- Use
-
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
{
"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
// At top of main.go
import (
// ... existing imports
"git.leaktechnologies.dev/stu/VideoTools/internal/convert"
)
Step 2: Replace Format Options
// 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
// 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
// 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:
-
DVD Menu Support [PLANNED]
- Simple menu generation
- Chapter selection
- Thumbnail previews
-
Batch Region Conversion [PLANNED]
- Convert same video to NTSC/PAL/SECAM in one batch
- Auto-detect region from source
-
Preset Management [PLANNED]
- Save custom DVD presets
- Share presets between users
-
Advanced Validation [PLANNED]
- Check minimum file size
- Estimate disc usage
- Warn about audio track count
-
CLI Integration [PLANNED]
videotools DVD-encode input.mp4 output.mpg --region PAL- Batch encoding from command line
Reference Documents
- DVD_IMPLEMENTATION_SUMMARY.md - Detailed DVD feature documentation
- QUEUE_SYSTEM_GUIDE.md - Complete queue system reference
- README.md - Main project overview
Troubleshooting
Issue: "undefined: convert" in main.go
Solution: Add import statement at top of main.go
import "git.leaktechnologies.dev/stu/VideoTools/internal/convert"
Issue: formatOption not found
Solution: Replace with convert.FormatOption
// 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
progressCallback(percentComplete) // Must be called regularly
Summary
The VideoTools project now has:
- Complete DVD-NTSC encoding system (internal/convert/)
- Fully functional queue system (internal/queue/)
- Integration points identified (this guide)
- 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.
Navigation
What is VideoTools?
Project Status
Capabilities
Codecs and Frame Rates
Installation (One Command)
Alternative: Developer Setup
DVD Workflow (Optional)
Documentation
- Project Status
- Installation
- Readme
- Build And Run
- DVD User Guide
- DVD Implementation Summary
- Integration Guide
- Queue System Guide
- Localization-Policy