Files
gwutilz/gwencoder/docs/reference/CODEC_EXTENSIBILITY.md
2026-03-23 15:48:34 -07:00

5.4 KiB
Executable File

Codec Extensibility Architecture

Overview

The Gwencoder architecture is designed to be extensible for future codec support. The current implementation focuses on AV1, but the structure allows easy addition of other codecs (x264, VP9, HEVC, etc.) without major refactoring.

Architecture Pattern

Current Implementation (AV1)

encoding/
├── av1.go              # AV1-specific logic
│   ├── AV1AdvancedParams struct
│   ├── DefaultAV1AdvancedParams()
│   ├── BuildSVTParams()
│   ├── BuildAV1QualityArgs()
│   └── IsAV1Codec()

Pattern for Adding New Codecs

To add a new codec (e.g., x264), follow this pattern:

  1. Create codec-specific file: encoding/x264.go

  2. Define parameter struct:

type X264AdvancedParams struct {
    CRF                int    // Default: 23
    Preset             string // Default: "medium"
    Tune               string // Default: "film"
    Profile            string // Default: "high"
    Level              string // Default: "4.1"
    ForceTranscode     bool   // Default: false
    // ... other x264-specific params
}
  1. Implement default function:
func DefaultX264AdvancedParams() X264AdvancedParams {
    return X264AdvancedParams{
        CRF:            23,
        Preset:         "medium",
        Tune:           "film",
        Profile:        "high",
        Level:          "4.1",
        ForceTranscode: false,
    }
}
  1. Implement build functions:
func BuildX264Params(params X264AdvancedParams) string {
    // Build x264 parameter string
}

func BuildX264QualityArgs(params X264AdvancedParams, finalCRF int) (string, string) {
    // Build FFmpeg quality arguments
}
  1. Add codec detection:
func IsX264Codec(codec string) bool {
    codec = strings.ToLower(codec)
    return codec == "h264" || codec == "libx264"
}
  1. Integrate into main pipeline:
    • Add codec detection in encodeFile()
    • Dispatch to x264 encoding logic when detected
    • Use same audio/stream handling infrastructure

Integration Points

Main Encoding Function

The encodeFile() function uses codec detection to dispatch:

if useX264 {
    // Use x264 encoding logic
    x264Params := encoding.DefaultX264AdvancedParams()
    // ... configure x264 params
    // ... build x264 FFmpeg args
} else if useNVHEVC {
    // Use NVENC HEVC logic (existing)
} else {
    // Use AV1 encoding logic (current implementation)
    av1Params := encoding.DefaultAV1AdvancedParams()
    // ... configure AV1 params
    // ... build AV1 FFmpeg args
}

Shared Infrastructure

All codecs share:

  • Audio standardization: encoding/audio.go (codec-agnostic)
  • Stream reordering: encoding/streams.go (codec-agnostic)
  • Subtitle handling: encoding/streams.go (codec-agnostic)
  • Resolution detection: Can be shared or codec-specific

Future Codec Support

Planned Codecs (Not Yet Implemented)

  1. x264/H.264

    • File: encoding/x264.go
    • Parameters: CRF, preset, tune, profile, level
    • Uses: libx264 encoder
  2. VP9

    • File: encoding/vp9.go
    • Parameters: CRF, speed, tile-columns, etc.
    • Uses: libvpx-vp9 encoder
  3. HEVC (Software)

    • File: encoding/hevc.go
    • Parameters: CRF, preset, etc.
    • Uses: libx265 encoder

Adding a New Codec: Step-by-Step

  1. Create codec file: encoding/{codec}.go
  2. Define parameter struct with codec-specific options
  3. Implement default parameters function
  4. Implement build functions for FFmpeg arguments
  5. Add codec detection helpers
  6. Add CLI flags for codec-specific options (optional)
  7. Integrate into encodeFile() with codec detection
  8. Test with sample files

Benefits of This Architecture

  1. Modularity: Each codec is self-contained
  2. Maintainability: Easy to update codec-specific logic
  3. Extensibility: New codecs don't require refactoring existing code
  4. Shared Infrastructure: Audio/stream handling works for all codecs
  5. Consistent Interface: All codecs follow the same pattern

Example: Adding x264 Support (Future)

// encoding/x264.go
package encoding

type X264AdvancedParams struct {
    CRF            int
    Preset         string
    Tune           string
    Profile        string
    Level          string
    ForceTranscode bool
}

func DefaultX264AdvancedParams() X264AdvancedParams {
    return X264AdvancedParams{
        CRF:            23,
        Preset:         "medium",
        Tune:           "film",
        Profile:        "high",
        Level:          "4.1",
        ForceTranscode: false,
    }
}

func BuildX264Args(params X264AdvancedParams) []string {
    args := []string{
        "-c:v", "libx264",
        "-crf", strconv.Itoa(params.CRF),
        "-preset", params.Preset,
        "-tune", params.Tune,
        "-profile:v", params.Profile,
        "-level", params.Level,
    }
    return args
}

Then in main.go:

if useX264 {
    x264Params := encoding.DefaultX264AdvancedParams()
    // Configure from mode or CLI flags
    x264Args := encoding.BuildX264Args(x264Params)
    args = append(args, x264Args...)
}

Notes

  • Force Transcode: All codecs should support ForceTranscode flag
  • Codec Detection: Use GetVideoCodec() to detect input codec
  • Skip Logic: Each codec can implement its own skip logic
  • CLI Flags: Codec-specific flags should follow pattern: --{codec}-{option}